diff options
Diffstat (limited to 'actionpack/test')
190 files changed, 9048 insertions, 3708 deletions
diff --git a/actionpack/test/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb index 981c023d38..62f82a4c7a 100644 --- a/actionpack/test/abstract/abstract_controller_test.rb +++ b/actionpack/test/abstract/abstract_controller_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'set' module AbstractController module Testing @@ -28,7 +29,7 @@ module AbstractController # Test Render mixin # ==== class RenderingController < AbstractController::Base - include ::AbstractController::Rendering + include AbstractController::Rendering def _prefixes [] @@ -50,7 +51,7 @@ module AbstractController end def index_to_string - self.response_body = render_to_string "index.erb" + self.response_body = render_to_string "index" end def action_with_ivars @@ -63,11 +64,11 @@ module AbstractController end def rendering_to_body - self.response_body = render_to_body :template => "naked_render.erb" + self.response_body = render_to_body :template => "naked_render" end def rendering_to_string - self.response_body = render_to_string :template => "naked_render.erb" + self.response_body = render_to_string :template => "naked_render" end end @@ -152,7 +153,7 @@ module AbstractController # ==== # self._layout is used when defined class WithLayouts < PrefixedViews - include Layouts + include AbstractController::Layouts private def self.layout(formats) @@ -178,16 +179,10 @@ module AbstractController end end - class Me5 < WithLayouts - def index - render - end - end - class TestLayouts < ActiveSupport::TestCase test "layouts are included" do controller = Me4.new - result = controller.process(:index) + controller.process(:index) assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", controller.response_body end end @@ -241,11 +236,11 @@ module AbstractController assert_dispatch ActionMissingRespondToActionController, "success", :ohai end - test "a method is available as an action if respond_to_action? returns true" do + test "a method is available as an action if method_for_action returns true" do assert_dispatch RespondToActionController, "success", :index end - test "raises ActionNotFound if method is defined but respond_to_action? returns false" do + test "raises ActionNotFound if method is defined but method_for_action returns false" do assert_raise(ActionNotFound) { RespondToActionController.new.process(:fail) } end end @@ -260,7 +255,7 @@ module AbstractController class TestActionMethodsReloading < ActiveSupport::TestCase test "action_methods should be reloaded after defining a new method" do - assert_equal ["index"], Me6.action_methods + assert_equal Set.new(["index"]), Me6.action_methods end end diff --git a/actionpack/test/abstract/callbacks_test.rb b/actionpack/test/abstract/callbacks_test.rb index 3bdde86291..5d1a703c55 100644 --- a/actionpack/test/abstract/callbacks_test.rb +++ b/actionpack/test/abstract/callbacks_test.rb @@ -131,7 +131,7 @@ module AbstractController end def authenticate - @list = [] + @list ||= [] @authenticated = "true" end end diff --git a/actionpack/test/abstract/collector_test.rb b/actionpack/test/abstract/collector_test.rb index 2ebcebbbb7..c14d24905b 100644 --- a/actionpack/test/abstract/collector_test.rb +++ b/actionpack/test/abstract/collector_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module AbstractController module Testing class MyCollector - include Collector + include AbstractController::Collector attr_accessor :responses def initialize @@ -54,4 +54,4 @@ module AbstractController end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract/helper_test.rb b/actionpack/test/abstract/helper_test.rb index b28a5b5afb..9a7445de7b 100644 --- a/actionpack/test/abstract/helper_test.rb +++ b/actionpack/test/abstract/helper_test.rb @@ -7,7 +7,7 @@ module AbstractController class ControllerWithHelpers < AbstractController::Base include AbstractController::Rendering - include Helpers + include AbstractController::Helpers def with_module render :inline => "Module <%= included_method %>" @@ -44,7 +44,7 @@ module AbstractController class AbstractHelpersBlock < ControllerWithHelpers helper do - include ::AbstractController::Testing::HelperyTest + include AbstractController::Testing::HelperyTest end end diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index 5ed6aa68b5..558a45b87f 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -14,7 +14,10 @@ module AbstractControllerTests "layouts/overwrite.erb" => "Overwrite <%= yield %>", "layouts/with_false_layout.erb" => "False Layout <%= yield %>", "abstract_controller_tests/layouts/with_string_implied_child.erb" => - "With Implied <%= yield %>" + "With Implied <%= yield %>", + "abstract_controller_tests/layouts/with_grand_child_of_implied.erb" => + "With Grand Child <%= yield %>" + )] end @@ -57,14 +60,15 @@ module AbstractControllerTests layout "hello_override" end - class WithNilChild < WithString + class WithStringImpliedChild < WithString layout nil end - class WithStringImpliedChild < WithString + class WithChildOfImplied < WithStringImpliedChild end - class WithChildOfImplied < WithStringImpliedChild + class WithGrandChildOfImplied < WithStringImpliedChild + layout nil end class WithProc < Base @@ -75,27 +79,36 @@ module AbstractControllerTests end end - class WithSymbol < Base - layout :hello + class WithZeroArityProc < Base + layout proc { "overwrite" } def index - render :template => ActionView::Template::Text.new("Hello symbol!") + render :template => ActionView::Template::Text.new("Hello zero arity proc!") end - private - def hello + end + + class WithProcInContextOfInstance < Base + def an_instance_method; end + + layout proc { + break unless respond_to? :an_instance_method "overwrite" + } + + def index + render :template => ActionView::Template::Text.new("Hello again zero arity proc!") end end - class WithSymbolReturningString < Base - layout :no_hello + class WithSymbol < Base + layout :hello def index - render :template => ActionView::Template::Text.new("Hello missing symbol!") + render :template => ActionView::Template::Text.new("Hello symbol!") end private - def no_hello - nil + def hello + "overwrite" end end @@ -153,6 +166,30 @@ module AbstractControllerTests end end + class WithOnlyConditional < WithStringImpliedChild + layout "overwrite", :only => :show + + def index + render :template => ActionView::Template::Text.new("Hello index!") + end + + def show + render :template => ActionView::Template::Text.new("Hello show!") + end + end + + class WithExceptConditional < WithStringImpliedChild + layout "overwrite", :except => :show + + def index + render :template => ActionView::Template::Text.new("Hello index!") + end + + def show + render :template => ActionView::Template::Text.new("Hello show!") + end + end + class TestBase < ActiveSupport::TestCase test "when no layout is specified, and no default is available, render without a layout" do controller = Blank.new @@ -212,6 +249,18 @@ module AbstractControllerTests assert_equal "Overwrite Hello proc!", controller.response_body end + test "when layout is specified as a proc without parameters it works just the same" do + controller = WithZeroArityProc.new + controller.process(:index) + assert_equal "Overwrite Hello zero arity proc!", controller.response_body + end + + test "when layout is specified as a proc without parameters the block is evaluated in the context of an instance" do + controller = WithProcInContextOfInstance.new + controller.process(:index) + assert_equal "Overwrite Hello again zero arity proc!", controller.response_body + end + test "when layout is specified as a symbol, call the requested method and use the layout returned" do controller = WithSymbol.new controller.process(:index) @@ -250,12 +299,6 @@ module AbstractControllerTests assert_equal "With Implied Hello string!", controller.response_body end - test "when a child controller specifies layout nil, do not use the parent layout" do - controller = WithNilChild.new - controller.process(:index) - assert_equal "Hello string!", controller.response_body - end - test "when a grandchild has no layout specified, the child has an implied layout, and the " \ "parent has specified a layout, use the child controller layout" do controller = WithChildOfImplied.new @@ -263,6 +306,13 @@ module AbstractControllerTests assert_equal "With Implied Hello string!", controller.response_body end + test "when a grandchild has nil layout specified, the child has an implied layout, and the " \ + "parent has specified a layout, use the child controller layout" do + controller = WithGrandChildOfImplied.new + controller.process(:index) + assert_equal "With Grand Child Hello string!", controller.response_body + end + test "raises an exception when specifying layout true" do assert_raises ArgumentError do Object.class_eval do @@ -272,6 +322,42 @@ module AbstractControllerTests end end end + + test "when specify an :only option which match current action name" do + controller = WithOnlyConditional.new + controller.process(:show) + assert_equal "Overwrite Hello show!", controller.response_body + end + + test "when specify an :only option which does not match current action name" do + controller = WithOnlyConditional.new + controller.process(:index) + assert_equal "With Implied Hello index!", controller.response_body + end + + test "when specify an :except option which match current action name" do + controller = WithExceptConditional.new + controller.process(:show) + assert_equal "With Implied Hello show!", controller.response_body + end + + test "when specify an :except option which does not match current action name" do + controller = WithExceptConditional.new + controller.process(:index) + assert_equal "Overwrite Hello index!", controller.response_body + end + + test "layout for anonymous controller" do + klass = Class.new(WithString) do + def index + render :text => 'index', :layout => true + end + end + + controller = klass.new + controller.process(:index) + assert_equal "With String index", controller.response_body + end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract/translation_test.rb b/actionpack/test/abstract/translation_test.rb index 8ec50fd57a..0194ee943f 100644 --- a/actionpack/test/abstract/translation_test.rb +++ b/actionpack/test/abstract/translation_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' # class TranslatingController < ActionController::Base # end -class TranslationControllerTest < Test::Unit::TestCase +class TranslationControllerTest < ActiveSupport::TestCase def setup @controller = ActionController::Base.new end @@ -23,4 +23,4 @@ class TranslationControllerTest < Test::Unit::TestCase def test_action_controller_base_responds_to_l assert_respond_to @controller, :l end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 60534a9746..ba06bcae51 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -1,11 +1,5 @@ require File.expand_path('../../../load_paths', __FILE__) -lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) - -activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__) -$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path) - $:.unshift(File.dirname(__FILE__) + '/lib') $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') $:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers') @@ -14,17 +8,14 @@ ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp') require 'active_support/core_ext/kernel/reporting' -require 'active_support/core_ext/string/encoding' -if "ruby".encoding_aware? - # These are the normal settings that will be set up by Railties - # TODO: Have these tests support other combinations of these values - silence_warnings do - Encoding.default_internal = "UTF-8" - Encoding.default_external = "UTF-8" - end +# These are the normal settings that will be set up by Railties +# TODO: Have these tests support other combinations of these values +silence_warnings do + Encoding.default_internal = "UTF-8" + Encoding.default_external = "UTF-8" end -require 'test/unit' +require 'minitest/autorun' require 'abstract_controller' require 'action_controller' require 'action_view' @@ -73,7 +64,17 @@ module RackTestUtils end module RenderERBUtils + def view + @view ||= begin + path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) + view_paths = ActionView::PathSet.new([path]) + ActionView::Base.new(view_paths) + end + end + def render_erb(string) + @virtual_path = nil + template = ActionView::Template.new( string.strip, "test template", @@ -118,11 +119,11 @@ module ActiveSupport # have been loaded. setup_once do SharedTestRoutes.draw do - match ':controller(/:action)' + get ':controller(/:action)' end ActionDispatch::IntegrationTest.app.routes.draw do - match ':controller(/:action)' + get ':controller(/:action)' end end end @@ -151,6 +152,7 @@ class BasicController config.assets_dir = public_dir config.javascripts_dir = "#{public_dir}/javascripts" config.stylesheets_dir = "#{public_dir}/stylesheets" + config.assets = ActiveSupport::InheritableOptions.new({ :prefix => "assets" }) config end end @@ -163,7 +165,8 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase def self.build_app(routes = nil) RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware| - middleware.use "ActionDispatch::ShowExceptions" + middleware.use "ActionDispatch::ShowExceptions", ActionDispatch::PublicExceptions.new("#{FIXTURE_LOAD_PATH}/public") + middleware.use "ActionDispatch::DebugExceptions" middleware.use "ActionDispatch::Callbacks" middleware.use "ActionDispatch::ParamsParser" middleware.use "ActionDispatch::Cookies" @@ -245,7 +248,7 @@ class Rack::TestCase < ActionDispatch::IntegrationTest end def assert_body(body) - assert_equal body, Array.wrap(response.body).join + assert_equal body, Array(response.body).join end def assert_status(code) @@ -253,7 +256,7 @@ class Rack::TestCase < ActionDispatch::IntegrationTest end def assert_response(body, status = 200, headers = {}) - assert_body body + assert_body body assert_status status headers.each do |header, value| assert_header header, value @@ -325,18 +328,33 @@ class Workshop end module ActionDispatch - class ShowExceptions + class DebugExceptions private - remove_method :public_path - def public_path - "#{FIXTURE_LOAD_PATH}/public" - end + remove_method :stderr_logger + # Silence logger + def stderr_logger + nil + end + end +end - remove_method :logger - # Silence logger - def logger - nil - end +module ActionDispatch + module RoutingVerbs + def get(uri_or_host, path = nil, port = nil) + host = uri_or_host.host unless path + path ||= uri_or_host.path + + params = {'PATH_INFO' => path, + 'REQUEST_METHOD' => 'GET', + 'HTTP_HOST' => host} + + routes.call(params)[2].join + end end end +module RoutingTestHelpers + def url_for(set, options, recall = nil) + set.send(:url_for, options.merge(:only_path => true, :_path_segments => recall)) + end +end diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index f0fb113860..275f25f597 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -33,8 +33,6 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest session[:foo] = "baz" head :ok end - - def rescue_action(e) raise end end def setup @@ -226,12 +224,49 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest end end + def test_incoming_invalid_session_id_via_cookie_should_be_ignored + with_test_route_set do + open_session do |sess| + sess.cookies['_session_id'] = 'INVALID' + + sess.get '/set_session_value' + new_session_id = sess.cookies['_session_id'] + assert_not_equal 'INVALID', new_session_id + + sess.get '/get_session_value' + new_session_id_2 = sess.cookies['_session_id'] + assert_equal new_session_id, new_session_id_2 + end + end + end + + def test_incoming_invalid_session_id_via_parameter_should_be_ignored + with_test_route_set(:cookie_only => false) do + open_session do |sess| + sess.get '/set_session_value', :_session_id => 'INVALID' + new_session_id = sess.cookies['_session_id'] + assert_not_equal 'INVALID', new_session_id + + sess.get '/get_session_value' + new_session_id_2 = sess.cookies['_session_id'] + assert_equal new_session_id, new_session_id_2 + end + end + end + + def test_session_store_with_all_domains + with_test_route_set(:domain => :all) do + get '/set_session_value' + assert_response :success + end + end + private def with_test_route_set(options = {}) with_routing do |set| set.draw do - match ':action', :to => 'active_record_store_test/test' + get ':action', :to => 'active_record_store_test/test' end @app = self.class.build_app(set) do |middleware| @@ -247,6 +282,7 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest session_class, ActiveRecord::SessionStore.session_class = ActiveRecord::SessionStore.session_class, "ActiveRecord::SessionStore::#{class_name.camelize}".constantize yield + ensure ActiveRecord::SessionStore.session_class = session_class end end diff --git a/actionpack/test/activerecord/controller_runtime_test.rb b/actionpack/test/activerecord/controller_runtime_test.rb index b87b9f9c47..2d789395ce 100644 --- a/actionpack/test/activerecord/controller_runtime_test.rb +++ b/actionpack/test/activerecord/controller_runtime_test.rb @@ -15,6 +15,17 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase def zero render :inline => "Zero DB runtime" end + + def redirect + Project.all + redirect_to :action => 'show' + end + + def db_after_render + render :inline => "Hello world" + Project.all + ActiveRecord::LogSubscriber.runtime += 100 + end end include ActiveSupport::LogSubscriber::TestHelper @@ -52,4 +63,19 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase assert_equal 2, @logger.logged(:info).size assert_match(/\(Views: [\d.]+ms \| ActiveRecord: 0.0ms\)/, @logger.logged(:info)[1]) end + + def test_log_with_active_record_when_redirecting + get :redirect + wait + assert_equal 3, @logger.logged(:info).size + assert_match(/\(ActiveRecord: [\d.]+ms\)/, @logger.logged(:info)[2]) + end + + def test_include_time_query_time_after_rendering + get :db_after_render + wait + + assert_equal 2, @logger.logged(:info).size + assert_match(/\(Views: [\d.]+ms \| ActiveRecord: ([1-9][\d.]+)ms\)/, @logger.logged(:info)[1]) + end end diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index f9e47d5118..90e7f4ae59 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -2,42 +2,40 @@ require 'active_record_unit' require 'fixtures/project' class Task < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end class Step < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end class Bid < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end class Tax < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end class Fax < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end class Series < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end module Blog class Post < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end class Blog < ActiveRecord::Base - set_table_name 'projects' + self.table_name = 'projects' end - def self._railtie - o = Object.new - def o.railtie_name; "blog" end - o + def self.use_relative_model_naming? + true end end @@ -87,6 +85,14 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def test_with_nil + with_test_routes do + assert_raise ArgumentError, "Nil location provided. Can't build URI." do + polymorphic_url(nil) + end + end + end + def test_with_record with_test_routes do @project.save diff --git a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb index 97be5a5bb0..409370104d 100644 --- a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb +++ b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb @@ -16,7 +16,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base end def render_with_has_many_through_association - @developer = Developer.find(:first) + @developer = Developer.first render :partial => @developer.topics end @@ -31,7 +31,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base end def render_with_record - @developer = Developer.find(:first) + @developer = Developer.first render :partial => @developer end @@ -130,14 +130,40 @@ class RenderPartialWithRecordIdentificationAndNestedControllersTest < ActiveReco def test_render_with_record_in_nested_controller get :render_with_record_in_nested_controller - assert_template 'fun/games/_game' - assert_equal 'Pong', @response.body + assert_template %r{\Afun/games/_game\Z} + assert_equal "Fun Pong\n", @response.body end def test_render_with_record_collection_in_nested_controller get :render_with_record_collection_in_nested_controller - assert_template 'fun/games/_game' - assert_equal 'PongTank', @response.body + assert_template %r{\Afun/games/_game\Z} + assert_equal "Fun Pong\nFun Tank\n", @response.body + end +end + +class RenderPartialWithRecordIdentificationAndNestedControllersWithoutPrefixTest < ActiveRecordTestCase + tests Fun::NestedController + + def test_render_with_record_in_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_in_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Pong\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config + end + + def test_render_with_record_collection_in_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_collection_in_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Pong\nJust Tank\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config end end @@ -146,13 +172,39 @@ class RenderPartialWithRecordIdentificationAndNestedDeeperControllersTest < Acti def test_render_with_record_in_deeper_nested_controller get :render_with_record_in_deeper_nested_controller - assert_template 'fun/serious/games/_game' - assert_equal 'Chess', @response.body + assert_template %r{\Afun/serious/games/_game\Z} + assert_equal "Serious Chess\n", @response.body end def test_render_with_record_collection_in_deeper_nested_controller get :render_with_record_collection_in_deeper_nested_controller - assert_template 'fun/serious/games/_game' - assert_equal 'ChessSudokuSolitaire', @response.body + assert_template %r{\Afun/serious/games/_game\Z} + assert_equal "Serious Chess\nSerious Sudoku\nSerious Solitaire\n", @response.body + end +end + +class RenderPartialWithRecordIdentificationAndNestedDeeperControllersWithoutPrefixTest < ActiveRecordTestCase + tests Fun::Serious::NestedDeeperController + + def test_render_with_record_in_deeper_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_in_deeper_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Chess\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config + end + + def test_render_with_record_collection_in_deeper_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_collection_in_deeper_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Chess\nJust Sudoku\nJust Solitaire\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config end end diff --git a/actionpack/test/assertions/response_assertions_test.rb b/actionpack/test/assertions/response_assertions_test.rb new file mode 100644 index 0000000000..ca1d58765d --- /dev/null +++ b/actionpack/test/assertions/response_assertions_test.rb @@ -0,0 +1,55 @@ +require 'abstract_unit' +require 'action_dispatch/testing/assertions/response' + +module ActionDispatch + module Assertions + class ResponseAssertionsTest < ActiveSupport::TestCase + include ResponseAssertions + + FakeResponse = Struct.new(:response_code) do + [:success, :missing, :redirect, :error].each do |sym| + define_method("#{sym}?") do + sym == response_code + end + end + end + + def test_assert_response_predicate_methods + [:success, :missing, :redirect, :error].each do |sym| + @response = FakeResponse.new sym + assert_response sym + + assert_raises(MiniTest::Assertion) { + assert_response :unauthorized + } + end + end + + def test_assert_response_fixnum + @response = FakeResponse.new 400 + assert_response 400 + + assert_raises(MiniTest::Assertion) { + assert_response :unauthorized + } + + assert_raises(MiniTest::Assertion) { + assert_response 500 + } + end + + def test_assert_response_sym_status + @response = FakeResponse.new 401 + assert_response :unauthorized + + assert_raises(MiniTest::Assertion) { + assert_response :ok + } + + assert_raises(MiniTest::Assertion) { + assert_response :success + } + end + end + end +end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 7f3d943bba..9b0d4d0f4c 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -71,6 +71,16 @@ class ActionPackAssertionsController < ActionController::Base render :text => "Hello!", :content_type => Mime::RSS end + def render_with_layout + @variable_for_layout = nil + render "test/hello_world", :layout => "layouts/standard" + end + + def render_with_layout_and_partial + @variable_for_layout = nil + render "test/hello_world_with_partial", :layout => "layouts/standard" + end + def session_stuffing session['xmas'] = 'turkey' render :text => "ho ho ho" @@ -100,9 +110,6 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base end end -class UserController < ActionController::Base -end - module Admin class InnerModuleController < ActionController::Base def index @@ -157,24 +164,10 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase assert_equal @response.body, 'request method: GET' end - def test_redirect_to_named_route - with_routing do |set| - set.draw do - match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one - match ':controller/:action' - end - set.install_helpers - - process :redirect_to_named_route - assert_redirected_to 'http://test.host/route_one' - assert_redirected_to route_one_url - end - end - def test_string_constraint with_routing do |set| set.draw do - match "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"} + get "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"} end end end @@ -182,15 +175,18 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_assert_redirect_to_named_route_failure with_routing do |set| set.draw do - match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one - match 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two - match ':controller/:action' + get 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one + get 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two + get ':controller/:action' end process :redirect_to_named_route assert_raise(ActiveSupport::TestCase::Assertion) do assert_redirected_to 'http://test.host/route_two' end assert_raise(ActiveSupport::TestCase::Assertion) do + assert_redirected_to %r(^http://test.host/route_two) + end + assert_raise(ActiveSupport::TestCase::Assertion) do assert_redirected_to :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two' end assert_raise(ActiveSupport::TestCase::Assertion) do @@ -204,8 +200,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do - match 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module - match ':controller/:action' + get 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module + get ':controller/:action' end process :redirect_to_index # redirection is <{"action"=>"index", "controller"=>"admin/admin/inner_module"}> @@ -218,12 +214,13 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do - match '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level - match ':controller/:action' + get '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level + get ':controller/:action' end process :redirect_to_top_level_named_route # assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return assert_redirected_to "/action_pack_assertions/foo" + assert_redirected_to %r(/action_pack_assertions/foo) end end @@ -233,8 +230,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do # this controller exists in the admin namespace as well which is the only difference from previous test - match '/user/:id', :to => 'user#index', :as => :top_level - match ':controller/:action' + get '/user/:id', :to => 'user#index', :as => :top_level + get ':controller/:action' end process :redirect_to_top_level_named_route # assert_redirected_to top_level_url('foo') would pass because of exact match early return @@ -350,7 +347,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase end def test_render_based_on_parameters - process :render_based_on_parameters, "name" => "David" + process :render_based_on_parameters, "GET", "name" => "David" assert_equal "Mr. David", @response.body end @@ -474,6 +471,50 @@ class AssertTemplateTest < ActionController::TestCase end end + def test_fails_with_wrong_layout + get :render_with_layout + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template :layout => "application" + end + end + + def test_fails_expecting_no_layout + get :render_with_layout + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template :layout => nil + end + end + + def test_passes_with_correct_layout + get :render_with_layout + assert_template :layout => "layouts/standard" + end + + def test_passes_with_layout_and_partial + get :render_with_layout_and_partial + assert_template :layout => "layouts/standard" + end + + def test_passed_with_no_layout + get :hello_world + assert_template :layout => nil + end + + def test_passed_with_no_layout_false + get :hello_world + assert_template :layout => false + end + + def test_passes_with_correct_layout_without_layouts_prefix + get :render_with_layout + assert_template :layout => "standard" + end + + def test_passes_with_correct_layout_symbol + get :render_with_layout + assert_template :layout => :standard + end + def test_assert_template_reset_between_requests get :hello_world assert_template 'test/hello_world' diff --git a/actionpack/test/controller/addresses_render_test.rb b/actionpack/test/controller/addresses_render_test.rb deleted file mode 100644 index c1cd22113d..0000000000 --- a/actionpack/test/controller/addresses_render_test.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'abstract_unit' -require 'logger' -require 'controller/fake_controllers' - -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 AddressesTest < ActionController::TestCase - tests AddressesController - - def setup - super - # 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.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/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index 878484eb57..3d667f0a2f 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -20,6 +20,15 @@ class AssertSelectTest < ActionController::TestCase end end + class AssertMultipartSelectMailer < ActionMailer::Base + def test(options) + mail :subject => "Test e-mail", :from => "test@test.host", :to => "test <test@test.host>" do |format| + format.text { render :text => options[:text] } + format.html { render :text => options[:html] } + end + end + end + class AssertSelectController < ActionController::Base def response_with=(content) @content = content @@ -38,10 +47,6 @@ class AssertSelectTest < ActionController::TestCase render :text=>@content, :layout=>false, :content_type=>Mime::XML @content = nil end - - def rescue_action(e) - raise e - end end tests AssertSelectController @@ -126,6 +131,13 @@ class AssertSelectTest < ActionController::TestCase assert_raise(Assertion) { assert_select "pre", :html=>text } end + def test_strip_textarea + render_html %Q{<textarea>\n\nfoo\n</textarea>} + assert_select "textarea", "\nfoo\n" + render_html %Q{<textarea>\nfoo</textarea>} + assert_select "textarea", "foo" + end + def test_counts render_html %Q{<div id="1">foo</div><div id="2">foo</div>} assert_nothing_raised { assert_select "div", 2 } @@ -313,6 +325,16 @@ EOF end end + def test_assert_select_email_multipart + AssertMultipartSelectMailer.test(:html => "<div><p>foo</p><p>bar</p></div>", :text => 'foo bar').deliver + 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 diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index 9c22a4e7e0..b9513ccff4 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'logger' +require 'active_support/logger' 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. @@ -40,35 +40,12 @@ class NonEmptyController < ActionController::Base 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 AnotherMethodMissingController < ActionController::Base - cattr_accessor :_exception - rescue_from Exception, :with => :_exception= - - protected - def method_missing(*attrs, &block) - super - end -end - class DefaultUrlOptionsController < ActionController::Base def from_view render :inline => "<%= #{params[:route]} %>" end - def default_url_options(options = nil) + def default_url_options { :host => 'www.override.com', :action => 'new', :locale => 'en' } end end @@ -79,7 +56,7 @@ class UrlOptionsController < ActionController::Base end def url_options - super.merge(:host => 'www.override.com', :action => 'new', :locale => 'en') + super.merge(:host => 'www.override.com') end end @@ -106,7 +83,7 @@ class ControllerClassTests < ActiveSupport::TestCase end end -class ControllerInstanceTests < Test::Unit::TestCase +class ControllerInstanceTests < ActiveSupport::TestCase def setup @empty = EmptyController.new @contained = Submodule::ContainedEmptyController.new @@ -116,6 +93,12 @@ class ControllerInstanceTests < Test::Unit::TestCase Submodule::ContainedNonEmptyController.new] end + def test_performed? + assert !@empty.performed? + @empty.response_body = ["sweet"] + assert @empty.performed? + end + def test_action_methods @empty_controllers.each do |c| assert_equal Set.new, c.class.action_methods, "#{c.controller_path} should be empty!" @@ -142,13 +125,11 @@ class PerformActionTest < ActionController::TestCase # 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) + @controller.logger = ActiveSupport::Logger.new(nil) @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @request.host = "www.nextangle.com" - - rescue_action_in_public! end def test_process_should_be_precise @@ -159,32 +140,10 @@ class PerformActionTest < ActionController::TestCase assert_equal exception.message, "The action 'non_existent' could not be found for EmptyController" 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_method?, 'method_missing') - - get :method_missing - assert_response :success - assert_equal 'method_missing', @response.body - end - - def test_method_missing_should_recieve_symbol - use_controller AnotherMethodMissingController - get :some_action - assert_kind_of NameError, @controller._exception - end - def test_get_on_hidden_should_fail use_controller NonEmptyController - assert_raise(ActionController::UnknownAction) { get :hidden_action } - assert_raise(ActionController::UnknownAction) { get :another_hidden_action } + assert_raise(AbstractController::ActionNotFound) { get :hidden_action } + assert_raise(AbstractController::ActionNotFound) { get :another_hidden_action } end end @@ -194,31 +153,45 @@ class UrlOptionsTest < ActionController::TestCase def setup super @request.host = 'www.example.com' - rescue_action_in_public! + end + + def test_url_for_query_params_included + rs = ActionDispatch::Routing::RouteSet.new + rs.draw do + get 'home' => 'pages#home' + end + + options = { + :action => "home", + :controller => "pages", + :only_path => true, + :params => { "token" => "secret" } + } + + assert_equal '/home?token=secret', rs.url_for(options) end def test_url_options_override with_routing do |set| set.draw do - match 'from_view', :to => 'url_options#from_view', :as => :from_view - match ':controller/:action' + get 'from_view', :to => 'url_options#from_view', :as => :from_view + get ':controller/:action' end get :from_view, :route => "from_view_url" - assert_equal 'http://www.override.com/from_view?locale=en', @response.body - assert_equal 'http://www.override.com/from_view?locale=en', @controller.send(:from_view_url) - assert_equal 'http://www.override.com/default_url_options/new?locale=en', @controller.url_for(:controller => 'default_url_options') + assert_equal 'http://www.override.com/from_view', @response.body + assert_equal 'http://www.override.com/from_view', @controller.send(:from_view_url) + assert_equal 'http://www.override.com/default_url_options/index', @controller.url_for(:controller => 'default_url_options') end end def test_url_helpers_does_not_become_actions with_routing do |set| set.draw do - match "account/overview" + get "account/overview" end - @controller.class.send(:include, set.url_helpers) assert !@controller.class.action_methods.include?("account_overview_path") end end @@ -230,14 +203,13 @@ class DefaultUrlOptionsTest < ActionController::TestCase def setup super @request.host = 'www.example.com' - rescue_action_in_public! end def test_default_url_options_override with_routing do |set| set.draw do - match 'from_view', :to => 'default_url_options#from_view', :as => :from_view - match ':controller/:action' + get 'from_view', :to => 'default_url_options#from_view', :as => :from_view + get ':controller/:action' end get :from_view, :route => "from_view_url" @@ -254,7 +226,7 @@ class DefaultUrlOptionsTest < ActionController::TestCase scope("/:locale") do resources :descriptions end - match ':controller/:action' + get ':controller/:action' end get :from_view, :route => "description_path(1)" @@ -281,7 +253,6 @@ class EmptyUrlOptionsTest < ActionController::TestCase def setup super @request.host = 'www.example.com' - rescue_action_in_public! end def test_ensure_url_for_works_as_expected_when_called_with_no_options_if_default_url_options_is_not_set diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index fada0c7748..d5afef9086 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -14,10 +14,14 @@ class CachingController < ActionController::Base end class PageCachingTestController < CachingController + self.page_cache_compression = :best_compression + caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? } caches_page :found, :not_found caches_page :about_me - + caches_page :default_gzip + caches_page :no_gzip, :gzip => false + caches_page :gzip_level, :gzip => :best_speed def ok head :ok @@ -40,6 +44,18 @@ class PageCachingTestController < CachingController cache_page("Super soaker", "/index.html") end + def default_gzip + render :text => "Text" + end + + def no_gzip + render :text => "PNG" + end + + def gzip_level + render :text => "Big text" + end + def expire_custom_path expire_page("/index.html") head :ok @@ -86,8 +102,8 @@ class PageCachingTest < ActionController::TestCase def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route with_routing do |set| set.draw do - match 'posts.:format', :to => 'posts#index', :as => :formatted_posts - match '/', :to => 'posts#index', :as => :main + get 'posts.:format', :to => 'posts#index', :as => :formatted_posts + get '/', :to => 'posts#index', :as => :main end @params[:format] = 'rss' assert_equal '/posts.rss', @routes.url_for(@params) @@ -115,6 +131,30 @@ class PageCachingTest < ActionController::TestCase assert !File.exist?("#{FILE_STORE_PATH}/index.html") end + def test_should_gzip_cache + get :custom_path + assert File.exist?("#{FILE_STORE_PATH}/index.html.gz") + + get :expire_custom_path + assert !File.exist?("#{FILE_STORE_PATH}/index.html.gz") + end + + def test_should_allow_to_disable_gzip + get :no_gzip + assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/no_gzip.html") + assert !File.exist?("#{FILE_STORE_PATH}/page_caching_test/no_gzip.html.gz") + end + + def test_should_use_config_gzip_by_default + @controller.expects(:cache_page).with(nil, nil, Zlib::BEST_COMPRESSION) + get :default_gzip + end + + def test_should_set_gzip_level + @controller.expects(:cache_page).with(nil, nil, Zlib::BEST_SPEED) + get :gzip_level + 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") @@ -127,7 +167,7 @@ class PageCachingTest < ActionController::TestCase assert_equal 'I am xml', @response.body end - def test_should_cache_with_trailing_slash_on_url + def test_cached_page_should_not_have_trailing_slash_even_if_url_has_trailing_slash @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash/' assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html") end @@ -140,8 +180,8 @@ class PageCachingTest < ActionController::TestCase end [:ok, :no_content, :found, :not_found].each do |status| - [:get, :post, :put, :delete].each do |method| - unless method == :get and status == :ok + [:get, :post, :patch, :put, :delete].each do |method| + unless method == :get && status == :ok define_method "test_shouldnt_cache_#{method}_with_#{status}_status" do send(method, status) assert_response status @@ -183,18 +223,26 @@ end class ActionCachingTestController < CachingController rescue_from(Exception) { head 500 } + rescue_from(ActionController::UnknownFormat) { head :not_acceptable } if defined? ActiveRecord rescue_from(ActiveRecord::RecordNotFound) { head :not_found } end - caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour + # Eliminate uninitialized ivar warning + before_filter { @title = nil } + + caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| c.request.format && !c.request.format.json? }, :expires_in => 1.hour 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" } caches_action :with_layout + caches_action :with_format_and_http_param, :cache_path => Proc.new { |c| { :key => 'value' } } caches_action :layout_false, :layout => false + caches_action :with_layout_proc_param, :layout => Proc.new { |c| c.params[:layout] } caches_action :record_not_found, :four_oh_four, :simple_runtime_error + caches_action :streaming + caches_action :invalid - layout 'talk_from_action.erb' + layout 'talk_from_action' def index @cache_this = MockTime.now.to_f.to_s @@ -216,6 +264,11 @@ class ActionCachingTestController < CachingController render :text => @cache_this, :layout => true end + def with_format_and_http_param + @cache_this = MockTime.now.to_f.to_s + render :text => @cache_this + end + def record_not_found raise ActiveRecord::RecordNotFound, "oops!" end @@ -232,6 +285,7 @@ class ActionCachingTestController < CachingController alias_method :edit, :index alias_method :destroy, :index alias_method :layout_false, :with_layout + alias_method :with_layout_proc_param, :with_layout def expire expire_action :controller => 'action_caching_test', :action => 'index' @@ -242,6 +296,23 @@ class ActionCachingTestController < CachingController expire_action :controller => 'action_caching_test', :action => 'index', :format => 'xml' render :nothing => true end + + def expire_with_url_string + expire_action url_for(:controller => 'action_caching_test', :action => 'index') + render :nothing => true + end + + def streaming + render :text => "streaming", :stream => true + end + + def invalid + @cache_this = MockTime.now.to_f.to_s + + respond_to do |format| + format.json{ render :json => @cache_this } + end + end end class MockTime < Time @@ -344,11 +415,40 @@ class ActionCacheTest < ActionController::TestCase get :layout_false assert_response :success assert_not_equal cached_time, @response.body - body = body_to_string(read_fragment('hostname.com/action_caching_test/layout_false')) assert_equal cached_time, body end + def test_action_cache_with_layout_and_layout_cache_false_via_proc + get :with_layout_proc_param, :layout => false + assert_response :success + cached_time = content_to_cache + assert_not_equal cached_time, @response.body + assert fragment_exist?('hostname.com/action_caching_test/with_layout_proc_param') + reset! + + get :with_layout_proc_param, :layout => false + assert_response :success + assert_not_equal cached_time, @response.body + body = body_to_string(read_fragment('hostname.com/action_caching_test/with_layout_proc_param')) + assert_equal cached_time, body + end + + def test_action_cache_with_layout_and_layout_cache_true_via_proc + get :with_layout_proc_param, :layout => true + assert_response :success + cached_time = content_to_cache + assert_not_equal cached_time, @response.body + assert fragment_exist?('hostname.com/action_caching_test/with_layout_proc_param') + reset! + + get :with_layout_proc_param, :layout => true + assert_response :success + assert_not_equal cached_time, @response.body + body = body_to_string(read_fragment('hostname.com/action_caching_test/with_layout_proc_param')) + assert_equal @response.body, body + end + def test_action_cache_conditional_options @request.env['HTTP_ACCEPT'] = 'application/json' get :index @@ -356,6 +456,13 @@ class ActionCacheTest < ActionController::TestCase assert !fragment_exist?('hostname.com/action_caching_test') end + def test_action_cache_with_format_and_http_param + get :with_format_and_http_param, :format => 'json' + assert_response :success + assert !fragment_exist?('hostname.com/action_caching_test/with_format_and_http_param.json?key=value.json') + assert fragment_exist?('hostname.com/action_caching_test/with_format_and_http_param.json?key=value') + end + def test_action_cache_with_store_options MockTime.expects(:now).returns(12345).once @controller.expects(:read_fragment).with('hostname.com/action_caching_test', :expires_in => 1.hour).once @@ -429,6 +536,21 @@ class ActionCacheTest < ActionController::TestCase assert_not_equal cached_time, @response.body end + def test_cache_expiration_with_url_string + get :index + cached_time = content_to_cache + reset! + + @request.request_uri = "/action_caching_test/expire_with_url_string" + get :expire_with_url_string + assert_response :success + reset! + + get :index + assert_response :success + assert_not_equal cached_time, @response.body + end + def test_cache_is_scoped_by_subdomain @request.host = 'jamis.hostname.com' get :index @@ -479,7 +601,7 @@ class ActionCacheTest < ActionController::TestCase def test_xml_version_of_resource_is_treated_as_different_cache with_routing do |set| set.draw do - match ':controller(/:action(.:format))' + get ':controller(/:action(.:format))' end get :index, :format => 'xml' @@ -571,6 +693,32 @@ class ActionCacheTest < ActionController::TestCase assert_response 500 end + def test_action_caching_plus_streaming + get :streaming + assert_response :success + assert_match(/streaming/, @response.body) + assert fragment_exist?('hostname.com/action_caching_test/streaming') + end + + def test_invalid_format_returns_not_acceptable + get :invalid, :format => "json" + assert_response :success + cached_time = content_to_cache + assert_equal cached_time, @response.body + + assert fragment_exist?("hostname.com/action_caching_test/invalid.json") + + get :invalid, :format => "json" + assert_response :success + assert_equal cached_time, @response.body + + get :invalid, :format => "xml" + assert_response :not_acceptable + + get :invalid, :format => "\xC3\x83" + assert_response :not_acceptable + end + private def content_to_cache assigns(:cache_this) @@ -610,8 +758,6 @@ class FragmentCachingTest < ActionController::TestCase @controller.params = @params @controller.request = @request @controller.response = @response - @controller.send(:initialize_template_class, @response) - @controller.send(:assign_shortcuts, @request, @response) end def test_fragment_cache_key @@ -719,10 +865,6 @@ class FunctionalCachingController < CachingController format.xml end end - - def rescue_action(e) - raise e - end end class FunctionalFragmentCachingTest < ActionController::TestCase @@ -742,6 +884,7 @@ class FunctionalFragmentCachingTest < ActionController::TestCase expected_body = <<-CACHED Hello This bit's fragment cached +Ciao CACHED assert_equal expected_body, @response.body @@ -783,3 +926,51 @@ CACHED assert_equal " <p>Builder</p>\n", @store.read('views/test.host/functional_caching/formatted_fragment_cached') end end + +class CacheHelperOutputBufferTest < ActionController::TestCase + + class MockController + def read_fragment(name, options) + return false + end + + def write_fragment(name, fragment, options) + fragment + end + end + + def setup + super + end + + def test_output_buffer + output_buffer = ActionView::OutputBuffer.new + controller = MockController.new + cache_helper = Object.new + cache_helper.extend(ActionView::Helpers::CacheHelper) + cache_helper.expects(:controller).returns(controller).at_least(0) + cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0) + # if the output_buffer is changed, the new one should be html_safe and of the same type + cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0) + + assert_nothing_raised do + cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + end + end + + def test_safe_buffer + output_buffer = ActiveSupport::SafeBuffer.new + controller = MockController.new + cache_helper = Object.new + cache_helper.extend(ActionView::Helpers::CacheHelper) + cache_helper.expects(:controller).returns(controller).at_least(0) + cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0) + # if the output_buffer is changed, the new one should be html_safe and of the same type + cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0) + + assert_nothing_raised do + cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + end + end + +end diff --git a/actionpack/test/controller/capture_test.rb b/actionpack/test/controller/capture_test.rb index d78acb8ce8..72263156d9 100644 --- a/actionpack/test/controller/capture_test.rb +++ b/actionpack/test/controller/capture_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'logger' +require 'active_support/logger' class CaptureController < ActionController::Base def self.controller_name; "test"; end @@ -28,8 +28,6 @@ class CaptureController < ActionController::Base def proper_block_detection @todo = "some todo" end - - def rescue_action(e) raise end end class CaptureTest < ActionController::TestCase @@ -39,7 +37,7 @@ class CaptureTest < ActionController::TestCase super # 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) + @controller.logger = ActiveSupport::Logger.new(nil) @request.host = "www.nextangle.com" end diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index b12c798302..03d5d27cf4 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -48,8 +48,6 @@ class OldContentTypeController < ActionController::Base format.rss { render :text => "hello world!", :content_type => Mime::XML } end end - - def rescue_action(e) raise end end class ContentTypeTest < ActionController::TestCase @@ -59,7 +57,7 @@ class ContentTypeTest < ActionController::TestCase super # 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) + @controller.logger = ActiveSupport::Logger.new(nil) end # :ported: @@ -70,11 +68,12 @@ class ContentTypeTest < ActionController::TestCase end def test_render_changed_charset_default - OldContentTypeController.default_charset = "utf-16" + ActionDispatch::Response.default_charset = "utf-16" get :render_defaults assert_equal "utf-16", @response.charset assert_equal Mime::HTML, @response.content_type - OldContentTypeController.default_charset = "utf-8" + ensure + ActionDispatch::Response.default_charset = "utf-8" end # :ported: @@ -106,12 +105,12 @@ class ContentTypeTest < ActionController::TestCase end def test_nil_default_for_erb - OldContentTypeController.default_charset = nil + ActionDispatch::Response.default_charset = nil get :render_default_for_erb assert_equal Mime::HTML, @response.content_type assert_nil @response.charset, @response.headers.inspect ensure - OldContentTypeController.default_charset = "utf-8" + ActionDispatch::Response.default_charset = "utf-8" end def test_default_for_erb diff --git a/actionpack/test/controller/default_url_options_with_filter_test.rb b/actionpack/test/controller/default_url_options_with_filter_test.rb new file mode 100644 index 0000000000..ef028e8cdb --- /dev/null +++ b/actionpack/test/controller/default_url_options_with_filter_test.rb @@ -0,0 +1,29 @@ +require 'abstract_unit' + + +class ControllerWithBeforeFilterAndDefaultUrlOptions < ActionController::Base + + before_filter { I18n.locale = params[:locale] } + after_filter { I18n.locale = "en" } + + def target + render :text => "final response" + end + + def redirect + redirect_to :action => "target" + end + + def default_url_options + {:locale => "de"} + end +end + +class ControllerWithBeforeFilterAndDefaultUrlOptionsTest < ActionController::TestCase + + # This test has its roots in issue #1872 + test "should redirect with correct locale :de" do + get :redirect, :locale => "de" + assert_redirected_to "/controller_with_before_filter_and_default_url_options/target?locale=de" + end +end diff --git a/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb b/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb deleted file mode 100644 index 0c02afea36..0000000000 --- a/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'abstract_unit' - -class DeprecatedBaseMethodsTest < ActionController::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 - - tests Target - - if defined? Test::Unit::Error - 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 -end diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index 9e44e8e088..ef7fbca675 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -16,7 +16,7 @@ class ActionController::Base def assigns(key = nil) assigns = {} - instance_variable_names.each do |ivar| + instance_variables.each do |ivar| next if ActionController::Base.protected_instance_variables.include?(ivar) assigns[ivar[1..-1]] = instance_variable_get(ivar) end @@ -165,8 +165,6 @@ class FilterTest < ActionController::TestCase @ran_filter ||= [] @ran_filter << "clean_up_tmp" end - - def rescue_action(e) raise(e) end end class ConditionalCollectionFilterController < ConditionalFilterController @@ -454,11 +452,6 @@ class FilterTest < ActionController::TestCase def show raise ErrorToRescue.new("Something made the bad noise.") end - - private - def rescue_action(exception) - raise exception - end end class NonYieldingAroundFilterController < ActionController::Base @@ -472,9 +465,6 @@ class FilterTest < ActionController::TestCase render :inline => "index" end - #make sure the controller complains - def rescue_action(e); raise e; end - private def filter_one @@ -520,6 +510,13 @@ class FilterTest < ActionController::TestCase end end + def test_sweeper_should_not_ignore_no_method_error + sweeper = ActionController::Caching::Sweeper.send(:new) + assert_raise NoMethodError do + sweeper.send_not_defined + end + end + def test_sweeper_should_not_block_rendering response = test_process(SweeperTestController) assert_equal 'hello world', response.body @@ -530,6 +527,11 @@ class FilterTest < ActionController::TestCase assert sweeper.before(TestController.new) end + def test_after_method_of_sweeper_should_always_return_nil + sweeper = ActionController::Caching::Sweeper.send(:new) + assert_nil sweeper.after(TestController.new) + end + def test_non_yielding_around_filters_not_returning_false_do_not_raise controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", true @@ -820,11 +822,7 @@ class FilterTest < ActionController::TestCase end end - - class PostsController < ActionController::Base - def rescue_action(e); raise e; end - module AroundExceptions class Error < StandardError ; end class Before < Error ; end @@ -946,9 +944,7 @@ class ControllerWithAllTypesOfFilters < PostsController end class ControllerWithTwoLessFilters < ControllerWithAllTypesOfFilters - $vbf = true skip_filter :around_again - $vbf = false skip_filter :after end diff --git a/actionpack/test/controller/flash_hash_test.rb b/actionpack/test/controller/flash_hash_test.rb index 9b69a2648e..ccca0dac17 100644 --- a/actionpack/test/controller/flash_hash_test.rb +++ b/actionpack/test/controller/flash_hash_test.rb @@ -75,6 +75,7 @@ module ActionDispatch def test_discard_no_args @hash['hello'] = 'world' @hash.discard + @hash.sweep assert_equal({}, @hash.to_hash) end @@ -83,8 +84,88 @@ module ActionDispatch @hash['hello'] = 'world' @hash['omg'] = 'world' @hash.discard 'hello' + @hash.sweep assert_equal({'omg' => 'world'}, @hash.to_hash) end + + def test_keep_sweep + @hash['hello'] = 'world' + + @hash.sweep + assert_equal({'hello' => 'world'}, @hash.to_hash) + end + + def test_update_sweep + @hash['hello'] = 'world' + @hash.update({'hi' => 'mom'}) + + @hash.sweep + assert_equal({'hello' => 'world', 'hi' => 'mom'}, @hash.to_hash) + end + + def test_update_delete_sweep + @hash['hello'] = 'world' + @hash.delete 'hello' + @hash.update({'hello' => 'mom'}) + + @hash.sweep + assert_equal({'hello' => 'mom'}, @hash.to_hash) + end + + def test_delete_sweep + @hash['hello'] = 'world' + @hash['hi'] = 'mom' + @hash.delete 'hi' + + @hash.sweep + assert_equal({'hello' => 'world'}, @hash.to_hash) + end + + def test_clear_sweep + @hash['hello'] = 'world' + @hash.clear + + @hash.sweep + assert_equal({}, @hash.to_hash) + end + + def test_replace_sweep + @hash['hello'] = 'world' + @hash.replace({'hi' => 'mom'}) + + @hash.sweep + assert_equal({'hi' => 'mom'}, @hash.to_hash) + end + + def test_discard_then_add + @hash['hello'] = 'world' + @hash['omg'] = 'world' + @hash.discard 'hello' + @hash['hello'] = 'world' + + @hash.sweep + assert_equal({'omg' => 'world', 'hello' => 'world'}, @hash.to_hash) + end + + def test_keep_all_sweep + @hash['hello'] = 'world' + @hash['omg'] = 'world' + @hash.discard 'hello' + @hash.keep + + @hash.sweep + assert_equal({'omg' => 'world', 'hello' => 'world'}, @hash.to_hash) + end + + def test_double_sweep + @hash['hello'] = 'world' + @hash.sweep + + assert_equal({'hello' => 'world'}, @hash.to_hash) + + @hash.sweep + assert_equal({}, @hash.to_hash) + end end end diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index e19612eace..e4b34125ad 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -51,10 +51,6 @@ class FlashTest < ActionController::TestCase render :inline => "hello" end - def rescue_action(e) - raise unless ActionView::MissingTemplate === e - end - # methods for test_sweep_after_halted_filter_chain before_filter :halt_and_redir, :only => "filter_halting_action" @@ -254,16 +250,6 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest end end - def test_setting_flash_raises_after_stream_back_to_client - with_test_route_set do - env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } - get '/set_flash', nil, env - assert_raise(ActionDispatch::ClosedError) { - @request.flash['alert'] = 'alert' - } - end - end - def test_setting_flash_does_not_raise_in_following_requests with_test_route_set do env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } @@ -280,36 +266,6 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest end end - def test_setting_flash_raises_after_stream_back_to_client_even_with_an_empty_flash - with_test_route_set do - env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } - get '/dont_set_flash', nil, env - assert_raise(ActionDispatch::ClosedError) { - @request.flash['alert'] = 'alert' - } - end - end - - def test_setting_flash_now_raises_after_stream_back_to_client - with_test_route_set do - env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } - get '/set_flash_now', nil, env - assert_raise(ActionDispatch::ClosedError) { - @request.flash.now['alert'] = 'alert' - } - end - end - - def test_setting_flash_now_raises_after_stream_back_to_client_even_with_an_empty_flash - with_test_route_set do - env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } - get '/dont_set_flash', nil, env - assert_raise(ActionDispatch::ClosedError) { - @request.flash.now['alert'] = 'alert' - } - end - end - private # Overwrite get to send SessionSecret in env hash @@ -321,7 +277,7 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match ':action', :to => FlashIntegrationTest::TestController + get ':action', :to => FlashIntegrationTest::TestController end @app = self.class.build_app(set) do |middleware| diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb index 3e723e20d9..5b423c8151 100644 --- a/actionpack/test/controller/force_ssl_test.rb +++ b/actionpack/test/controller/force_ssl_test.rb @@ -14,6 +14,10 @@ class ForceSSLControllerLevel < ForceSSLController force_ssl end +class ForceSSLCustomDomain < ForceSSLController + force_ssl :host => "secure.test.host" +end + class ForceSSLOnlyAction < ForceSSLController force_ssl :only => :cheeseburger end @@ -22,6 +26,29 @@ class ForceSSLExceptAction < ForceSSLController force_ssl :except => :banana end +class ForceSSLIfCondition < ForceSSLController + force_ssl :if => :use_force_ssl? + + def use_force_ssl? + action_name == 'cheeseburger' + end +end + +class ForceSSLFlash < ForceSSLController + force_ssl :except => [:banana, :set_flash, :use_flash] + + def set_flash + flash["that"] = "hello" + redirect_to '/force_ssl_flash/cheeseburger' + end + + def use_flash + @flash_copy = {}.update flash + @flashy = flash["that"] + render :inline => "hello" + end +end + class ForceSSLControllerLevelTest < ActionController::TestCase tests ForceSSLControllerLevel @@ -31,6 +58,12 @@ class ForceSSLControllerLevelTest < ActionController::TestCase assert_equal "https://test.host/force_ssl_controller_level/banana", redirect_to_url end + def test_banana_redirects_to_https_with_extra_params + get :banana, :token => "secret" + assert_response 301 + assert_equal "https://test.host/force_ssl_controller_level/banana?token=secret", redirect_to_url + end + def test_cheeseburger_redirects_to_https get :cheeseburger assert_response 301 @@ -38,6 +71,22 @@ class ForceSSLControllerLevelTest < ActionController::TestCase end end +class ForceSSLCustomDomainTest < ActionController::TestCase + tests ForceSSLCustomDomain + + def test_banana_redirects_to_https_with_custom_host + get :banana + assert_response 301 + assert_equal "https://secure.test.host/force_ssl_custom_domain/banana", redirect_to_url + end + + def test_cheeseburger_redirects_to_https_with_custom_host + get :cheeseburger + assert_response 301 + assert_equal "https://secure.test.host/force_ssl_custom_domain/cheeseburger", redirect_to_url + end +end + class ForceSSLOnlyActionTest < ActionController::TestCase tests ForceSSLOnlyAction @@ -68,16 +117,35 @@ class ForceSSLExceptActionTest < ActionController::TestCase end end -class ForceSSLExcludeDevelopmentTest < ActionController::TestCase - tests ForceSSLControllerLevel - - def setup - Rails.env.stubs(:development?).returns(false) - end +class ForceSSLIfConditionTest < ActionController::TestCase + tests ForceSSLIfCondition - def test_development_environment_not_redirects_to_https - Rails.env.stubs(:development?).returns(true) + def test_banana_not_redirects_to_https get :banana assert_response 200 end -end
\ No newline at end of file + + def test_cheeseburger_redirects_to_https + get :cheeseburger + assert_response 301 + assert_equal "https://test.host/force_ssl_if_condition/cheeseburger", redirect_to_url + end +end + +class ForceSSLFlashTest < ActionController::TestCase + tests ForceSSLFlash + + def test_cheeseburger_redirects_to_https + get :set_flash + assert_response 302 + assert_equal "http://test.host/force_ssl_flash/cheeseburger", redirect_to_url + + get :cheeseburger + assert_response 301 + assert_equal "https://test.host/force_ssl_flash/cheeseburger", redirect_to_url + + get :use_flash + assert_equal "hello", assigns["flash_copy"]["that"] + assert_equal "hello", assigns["flashy"] + end +end diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 9f0670ffdf..757661d8d0 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'active_support/core_ext/kernel/reporting' ActionController::Base.helpers_path = File.expand_path('../../fixtures/helpers', __FILE__) @@ -8,16 +7,12 @@ module Fun 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 @@ -61,7 +56,6 @@ class HelperTest < ActiveSupport::TestCase class TestController < ActionController::Base attr_accessor :delegate_attr def delegate_method() end - def rescue_action(e) raise end end def setup @@ -77,7 +71,7 @@ class HelperTest < ActiveSupport::TestCase self.test_helper = LocalAbcHelper end - def test_deprecated_helper + def test_helper assert_equal expected_helper_methods, missing_methods assert_nothing_raised { @controller_class.helper TestHelper } assert_equal [], missing_methods @@ -202,8 +196,6 @@ class IsolatedHelpersTest < ActiveSupport::TestCase def index render :inline => '<%= shout %>' end - - def rescue_action(e) raise end end class B < A diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb index bd3e13e6fa..7286b249c7 100644 --- a/actionpack/test/controller/http_basic_authentication_test.rb +++ b/actionpack/test/controller/http_basic_authentication_test.rb @@ -85,6 +85,14 @@ class HttpBasicAuthenticationTest < ActionController::TestCase end end + def test_encode_credentials_has_no_newline + username = 'laskjdfhalksdjfhalkjdsfhalksdjfhklsdjhalksdjfhalksdjfhlakdsjfh' + password = 'kjfhueyt9485osdfasdkljfh4lkjhakldjfhalkdsjf' + result = ActionController::HttpAuthentication::Basic.encode_credentials( + username, password) + assert_no_match(/\n/, result) + end + test "authentication request without credential" do get :display @@ -124,6 +132,6 @@ class HttpBasicAuthenticationTest < ActionController::TestCase private def encode_credentials(username, password) - "Basic #{ActiveSupport::Base64.encode64("#{username}:#{password}")}" + "Basic #{::Base64.encode64("#{username}:#{password}")}" end end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index b011536717..828ea5b0fb 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -139,7 +139,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase test "authentication request with request-uri that doesn't match credentials digest-uri" do @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') - @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/altered/uri" + @request.env['ORIGINAL_FULLPATH'] = "/http_digest_authentication_test/dummy_digest/altered/uri" get :display assert_response :unauthorized @@ -208,6 +208,44 @@ class HttpDigestAuthenticationTest < ActionController::TestCase assert !ActionController::HttpAuthentication::Digest.validate_digest_response(@request, "SuperSecret"){nil} end + test "authentication request with request-uri ending in '/'" do + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/" + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') + + # simulate normalizing PATH_INFO + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest" + get :display + + assert_response :success + assert_equal 'Definitely Maybe', @response.body + end + + test "authentication request with request-uri ending in '?'" do + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/?" + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') + + # simulate normalizing PATH_INFO + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest" + get :display + + assert_response :success + assert_equal 'Definitely Maybe', @response.body + end + + test "authentication request with absolute uri in credentials (as in IE) ending with /" do + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/" + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:uri => "http://test.host/http_digest_authentication_test/dummy_digest/", + :username => 'pretty', :password => 'please') + + # simulate normalizing PATH_INFO + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest" + get :display + + assert_response :success + assert assigns(:logged_in) + assert_equal 'Definitely Maybe', @response.body + end + private def encode_credentials(options) @@ -228,11 +266,14 @@ class HttpDigestAuthenticationTest < ActionController::TestCase credentials = decode_credentials(@response.headers['WWW-Authenticate']) credentials.merge!(options) - credentials.merge!(:uri => @request.env['PATH_INFO'].to_s) + path_info = @request.env['PATH_INFO'].to_s + uri = options[:uri] || path_info + credentials.merge!(:uri => uri) + @request.env["ORIGINAL_FULLPATH"] = path_info ActionController::HttpAuthentication::Digest.encode_credentials(method, credentials, password, options[:password_is_ha1]) end def decode_credentials(header) - ActionController::HttpAuthentication::Digest.decode_credentials(@response.headers['WWW-Authenticate']) + ActionController::HttpAuthentication::Digest.decode_credentials(header) end end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 01dc2f2091..fb41dcb33a 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'controller/fake_controllers' require 'action_controller/vendor/html-scanner' -class SessionTest < Test::Unit::TestCase +class SessionTest < ActiveSupport::TestCase StubApp = lambda { |env| [200, {"Content-Type" => "text/html", "Content-Length" => "13"}, ["Hello, World!"]] } @@ -63,6 +63,12 @@ class SessionTest < Test::Unit::TestCase @session.post_via_redirect(path, args, headers) end + def test_patch_via_redirect + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } + @session.expects(:request_via_redirect).with(:patch, path, args, headers) + @session.patch_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) @@ -87,6 +93,12 @@ class SessionTest < Test::Unit::TestCase @session.post(path,params,headers) end + def test_patch + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:patch,path,params,headers) + @session.patch(path,params,headers) + end + def test_put path = "/index"; params = "blah"; headers = {:location => 'blah'} @session.expects(:process).with(:put,path,params,headers) @@ -105,6 +117,12 @@ class SessionTest < Test::Unit::TestCase @session.head(path,params,headers) end + def test_options + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:options,path,params,headers) + @session.options(path,params,headers) + end + def test_xml_http_request_get path = "/index"; params = "blah"; headers = {:location => 'blah'} headers_after_xhr = headers.merge( @@ -125,6 +143,16 @@ class SessionTest < Test::Unit::TestCase @session.xml_http_request(:post,path,params,headers) end + def test_xml_http_request_patch + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", + "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:patch,path,params,headers_after_xhr) + @session.xml_http_request(:patch,path,params,headers) + end + def test_xml_http_request_put path = "/index"; params = "blah"; headers = {:location => 'blah'} headers_after_xhr = headers.merge( @@ -155,6 +183,16 @@ class SessionTest < Test::Unit::TestCase @session.xml_http_request(:head,path,params,headers) end + def test_xml_http_request_options + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", + "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:options,path,params,headers_after_xhr) + @session.xml_http_request(:options,path,params,headers) + end + def test_xml_http_request_override_accept path = "/index"; params = "blah"; headers = {:location => 'blah', "HTTP_ACCEPT" => "application/xml"} headers_after_xhr = headers.merge( @@ -165,7 +203,7 @@ class SessionTest < Test::Unit::TestCase end end -class IntegrationTestTest < Test::Unit::TestCase +class IntegrationTestTest < ActiveSupport::TestCase def setup @test = ::ActionDispatch::IntegrationTest.new(:app) @test.class.stubs(:fixture_table_names).returns([]) @@ -212,7 +250,7 @@ class IntegrationTestUsesCorrectClass < ActionDispatch::IntegrationTest @integration_session.stubs(:generic_url_rewriter) @integration_session.stubs(:process) - %w( get post head put delete ).each do |verb| + %w( get post head patch put delete options ).each do |verb| assert_nothing_raised("'#{verb}' should use integration test methods") { __send__(verb, '/') } end end @@ -367,6 +405,15 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end end + def test_request_with_bad_format + with_test_route_set do + xhr :get, '/get.php' + assert_equal 406, status + assert_response 406 + assert_response :not_acceptable + end + end + def test_get_with_query_string with_test_route_set do get '/get_with_params?foo=bar' @@ -428,7 +475,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end set.draw do - match ':action', :to => controller + match ':action', :to => controller, :via => [:get, :post] get 'get/:action', :to => controller end @@ -492,8 +539,10 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest end routes.draw do - match 'foo', :to => 'application_integration_test/test#index', :as => :foo - match 'bar', :to => 'application_integration_test/test#index', :as => :bar + get '', :to => 'application_integration_test/test#index', :as => :empty_string + + get 'foo', :to => 'application_integration_test/test#index', :as => :foo + get 'bar', :to => 'application_integration_test/test#index', :as => :bar end def app @@ -501,11 +550,15 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest end test "includes route helpers" do + assert_equal '/', empty_string_path assert_equal '/foo', foo_path assert_equal '/bar', bar_path end test "route helpers after controller access" do + get '/' + assert_equal '/', empty_string_path + get '/foo' assert_equal '/foo', foo_path @@ -522,11 +575,123 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest assert_raise(NameError) { missing_path } end - test "process reuse the env we pass as argument" do + test "process do not modify the env passed as argument" do env = { :SERVER_NAME => 'server', 'action_dispatch.custom' => 'custom' } + old_env = env.dup get '/foo', nil, env - assert_equal :get, env[:method] - assert_equal 'server', env[:SERVER_NAME] - assert_equal 'custom', env['action_dispatch.custom'] + assert_equal old_env, env + end +end + +class EnvironmentFilterIntegrationTest < ActionDispatch::IntegrationTest + class TestController < ActionController::Base + def post + render :text => "Created", :status => 201 + end + end + + def self.call(env) + env["action_dispatch.parameter_filter"] = [:password] + routes.call(env) + end + + def self.routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + routes.draw do + match '/post', :to => 'environment_filter_integration_test/test#post', :via => :post + end + + def app + self.class + end + + test "filters rack request form vars" do + post "/post", :username => 'cjolly', :password => 'secret' + + assert_equal 'cjolly', request.filtered_parameters['username'] + assert_equal '[FILTERED]', request.filtered_parameters['password'] + assert_equal '[FILTERED]', request.filtered_env['rack.request.form_vars'] + end +end + +class UrlOptionsIntegrationTest < ActionDispatch::IntegrationTest + class FooController < ActionController::Base + def index + render :text => "foo#index" + end + + def show + render :text => "foo#show" + end + + def edit + render :text => "foo#show" + end + end + + class BarController < ActionController::Base + def default_url_options + { :host => "bar.com" } + end + + def index + render :text => "foo#index" + end + end + + def self.routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + def self.call(env) + routes.call(env) + end + + def app + self.class + end + + routes.draw do + default_url_options :host => "foo.com" + + scope :module => "url_options_integration_test" do + get "/foo" => "foo#index", :as => :foos + get "/foo/:id" => "foo#show", :as => :foo + get "/foo/:id/edit" => "foo#edit", :as => :edit_foo + get "/bar" => "bar#index", :as => :bars + end + end + + test "session uses default url options from routes" do + assert_equal "http://foo.com/foo", foos_url + end + + test "current host overrides default url options from routes" do + get "/foo" + assert_response :success + assert_equal "http://www.example.com/foo", foos_url + end + + test "controller can override default url options from request" do + get "/bar" + assert_response :success + assert_equal "http://bar.com/foo", foos_url + end + + test "test can override default url options" do + default_url_options[:host] = "foobar.com" + assert_equal "http://foobar.com/foo", foos_url + + get "/bar" + assert_response :success + assert_equal "http://foobar.com/foo", foos_url + end + + test "current request path parameters are recalled" do + get "/foo/1" + assert_response :success + assert_equal "/foo/1/edit", url_for(:action => 'edit', :only_path => true) end end diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index cafe2b9320..c73b36f05e 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -78,8 +78,15 @@ end class DefaultLayoutController < LayoutTest end +class StreamingLayoutController < LayoutTest + def render(*args) + options = args.extract_options! || {} + super(*args, options.merge(:stream => true)) + end +end + class AbsolutePathLayoutController < LayoutTest - layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test.erb') + layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test') end class HasOwnLayoutController < LayoutTest @@ -122,6 +129,12 @@ class LayoutSetInResponseTest < ActionController::TestCase assert_template :layout => "layouts/layout_test" end + def test_layout_set_when_using_streaming_layout + @controller = StreamingLayoutController.new + get :hello + assert_template :hello + end + def test_layout_set_when_set_in_controller @controller = HasOwnLayoutController.new get :hello @@ -167,7 +180,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_is_picked_from_the_controller_instances_view_path @controller = PrependsViewPathController.new get :hello - assert_template :layout => /layouts\/alt\.\w+/ + assert_template :layout => /layouts\/alt/ end def test_absolute_pathed_layout @@ -184,7 +197,7 @@ class RenderWithTemplateOptionController < LayoutTest end class SetsNonExistentLayoutFile < LayoutTest - layout "nofile.erb" + layout "nofile" end class LayoutExceptionRaised < ActionController::TestCase diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 80c4fa2ee5..700fd788fa 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -6,6 +6,18 @@ module Another class LogSubscribersController < ActionController::Base wrap_parameters :person, :include => :name, :format => :json + class SpecialException < Exception + end + + rescue_from SpecialException do + head :status => 406 + end + + before_filter :redirector, :only => :never_executed + + def never_executed + end + def show render :nothing => true end @@ -39,6 +51,9 @@ module Another raise Exception end + def with_rescued_exception + raise SpecialException + end end end @@ -75,6 +90,13 @@ class ACLogSubscriberTest < ActionController::TestCase assert_equal "Processing by Another::LogSubscribersController#show as HTML", logs.first end + def test_halted_callback + get :never_executed + wait + assert_equal 4, logs.size + assert_equal "Filter chain halted as :redirector rendered or redirected", logs.third + end + def test_process_action get :show wait @@ -195,6 +217,14 @@ class ACLogSubscriberTest < ActionController::TestCase assert_match(/Completed 500/, logs.last) end + def test_process_action_with_rescued_exception_includes_http_status_code + get :with_rescued_exception + wait + + assert_equal 2, logs.size + assert_match(/Completed 406/, logs.last) + end + def logs @logs ||= @logger.logged(:info) end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 4a5e597500..bdcd5561a8 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -132,7 +132,6 @@ class RespondToController < ActionController::Base end end - def iphone_with_html_response_type request.format = :iphone if request.env["HTTP_ACCEPT"] == "text/iphone" @@ -151,10 +150,6 @@ class RespondToController < ActionController::Base end end - def rescue_action(e) - raise - end - protected def set_layout if action_name.in?(["all_types_with_layout", "iphone_with_html_response_type"]) @@ -212,8 +207,9 @@ class RespondToControllerTest < ActionController::TestCase get :html_or_xml assert_equal 'HTML', @response.body - get :just_xml - assert_response 406 + assert_raises(ActionController::UnknownFormat) do + get :just_xml + end end def test_all @@ -244,8 +240,10 @@ class RespondToControllerTest < ActionController::TestCase assert_equal 'HTML', @response.body @request.accept = "text/javascript, text/html" - xhr :get, :just_xml - assert_response 406 + + assert_raises(ActionController::UnknownFormat) do + xhr :get, :just_xml + end end def test_json_or_yaml_with_leading_star_star @@ -498,12 +496,18 @@ class RespondToControllerTest < ActionController::TestCase 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_invalid_format + assert_raises(ActionController::UnknownFormat) do + get :using_defaults, :format => "invalidformat" + end + end end class RespondWithController < ActionController::Base respond_to :html, :json respond_to :xml, :except => :using_resource_with_block - respond_to :js, :only => [ :using_resource_with_block, :using_resource ] + respond_to :js, :only => [ :using_resource_with_block, :using_resource, 'using_hash_resource' ] def using_resource respond_with(resource) @@ -569,11 +573,6 @@ protected def resource Customer.new("david", request.delete? ? nil : 13) end - - def _render_js(js, options) - self.content_type ||= Mime::JS - self.response_body = js.respond_to?(:to_js) ? js.to_js : js - end end class InheritedRespondWithController < RespondWithController @@ -596,6 +595,19 @@ class RenderJsonRespondWithController < RespondWithController format.json { render :json => RenderJsonTestException.new('boom') } end end + + def create + resource = ValidatedCustomer.new(params[:name], 1) + respond_with(resource) do |format| + format.json do + if resource.errors.empty? + render :json => { :valid => true } + else + render :json => { :valid => false } + end + end + end + end end class EmptyRespondWithController < ActionController::Base @@ -632,6 +644,20 @@ class RespondWithControllerTest < ActionController::TestCase end end + def test_using_resource_with_js_simply_tries_to_render_the_template + @request.accept = "text/javascript" + get :using_resource + assert_equal "text/javascript", @response.content_type + assert_equal "alert(\"Hi\");", @response.body + end + + def test_using_hash_resource_with_js_raises_an_error_if_template_cant_be_found + @request.accept = "text/javascript" + assert_raise ActionView::MissingTemplate do + get :using_hash_resource + end + end + def test_using_hash_resource @request.accept = "application/xml" get :using_hash_resource @@ -641,7 +667,16 @@ class RespondWithControllerTest < ActionController::TestCase @request.accept = "application/json" get :using_hash_resource assert_equal "application/json", @response.content_type - assert_equal %Q[{"result":{"name":"david","id":13}}], @response.body + assert @response.body.include?("result") + assert @response.body.include?('"name":"david"') + assert @response.body.include?('"id":13') + end + + def test_using_hash_resource_with_post + @request.accept = "application/json" + assert_raise ArgumentError, "Nil location provided. Can't build URI." do + post :using_hash_resource + end end def test_using_resource_with_block @@ -669,12 +704,14 @@ class RespondWithControllerTest < ActionController::TestCase def test_not_acceptable @request.accept = "application/xml" - get :using_resource_with_block - assert_equal 406, @response.status + assert_raises(ActionController::UnknownFormat) do + get :using_resource_with_block + end @request.accept = "text/javascript" - get :using_resource_with_overwrite_block - assert_equal 406, @response.status + assert_raises(ActionController::UnknownFormat) do + get :using_resource_with_overwrite_block + end end def test_using_resource_for_post_with_html_redirects_on_success @@ -723,6 +760,55 @@ class RespondWithControllerTest < ActionController::TestCase end end + def test_using_resource_for_post_with_json_yields_unprocessable_entity_on_failure + with_test_route_set do + @request.accept = "application/json" + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + post :using_resource + assert_equal "application/json", @response.content_type + assert_equal 422, @response.status + errors = {:errors => errors} + assert_equal errors.to_json, @response.body + assert_nil @response.location + end + end + + def test_using_resource_for_patch_with_html_redirects_on_success + with_test_route_set do + patch :using_resource + assert_equal "text/html", @response.content_type + assert_equal 302, @response.status + assert_equal "http://www.example.com/customers/13", @response.location + assert @response.redirect? + end + end + + def test_using_resource_for_patch_with_html_rerender_on_failure + with_test_route_set do + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + patch :using_resource + assert_equal "text/html", @response.content_type + assert_equal 200, @response.status + assert_equal "Edit world!\n", @response.body + assert_nil @response.location + end + end + + def test_using_resource_for_patch_with_html_rerender_on_failure_even_on_method_override + with_test_route_set do + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + @request.env["rack.methodoverride.original_method"] = "POST" + patch :using_resource + assert_equal "text/html", @response.content_type + assert_equal 200, @response.status + assert_equal "Edit world!\n", @response.body + assert_nil @response.location + end + end + def test_using_resource_for_put_with_html_redirects_on_success with_test_route_set do put :using_resource @@ -758,21 +844,21 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_put_with_xml_yields_ok_on_success + def test_using_resource_for_put_with_xml_yields_no_content_on_success @request.accept = "application/xml" put :using_resource assert_equal "application/xml", @response.content_type - assert_equal 200, @response.status + assert_equal 204, @response.status assert_equal " ", @response.body end - def test_using_resource_for_put_with_json_yields_ok_on_success + def test_using_resource_for_put_with_json_yields_no_content_on_success Customer.any_instance.stubs(:to_json).returns('{"name": "David"}') @request.accept = "application/json" put :using_resource assert_equal "application/json", @response.content_type - assert_equal 200, @response.status - assert_equal "{}", @response.body + assert_equal 204, @response.status + assert_equal " ", @response.body end def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure @@ -786,6 +872,18 @@ class RespondWithControllerTest < ActionController::TestCase assert_nil @response.location end + def test_using_resource_for_put_with_json_yields_unprocessable_entity_on_failure + @request.accept = "application/json" + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + put :using_resource + assert_equal "application/json", @response.content_type + assert_equal 422, @response.status + errors = {:errors => errors} + assert_equal errors.to_json, @response.body + assert_nil @response.location + end + def test_using_resource_for_delete_with_html_redirects_on_success with_test_route_set do Customer.any_instance.stubs(:destroyed?).returns(true) @@ -796,23 +894,23 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_delete_with_xml_yields_ok_on_success + def test_using_resource_for_delete_with_xml_yields_no_content_on_success Customer.any_instance.stubs(:destroyed?).returns(true) @request.accept = "application/xml" delete :using_resource assert_equal "application/xml", @response.content_type - assert_equal 200, @response.status + assert_equal 204, @response.status assert_equal " ", @response.body end - def test_using_resource_for_delete_with_json_yields_ok_on_success + def test_using_resource_for_delete_with_json_yields_no_content_on_success Customer.any_instance.stubs(:to_json).returns('{"name": "David"}') Customer.any_instance.stubs(:destroyed?).returns(true) @request.accept = "application/json" delete :using_resource assert_equal "application/json", @response.content_type - assert_equal 200, @response.status - assert_equal "{}", @response.body + assert_equal 204, @response.status + assert_equal " ", @response.body end def test_using_resource_for_delete_with_html_redirects_on_failure @@ -891,8 +989,9 @@ class RespondWithControllerTest < ActionController::TestCase def test_clear_respond_to @controller = InheritedRespondWithController.new @request.accept = "text/html" - get :index - assert_equal 406, @response.status + assert_raises(ActionController::UnknownFormat) do + get :index + end end def test_first_in_respond_to_has_higher_priority @@ -918,6 +1017,18 @@ class RespondWithControllerTest < ActionController::TestCase assert_match(/"error":"RenderJsonTestException"/, @response.body) end + def test_api_response_with_valid_resource_respect_override_block + @controller = RenderJsonRespondWithController.new + post :create, :name => "sikachu", :format => :json + assert_equal '{"valid":true}', @response.body + end + + def test_api_response_with_invalid_resource_respect_override_block + @controller = RenderJsonRespondWithController.new + post :create, :name => "david", :format => :json + assert_equal '{"valid":false}', @response.body + end + def test_no_double_render_is_raised @request.accept = "text/html" assert_raise ActionView::MissingTemplate do @@ -1013,7 +1124,7 @@ class RespondWithControllerTest < ActionController::TestCase resources :quiz_stores do resources :customers end - match ":controller/:action" + get ":controller/:action" end yield end @@ -1029,7 +1140,7 @@ class PostController < AbstractPostController around_filter :with_iphone def index - respond_to(:html, :iphone) + respond_to(:html, :iphone, :js) end protected @@ -1076,4 +1187,45 @@ class MimeControllerLayoutsTest < ActionController::TestCase get :index assert_equal '<html><div id="super_iphone">Super iPhone</div></html>', @response.body end + + def test_non_navigational_format_with_no_template_fallbacks_to_html_template_with_no_layout + get :index, :format => :js + assert_equal "Hello Firefox", @response.body + end +end + +class FlashResponder < ActionController::Responder + def initialize(controller, resources, options={}) + super + end + + def to_html + controller.flash[:notice] = 'Success' + super + end +end + +class FlashResponderController < ActionController::Base + self.responder = FlashResponder + respond_to :html + + def index + respond_with Object.new do |format| + format.html { render :text => 'HTML' } + end + end +end + +class FlashResponderControllerTest < ActionController::TestCase + tests FlashResponderController + + def test_respond_with_block_executed + get :index + assert_equal 'HTML', @response.body + end + + def test_flash_responder_executed + get :index + assert_equal 'Success', flash[:notice] + end end diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index 3ca29f1bcf..5bcd79ebec 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -23,6 +23,12 @@ module BareMetalTest assert_equal "Hello world", string end + + test "response_body value is wrapped in an array when the value is a String" do + controller = BareController.new + controller.index + assert_equal ["Hello world"], controller.response_body + end end class HeadController < ActionController::Metal @@ -31,6 +37,36 @@ module BareMetalTest def index head :not_found end + + def continue + self.content_type = "text/html" + head 100 + end + + def switching_protocols + self.content_type = "text/html" + head 101 + end + + def processing + self.content_type = "text/html" + head 102 + end + + def no_content + self.content_type = "text/html" + head 204 + end + + def reset_content + self.content_type = "text/html" + head 205 + end + + def not_modified + self.content_type = "text/html" + head 304 + end end class HeadTest < ActiveSupport::TestCase @@ -38,6 +74,42 @@ module BareMetalTest status = HeadController.action(:index).call(Rack::MockRequest.env_for("/")).first assert_equal 404, status end + + test "head :continue (100) does not return a content-type header" do + headers = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :continue (101) does not return a content-type header" do + headers = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :processing (102) does not return a content-type header" do + headers = HeadController.action(:processing).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :no_content (204) does not return a content-type header" do + headers = HeadController.action(:no_content).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :reset_content (205) does not return a content-type header" do + headers = HeadController.action(:reset_content).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :not_modified (304) does not return a content-type header" do + headers = HeadController.action(:not_modified).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end end class BareControllerTest < ActionController::TestCase diff --git a/actionpack/test/controller/new_base/base_test.rb b/actionpack/test/controller/new_base/base_test.rb index 8fa5d20372..ed244513a5 100644 --- a/actionpack/test/controller/new_base/base_test.rb +++ b/actionpack/test/controller/new_base/base_test.rb @@ -40,7 +40,7 @@ module Dispatching class ContainedEmptyController < ActionController::Base ; end class ContainedSubEmptyController < ContainedEmptyController ; end class ContainedNonDefaultPathController < ActionController::Base - def self.controller_path; "i_am_extremly_not_default"; end + def self.controller_path; "i_am_extremely_not_default"; end end end @@ -89,7 +89,7 @@ module Dispatching end test "namespaced non-default controller path" do - assert_equal 'i_am_extremly_not_default', Submodule::ContainedNonDefaultPathController.controller_path + assert_equal 'i_am_extremely_not_default', Submodule::ContainedNonDefaultPathController.controller_path assert_equal Submodule::ContainedNonDefaultPathController.controller_path, Submodule::ContainedNonDefaultPathController.new.controller_path end diff --git a/actionpack/test/controller/new_base/content_type_test.rb b/actionpack/test/controller/new_base/content_type_test.rb index 4b70031c90..9b57641e75 100644 --- a/actionpack/test/controller/new_base/content_type_test.rb +++ b/actionpack/test/controller/new_base/content_type_test.rb @@ -43,7 +43,7 @@ module ContentType test "default response is HTML and UTF8" do with_routing do |set| set.draw do - match ':controller', :action => 'index' + get ':controller', :action => 'index' end get "/content_type/base" diff --git a/actionpack/test/controller/new_base/render_file_test.rb b/actionpack/test/controller/new_base/render_file_test.rb index 8b2fdf8f96..a961cbf849 100644 --- a/actionpack/test/controller/new_base/render_file_test.rb +++ b/actionpack/test/controller/new_base/render_file_test.rb @@ -10,7 +10,7 @@ module RenderFile def with_instance_variables @secret = 'in the sauce' - render :file => File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_ivar.erb') + render :file => File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_ivar') end def without_file_key @@ -19,7 +19,7 @@ module RenderFile def without_file_key_with_instance_variable @secret = 'in the sauce' - render File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_ivar.erb') + render File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_ivar') end def relative_path @@ -34,16 +34,16 @@ module RenderFile def pathname @secret = 'in the sauce' - render :file => Pathname.new(File.dirname(__FILE__)).join(*%w[.. .. fixtures test dot.directory render_file_with_ivar.erb]) + render :file => Pathname.new(File.dirname(__FILE__)).join(*%w[.. .. fixtures test dot.directory render_file_with_ivar]) end def with_locals - path = File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_locals.erb') + path = File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_locals') render :file => path, :locals => {:secret => 'in the sauce'} end def without_file_key_with_locals - path = FIXTURES.join('test/render_file_with_locals.erb').to_s + path = FIXTURES.join('test/render_file_with_locals').to_s render path, :locals => {:secret => 'in the sauce'} end end diff --git a/actionpack/test/controller/new_base/render_layout_test.rb b/actionpack/test/controller/new_base/render_layout_test.rb index d3dcb5cad6..4ac40ca405 100644 --- a/actionpack/test/controller/new_base/render_layout_test.rb +++ b/actionpack/test/controller/new_base/render_layout_test.rb @@ -71,7 +71,8 @@ module ControllerLayouts self.view_paths = [ActionView::FixtureResolver.new( "layouts/application.html.erb" => "<html><%= yield %></html>", "controller_layouts/mismatch_format/index.xml.builder" => "xml.instruct!", - "controller_layouts/mismatch_format/implicit.builder" => "xml.instruct!" + "controller_layouts/mismatch_format/implicit.builder" => "xml.instruct!", + "controller_layouts/mismatch_format/explicit.js.erb" => "alert('foo');" )] def explicit @@ -81,7 +82,7 @@ module ControllerLayouts class MismatchFormatTest < Rack::TestCase testing ControllerLayouts::MismatchFormatController - + XML_INSTRUCT = %Q(<?xml version="1.0" encoding="UTF-8"?>\n) test "if XML is selected, an HTML template is not also selected" do @@ -94,10 +95,33 @@ module ControllerLayouts assert_response XML_INSTRUCT end - test "if an HTML template is explicitly provides for a JS template, an error is raised" do - assert_raises ActionView::MissingTemplate do - get :explicit, {}, "action_dispatch.show_exceptions" => false - end + test "a layout for JS is ignored even if explicitly provided for HTML" do + get :explicit, { :format => "js" } + assert_response "alert('foo');" + end + end + + class FalseLayoutMethodController < ::ApplicationController + self.view_paths = [ActionView::FixtureResolver.new( + "controller_layouts/false_layout_method/index.js.erb" => "alert('foo');" + )] + + layout :which_layout? + + def which_layout? + false + end + + def index + end + end + + class FalseLayoutMethodTest < Rack::TestCase + testing ControllerLayouts::FalseLayoutMethodController + + test "access false layout returned by a method/proc" do + get :index, :format => "js" + assert_response "alert('foo');" end end end diff --git a/actionpack/test/controller/new_base/render_partial_test.rb b/actionpack/test/controller/new_base/render_partial_test.rb index 83b0d039ad..b4a25c49c9 100644 --- a/actionpack/test/controller/new_base/render_partial_test.rb +++ b/actionpack/test/controller/new_base/render_partial_test.rb @@ -7,12 +7,12 @@ module RenderPartial self.view_paths = [ActionView::FixtureResolver.new( "render_partial/basic/_basic.html.erb" => "BasicPartial!", "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>", - "render_partial/basic/with_json.html.erb" => "<%= render 'with_json.json' %>", - "render_partial/basic/_with_json.json.erb" => "<%= render 'final' %>", + "render_partial/basic/with_json.html.erb" => "<%= render :partial => 'with_json', :formats => [:json] %>", + "render_partial/basic/_with_json.json.erb" => "<%= render :partial => 'final', :formats => [:json] %>", "render_partial/basic/_final.json.erb" => "{ final: json }", - "render_partial/basic/overriden.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'overriden' %><%= @test_unchanged %>", - "render_partial/basic/_overriden.html.erb" => "ParentPartial!", - "render_partial/child/_overriden.html.erb" => "OverridenPartial!" + "render_partial/basic/overriden.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'overriden' %><%= @test_unchanged %>", + "render_partial/basic/_overriden.html.erb" => "ParentPartial!", + "render_partial/child/_overriden.html.erb" => "OverridenPartial!" )] def html_with_json_inside_json diff --git a/actionpack/test/controller/new_base/render_streaming_test.rb b/actionpack/test/controller/new_base/render_streaming_test.rb index 48cf0ab9cb..bfca8c5c24 100644 --- a/actionpack/test/controller/new_base/render_streaming_test.rb +++ b/actionpack/test/controller/new_base/render_streaming_test.rb @@ -10,9 +10,9 @@ module RenderStreaming )] layout "application" - stream :only => [:hello_world, :skip] def hello_world + render :stream => true end def layout_exception @@ -73,19 +73,19 @@ module RenderStreaming test "rendering with layout exception" do get "/render_streaming/basic/layout_exception" - assert_body "d\r\n<body class=\"\r\n4e\r\n\"><script type=\"text/javascript\">window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" + assert_body "d\r\n<body class=\"\r\n37\r\n\"><script>window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" assert_streaming! end test "rendering with template exception" do get "/render_streaming/basic/template_exception" - assert_body "4e\r\n\"><script type=\"text/javascript\">window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" + assert_body "37\r\n\"><script>window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" assert_streaming! end test "rendering with template exception logs the exception" do io = StringIO.new - _old, ActionController::Base.logger = ActionController::Base.logger, Logger.new(io) + _old, ActionController::Base.logger = ActionController::Base.logger, ActiveSupport::Logger.new(io) begin get "/render_streaming/basic/template_exception" @@ -111,4 +111,4 @@ module RenderStreaming assert_equal cache, headers["Cache-Control"] end end -end if defined?(Fiber) +end diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index 584f2d772c..00c7df2af8 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -10,8 +10,8 @@ module RenderTemplate "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend", "with_raw.html.erb" => "Hello <%=raw '<strong>this is raw</strong>' %>", "with_implicit_raw.html.erb" => "Hello <%== '<strong>this is also raw</strong>' %>", - "test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>", - "test/with_json.json.erb" => "<%= render :template => 'test/final' %>", + "test/with_json.html.erb" => "<%= render :template => 'test/with_json', :formats => [:json] %>", + "test/with_json.json.erb" => "<%= render :template => 'test/final', :formats => [:json] %>", "test/final.json.erb" => "{ final: json }", "test/with_error.html.erb" => "<%= idontexist %>" )] @@ -59,6 +59,12 @@ module RenderTemplate def with_error render :template => "test/with_error" end + + private + + def show_detailed_exceptions? + request.local? + end end class TestWithoutLayout < Rack::TestCase @@ -117,7 +123,7 @@ module RenderTemplate assert_response "{ final: json }" end - test "rendering a template with error properly exceprts the code" do + test "rendering a template with error properly excerts the code" do get :with_error assert_status 500 assert_match "undefined local variable or method `idontexist'", response.body @@ -158,7 +164,7 @@ module RenderTemplate test "rendering with implicit layout" do with_routing do |set| - set.draw { match ':controller', :action => :index } + set.draw { get ':controller', :action => :index } get "/render_template/with_layout" diff --git a/actionpack/test/controller/new_base/render_test.rb b/actionpack/test/controller/new_base/render_test.rb index 60468bf5c7..cc7f12ac6d 100644 --- a/actionpack/test/controller/new_base/render_test.rb +++ b/actionpack/test/controller/new_base/render_test.rb @@ -57,7 +57,7 @@ module Render test "render with blank" do with_routing do |set| set.draw do - match ":controller", :action => 'index' + get ":controller", :action => 'index' end get "/render/blank_render" @@ -70,7 +70,7 @@ module Render test "rendering more than once raises an exception" do with_routing do |set| set.draw do - match ":controller", :action => 'index' + get ":controller", :action => 'index' end assert_raises(AbstractController::DoubleRenderError) do diff --git a/actionpack/test/controller/new_base/render_text_test.rb b/actionpack/test/controller/new_base/render_text_test.rb index 06d500cca7..f8d02e8b6c 100644 --- a/actionpack/test/controller/new_base/render_text_test.rb +++ b/actionpack/test/controller/new_base/render_text_test.rb @@ -65,9 +65,9 @@ module RenderText class RenderTextTest < Rack::TestCase describe "Rendering text using render :text" - test "rendering text from a action with default options renders the text with the layout" do + test "rendering text from an action with default options renders the text with the layout" do with_routing do |set| - set.draw { match ':controller', :action => 'index' } + set.draw { get ':controller', :action => 'index' } get "/render_text/simple" assert_body "hello david" @@ -75,9 +75,9 @@ module RenderText end end - test "rendering text from a action with default options renders the text without the layout" do + test "rendering text from an action with default options renders the text without the layout" do with_routing do |set| - set.draw { match ':controller', :action => 'index' } + set.draw { get ':controller', :action => 'index' } get "/render_text/with_layout" diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index 7bef1e8d5d..5b05f77045 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -37,6 +37,14 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.last_parameters = nil end + def test_filtered_parameters + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu' } + assert_equal @request.filtered_parameters, { 'controller' => 'params_wrapper_test/users', 'action' => 'parse', 'username' => 'sikachu', 'user' => { 'username' => 'sikachu' } } + end + end + def test_derived_name_from_controller with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' @@ -147,6 +155,7 @@ class ParamsWrapperTest < ActionController::TestCase end def test_derived_wrapped_keys_from_matching_model + User.expects(:respond_to?).with(:accessible_attributes).returns(false) User.expects(:respond_to?).with(:attribute_names).returns(true) User.expects(:attribute_names).twice.returns(["username"]) @@ -159,6 +168,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_derived_wrapped_keys_from_specified_model with_default_wrapper_options do + Person.expects(:respond_to?).with(:accessible_attributes).returns(false) Person.expects(:respond_to?).with(:attribute_names).returns(true) Person.expects(:attribute_names).twice.returns(["username"]) @@ -169,8 +179,46 @@ class ParamsWrapperTest < ActionController::TestCase assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) end end + + def test_accessible_wrapped_keys_from_matching_model + User.expects(:respond_to?).with(:accessible_attributes).returns(true) + User.expects(:accessible_attributes).with(:default).twice.returns(["username"]) + + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) + end + end + + def test_accessible_wrapped_keys_from_specified_model + with_default_wrapper_options do + Person.expects(:respond_to?).with(:accessible_attributes).returns(true) + Person.expects(:accessible_attributes).with(:default).twice.returns(["username"]) + + UsersController.wrap_parameters Person + + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) + end + end + + def test_accessible_wrapped_keys_with_role_from_specified_model + with_default_wrapper_options do + Person.expects(:respond_to?).with(:accessible_attributes).returns(true) + Person.expects(:accessible_attributes).with(:admin).twice.returns(["username"]) + + UsersController.wrap_parameters Person, :as => :admin + + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) + end + end def test_not_wrapping_abstract_model + User.expects(:respond_to?).with(:accessible_attributes).returns(false) User.expects(:respond_to?).with(:attribute_names).returns(true) User.expects(:attribute_names).returns([]) @@ -285,3 +333,38 @@ class AnonymousControllerParamsWrapperTest < ActionController::TestCase end end end + +class IrregularInflectionParamsWrapperTest < ActionController::TestCase + include ParamsWrapperTestHelp + + class ParamswrappernewsItem + def self.attribute_names + ['test_attr'] + end + end + + class ParamswrappernewsController < ActionController::Base + class << self + attr_accessor :last_parameters + end + + def parse + self.class.last_parameters = request.params.except(:controller, :action) + head :ok + end + end + + tests ParamswrappernewsController + + def test_uses_model_attribute_names_with_irregular_inflection + ActiveSupport::Inflector.inflections do |inflect| + inflect.irregular 'paramswrappernews_item', 'paramswrappernews' + end + + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu', 'test_attr' => 'test_value' } + assert_parameters({ 'username' => 'sikachu', 'test_attr' => 'test_value', 'paramswrappernews_item' => { 'test_attr' => 'test_value' }}) + end + end +end diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb index f3e5ff8a47..eb38b81e85 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/controller/record_identifier_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'controller/fake_models' -class RecordIdentifierTest < Test::Unit::TestCase +class RecordIdentifierTest < ActiveSupport::TestCase include ActionController::RecordIdentifier def setup diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 92d4a6d98b..4331333b98 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -4,6 +4,11 @@ class WorkshopsController < ActionController::Base end class RedirectController < ActionController::Base + # empty method not used anywhere to ensure methods like + # `status` and `location` aren't called on `redirect_to` calls + def status; render :text => 'called status'; end + def location; render :text => 'called location'; end + def simple_redirect redirect_to :action => "hello_world" end @@ -65,6 +70,10 @@ class RedirectController < ActionController::Base redirect_to "x-test+scheme.complex:redirect" end + def redirect_to_url_with_network_path_reference + redirect_to "//www.rubyonrails.org/" + end + def redirect_to_back redirect_to :back end @@ -94,9 +103,15 @@ class RedirectController < ActionController::Base redirect_to proc { {:action => "hello_world"} } end - def rescue_errors(e) raise e end + def redirect_with_header_break + redirect_to "/lol\r\nwat" + end - def rescue_action(e) raise end + def redirect_with_null_bytes + redirect_to "\000/lol\r\nwat" + end + + def rescue_errors(e) raise e end protected def dashbord_url(id, message) @@ -113,6 +128,18 @@ class RedirectTest < ActionController::TestCase assert_equal "http://test.host/redirect/hello_world", redirect_to_url end + def test_redirect_with_header_break + get :redirect_with_header_break + assert_response :redirect + assert_equal "http://test.host/lolwat", redirect_to_url + end + + def test_redirect_with_null_bytes + get :redirect_with_null_bytes + assert_response :redirect + assert_equal "http://test.host/lolwat", redirect_to_url + end + def test_redirect_with_no_status get :simple_redirect assert_response 302 @@ -211,6 +238,12 @@ class RedirectTest < ActionController::TestCase assert_equal "x-test+scheme.complex:redirect", redirect_to_url end + def test_redirect_to_url_with_network_path_reference + get :redirect_to_url_with_network_path_reference + assert_response :redirect + assert_equal "//www.rubyonrails.org/", redirect_to_url + end + def test_redirect_to_back @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from" get :redirect_to_back @@ -229,7 +262,7 @@ class RedirectTest < ActionController::TestCase with_routing do |set| set.draw do resources :workshops - match ':controller/:action' + get ':controller/:action' end get :redirect_to_existing_record @@ -263,7 +296,7 @@ class RedirectTest < ActionController::TestCase def test_redirect_to_with_block_and_accepted_options with_routing do |set| set.draw do - match ':controller/:action' + get ':controller/:action' end get :redirect_to_with_block_and_options diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index fc604a2db3..7c0a6bd67e 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'controller/fake_models' +require 'active_support/logger' require 'pathname' class RenderJsonTest < ActionController::TestCase @@ -69,7 +70,7 @@ class RenderJsonTest < ActionController::TestCase # 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". super - @controller.logger = Logger.new(nil) + @controller.logger = ActiveSupport::Logger.new(nil) @request.host = "www.nextangle.com" end @@ -101,7 +102,7 @@ class RenderJsonTest < ActionController::TestCase 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 + assert_equal 'text/javascript', @response.content_type end def test_render_json_with_custom_content_type diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index e62f3155c5..3d58c02338 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -9,7 +9,15 @@ module Fun end def nested_partial_with_form_builder - render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {}, Proc.new {}) + render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {}) + end + end +end + +module Quiz + class QuestionsController < ActionController::Base + def new + render :partial => Quiz::Question.new("Namespaced Partial") end end end @@ -17,6 +25,8 @@ end class TestController < ActionController::Base protect_from_forgery + before_filter :set_variable_for_layout + class LabellingFormBuilder < ActionView::Helpers::FormBuilder end @@ -33,7 +43,7 @@ class TestController < ActionController::Base end def hello_world_file - render :file => File.expand_path("../../fixtures/hello.html", __FILE__) + render :file => File.expand_path("../../fixtures/hello", __FILE__), :formats => [:html] end def conditional_hello @@ -42,12 +52,28 @@ class TestController < ActionController::Base end end + def conditional_hello_with_record + record = Struct.new(:updated_at, :cache_key).new(Time.now.utc.beginning_of_day, "foo/123") + + if stale?(record) + render :action => 'hello_world' + end + end + def conditional_hello_with_public_header if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) render :action => 'hello_world' end end + def conditional_hello_with_public_header_with_record + record = Struct.new(:updated_at, :cache_key).new(Time.now.utc.beginning_of_day, "foo/123") + + if stale?(record, :public => true) + render :action => 'hello_world' + end + end + def conditional_hello_with_public_header_and_expires_at expires_in 1.minute if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) @@ -65,13 +91,23 @@ class TestController < ActionController::Base render :action => 'hello_world' end + def conditional_hello_with_expires_in_with_must_revalidate + expires_in 1.minute, :must_revalidate => true + render :action => 'hello_world' + end + + def conditional_hello_with_expires_in_with_public_and_must_revalidate + expires_in 1.minute, :public => true, :must_revalidate => true + render :action => 'hello_world' + end + def conditional_hello_with_expires_in_with_public_with_more_keys - expires_in 1.minute, :public => true, 'max-stale' => 5.hours + expires_in 1.minute, :public => true, 's-maxage' => 5.hours render :action => 'hello_world' end def conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax - expires_in 1.minute, :public => true, :private => nil, 'max-stale' => 5.hours + expires_in 1.minute, :public => true, :private => nil, 's-maxage' => 5.hours render :action => 'hello_world' end @@ -155,14 +191,14 @@ class TestController < ActionController::Base # :ported: def render_file_with_instance_variables @secret = 'in the sauce' - path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb') + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar') render :file => path end # :ported: def render_file_as_string_with_instance_variables @secret = 'in the sauce' - path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')) + path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar')) render path end @@ -179,21 +215,21 @@ class TestController < ActionController::Base def render_file_using_pathname @secret = 'in the sauce' - render :file => Pathname.new(File.dirname(__FILE__)).join('..', 'fixtures', 'test', 'dot.directory', 'render_file_with_ivar.erb') + render :file => Pathname.new(File.dirname(__FILE__)).join('..', 'fixtures', 'test', 'dot.directory', 'render_file_with_ivar') end def render_file_from_template @secret = 'in the sauce' - @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')) + @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar')) end def render_file_with_locals - path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb') + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals') render :file => path, :locals => {:secret => 'in the sauce'} end def render_file_as_string_with_locals - path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb')) + path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals')) render path, :locals => {:secret => 'in the sauce'} end @@ -340,17 +376,14 @@ class TestController < ActionController::Base end def layout_test_with_different_layout - @variable_for_layout = nil render :action => "hello_world", :layout => "standard" end def layout_test_with_different_layout_and_string_action - @variable_for_layout = nil render "hello_world", :layout => "standard" end def layout_test_with_different_layout_and_symbol_action - @variable_for_layout = nil render :hello_world, :layout => "standard" end @@ -359,7 +392,6 @@ class TestController < ActionController::Base end def layout_overriding_layout - @variable_for_layout = nil render :action => "hello_world", :layout => "standard" end @@ -397,6 +429,14 @@ class TestController < ActionController::Base render :template => "test/hello_world" end + def render_with_explicit_unescaped_template + render :template => "test/h*llo_world" + end + + def render_with_explicit_escaped_template + render :template => "test/hello,world" + end + def render_with_explicit_string_template render "test/hello_world" end @@ -437,17 +477,13 @@ class TestController < ActionController::Base render :action => "potential_conflicts" end - # :deprecated: - # Tests being able to pick a .builder template over a .erb - # For instance, being able to have hello.xml.builder and hello.xml.erb - # and select one via "hello.builder" or "hello.erb" def hello_world_from_rxml_using_action - render :action => "hello_world_from_rxml.builder" + render :action => "hello_world_from_rxml", :handlers => [:builder] end # :deprecated: def hello_world_from_rxml_using_template - render :template => "test/hello_world_from_rxml.builder" + render :template => "test/hello_world_from_rxml", :handlers => [:builder] end def action_talk_to_layout @@ -469,6 +505,14 @@ class TestController < ActionController::Base render :text => "hello world!" end + def head_created + head :created + end + + def head_created_with_application_json_content_type + head :created, :content_type => "application/json" + end + def head_with_location_header head :location => "/foo" end @@ -509,20 +553,41 @@ class TestController < ActionController::Base render :action => "using_layout_around_block", :layout => "layouts/block_with_layout" end - def partial_dot_html - render :partial => 'partial.html.erb' + def partial_formats_html + render :partial => 'partial', :formats => [:html] end def partial render :partial => 'partial' end + def partial_html_erb + render :partial => 'partial_html_erb' + 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 :template => "test/hello_world" end + def render_to_string_with_template_and_html_partial + @text = render_to_string :template => "test/with_partial", :formats => [:text] + @html = render_to_string :template => "test/with_partial", :formats => [:html] + render :template => "test/with_html_partial" + end + + def render_to_string_and_render_with_different_formats + @html = render_to_string :template => "test/with_partial", :formats => [:html] + render :template => "test/with_partial", :formats => [:text] + end + + def render_template_within_a_template_with_other_format + render :template => "test/with_xml_template", + :formats => [:html], + :layout => "with_html_partial" + end + def partial_with_counter render :partial => "counter", :locals => { :counter_counter => 5 } end @@ -532,11 +597,11 @@ class TestController < ActionController::Base end def partial_with_form_builder - render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {}, Proc.new {}) + render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {}) end def partial_with_form_builder_subclass - render :partial => LabellingFormBuilder.new(:post, nil, view_context, {}, Proc.new {}) + render :partial => LabellingFormBuilder.new(:post, nil, view_context, {}) end def partial_collection @@ -623,10 +688,6 @@ class TestController < ActionController::Base render :action => "calling_partial_with_layout", :layout => "layouts/partial_with_layout" end - def rescue_action(e) - raise - end - before_filter :only => :render_with_filters do request.format = :xml end @@ -638,8 +699,11 @@ class TestController < ActionController::Base private + def set_variable_for_layout + @variable_for_layout = nil + end + def determine_layout - @variable_for_layout ||= nil case action_name when "hello_world", "layout_test", "rendering_without_layout", "rendering_nothing_on_layout", "render_text_hello_world", @@ -667,7 +731,8 @@ class RenderTest < ActionController::TestCase # 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". super - @controller.logger = Logger.new(nil) + @controller.logger = ActiveSupport::Logger.new(nil) + ActionView::Base.logger = ActiveSupport::Logger.new(nil) @request.host = "www.nextangle.com" end @@ -862,12 +927,12 @@ class RenderTest < ActionController::TestCase # :ported: def test_attempt_to_access_object_method - assert_raise(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } + assert_raise(AbstractController::ActionNotFound, "No action responded to [clone]") { get :clone } end # :ported: def test_private_methods - assert_raise(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } + assert_raise(AbstractController::ActionNotFound, "No action responded to [determine_layout]") { get :determine_layout } end # :ported: @@ -878,7 +943,7 @@ class RenderTest < ActionController::TestCase def test_access_to_logger_in_view get :accessing_logger_in_template - assert_equal "Logger", @response.body + assert_equal "ActiveSupport::Logger", @response.body end # :ported: @@ -965,6 +1030,7 @@ class RenderTest < ActionController::TestCase 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 + assert_equal "text/html", @response.content_type end def test_should_implicitly_render_html_template_from_xhr_request @@ -1023,11 +1089,6 @@ class RenderTest < ActionController::TestCase assert_equal " ", @response.body end - def test_render_to_string_not_deprecated - 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) @@ -1054,6 +1115,12 @@ class RenderTest < ActionController::TestCase assert_response :success end + def test_render_with_explicit_unescaped_template + assert_raise(ActionView::MissingTemplate) { get :render_with_explicit_unescaped_template } + get :render_with_explicit_escaped_template + assert_equal "Hello w*rld!", @response.body + end + def test_render_with_explicit_string_template get :render_with_explicit_string_template assert_equal "<html>Hello world!</html>", @response.body @@ -1066,15 +1133,15 @@ class RenderTest < ActionController::TestCase # :ported: def test_double_render - assert_raise(ActionController::DoubleRenderError) { get :double_render } + assert_raise(AbstractController::DoubleRenderError) { get :double_render } end def test_double_redirect - assert_raise(ActionController::DoubleRenderError) { get :double_redirect } + assert_raise(AbstractController::DoubleRenderError) { get :double_redirect } end def test_render_and_redirect - assert_raise(ActionController::DoubleRenderError) { get :render_and_redirect } + assert_raise(AbstractController::DoubleRenderError) { get :render_and_redirect } end # specify the one exception to double render rule - render_to_string followed by render @@ -1106,7 +1173,7 @@ class RenderTest < ActionController::TestCase end def test_yield_content_for - assert_not_deprecated { get :yield_content_for } + get :yield_content_for assert_equal "<title>Putting stuff in the title!</title>\nGreat stuff!\n", @response.body end @@ -1118,6 +1185,19 @@ class RenderTest < ActionController::TestCase assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body end + def test_head_created + post :head_created + assert_blank @response.body + assert_response :created + end + + def test_head_created_with_application_json_content_type + post :head_created_with_application_json_content_type + assert_blank @response.body + assert_equal "application/json", @response.content_type + assert_response :created + end + def test_head_with_location_header get :head_with_location_header assert_blank @response.body @@ -1129,7 +1209,7 @@ class RenderTest < ActionController::TestCase with_routing do |set| set.draw do resources :customers - match ':controller/:action' + get ':controller/:action' end get :head_with_location_object @@ -1209,22 +1289,57 @@ class RenderTest < ActionController::TestCase def test_partial_only get :partial_only assert_equal "only partial", @response.body + assert_equal "text/html", @response.content_type end def test_should_render_html_formatted_partial get :partial - assert_equal 'partial html', @response.body + assert_equal "partial html", @response.body + assert_equal "text/html", @response.content_type end - def test_should_render_html_partial_with_dot - get :partial_dot_html - assert_equal 'partial html', @response.body + def test_render_html_formatted_partial_even_with_other_mime_time_in_accept + @request.accept = "text/javascript, text/html" + + get :partial_html_erb + + assert_equal "partial.html.erb", @response.body.strip + assert_equal "text/html", @response.content_type + end + + def test_should_render_html_partial_with_formats + get :partial_formats_html + assert_equal "partial html", @response.body + assert_equal "text/html", @response.content_type 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) + assert_equal "text/html", @response.content_type + end + + def test_render_to_string_with_template_and_html_partial + get :render_to_string_with_template_and_html_partial + assert_equal "**only partial**\n", assigns(:text) + assert_equal "<strong>only partial</strong>\n", assigns(:html) + assert_equal "<strong>only html partial</strong>\n", @response.body + assert_equal "text/html", @response.content_type + end + + def test_render_to_string_and_render_with_different_formats + get :render_to_string_and_render_with_different_formats + assert_equal "<strong>only partial</strong>\n", assigns(:html) + assert_equal "**only partial**\n", @response.body + assert_equal "text/plain", @response.content_type + end + + def test_render_template_within_a_template_with_other_format + get :render_template_within_a_template_with_other_format + expected = "only html partial<p>This is grand!</p>" + assert_equal expected, @response.body.strip + assert_equal "text/html", @response.content_type end def test_partial_with_counter @@ -1256,6 +1371,12 @@ class RenderTest < ActionController::TestCase assert_template('fun/games/_form') end + def test_namespaced_object_partial + @controller = Quiz::QuestionsController.new + get :new + assert_equal "Namespaced Partial", @response.body + end + def test_partial_collection get :partial_collection assert_equal "Hello: davidHello: mary", @response.body @@ -1366,20 +1487,37 @@ class ExpiresInRenderTest < ActionController::TestCase assert_equal "max-age=60, public", @response.headers["Cache-Control"] end + def test_expires_in_header_with_must_revalidate + get :conditional_hello_with_expires_in_with_must_revalidate + assert_equal "max-age=60, private, must-revalidate", @response.headers["Cache-Control"] + end + + def test_expires_in_header_with_public_and_must_revalidate + get :conditional_hello_with_expires_in_with_public_and_must_revalidate + assert_equal "max-age=60, public, must-revalidate", @response.headers["Cache-Control"] + end + def test_expires_in_header_with_additional_headers get :conditional_hello_with_expires_in_with_public_with_more_keys - assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] + assert_equal "max-age=60, public, s-maxage=18000", @response.headers["Cache-Control"] end def test_expires_in_old_syntax get :conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax - assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] + assert_equal "max-age=60, public, s-maxage=18000", @response.headers["Cache-Control"] end def test_expires_now get :conditional_hello_with_expires_now assert_equal "no-cache", @response.headers["Cache-Control"] end + + def test_date_header_when_expires_in + time = Time.mktime(2011,10,30) + Time.stubs(:now).returns(time) + get :conditional_hello_with_expires_in + assert_equal Time.now.httpdate, @response.headers["Date"] + end end class LastModifiedRenderTest < ActionController::TestCase @@ -1419,6 +1557,36 @@ class LastModifiedRenderTest < ActionController::TestCase assert_equal @last_modified, @response.headers['Last-Modified'] end + + def test_responds_with_last_modified_with_record + get :conditional_hello_with_record + assert_equal @last_modified, @response.headers['Last-Modified'] + end + + def test_request_not_modified_with_record + @request.if_modified_since = @last_modified + get :conditional_hello_with_record + assert_equal 304, @response.status.to_i + assert_blank @response.body + assert_equal @last_modified, @response.headers['Last-Modified'] + end + + def test_request_not_modified_but_etag_differs_with_record + @request.if_modified_since = @last_modified + @request.if_none_match = "234" + get :conditional_hello_with_record + assert_response :success + end + + def test_request_modified_with_record + @request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT' + get :conditional_hello_with_record + assert_equal 200, @response.status.to_i + assert_present @response.body + assert_equal @last_modified, @response.headers['Last-Modified'] + end + + def test_request_with_bang_gets_last_modified get :conditional_hello_with_bangs assert_equal @last_modified, @response.headers['Last-Modified'] diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index ec4dc848ff..4f280c4bec 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -48,7 +48,7 @@ class RenderXmlTest < ActionController::TestCase # 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". super - @controller.logger = Logger.new(nil) + @controller.logger = ActiveSupport::Logger.new(nil) @request.host = "www.nextangle.com" end @@ -72,7 +72,7 @@ class RenderXmlTest < ActionController::TestCase with_routing do |set| set.draw do resources :customers - match ':controller/:action' + get ':controller/:action' end get :render_with_object_location diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index dea80ed887..066cd523be 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' require 'digest/sha1' -require 'active_support/core_ext/string/strip' +require "active_support/log_subscriber/test_helper" # common controller actions module RequestForgeryProtectionActions @@ -36,6 +36,22 @@ module RequestForgeryProtectionActions render :inline => "<%= form_for(:some_resource, :authenticity_token => false ) {} %>" end + def form_for_remote + render :inline => "<%= form_for(:some_resource, :remote => true ) {} %>" + end + + def form_for_remote_with_token + render :inline => "<%= form_for(:some_resource, :remote => true, :authenticity_token => true ) {} %>" + end + + def form_for_with_token + render :inline => "<%= form_for(:some_resource, :authenticity_token => true ) {} %>" + end + + def form_for_remote_with_external_token + render :inline => "<%= form_for(:some_resource, :remote => true, :authenticity_token => 'external_token') {} %>" + end + def rescue_action(e) raise e end end @@ -45,7 +61,7 @@ class RequestForgeryProtectionController < ActionController::Base protect_from_forgery :only => %w(index meta) end -class RequestForgeryProtectionControllerUsingOldBehaviour < ActionController::Base +class RequestForgeryProtectionControllerUsingException < ActionController::Base include RequestForgeryProtectionActions protect_from_forgery :only => %w(index meta) @@ -73,14 +89,12 @@ class CustomAuthenticityParamController < RequestForgeryProtectionController end end - # common test methods - module RequestForgeryProtectionTests def setup @token = "cf50faa3fe97702ca1ae" - ActiveSupport::SecureRandom.stubs(:base64).returns(@token) + SecureRandom.stubs(:base64).returns(@token) ActionController::Base.request_forgery_protection_token = :custom_authenticity_token end @@ -102,6 +116,60 @@ module RequestForgeryProtectionTests assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', @token end + def test_should_render_form_without_token_tag_if_remote + assert_not_blocked do + get :form_for_remote + end + assert_no_match(/authenticity_token/, response.body) + end + + def test_should_render_form_with_token_tag_if_remote_and_embedding_token_is_on + original = ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms + begin + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = true + assert_not_blocked do + get :form_for_remote + end + assert_match(/authenticity_token/, response.body) + ensure + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = original + end + end + + def test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested_and_embedding_is_on + original = ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms + begin + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = true + assert_not_blocked do + get :form_for_remote_with_external_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', 'external_token' + ensure + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = original + end + end + + def test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested + assert_not_blocked do + get :form_for_remote_with_external_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', 'external_token' + end + + def test_should_render_form_with_token_tag_if_remote_and_authenticity_token_requested + assert_not_blocked do + get :form_for_remote_with_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', @token + end + + def test_should_render_form_with_token_tag_with_authenticity_token_requested + assert_not_blocked do + get :form_for_with_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', @token + end + def test_should_allow_get assert_not_blocked { get :index } end @@ -118,6 +186,10 @@ module RequestForgeryProtectionTests assert_blocked { post :index, :format=>'xml' } end + def test_should_not_allow_patch_without_token + assert_blocked { patch :index } + end + def test_should_not_allow_put_without_token assert_blocked { put :index } end @@ -134,6 +206,10 @@ module RequestForgeryProtectionTests assert_not_blocked { post :index, :custom_authenticity_token => @token } end + def test_should_allow_patch_with_token + assert_not_blocked { patch :index, :custom_authenticity_token => @token } + end + def test_should_allow_put_with_token assert_not_blocked { put :index, :custom_authenticity_token => @token } end @@ -152,11 +228,31 @@ module RequestForgeryProtectionTests assert_not_blocked { delete :index } end + def test_should_allow_patch_with_token_in_header + @request.env['HTTP_X_CSRF_TOKEN'] = @token + assert_not_blocked { patch :index } + end + def test_should_allow_put_with_token_in_header @request.env['HTTP_X_CSRF_TOKEN'] = @token assert_not_blocked { put :index } end + def test_should_warn_on_missing_csrf_token + old_logger = ActionController::Base.logger + logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new + ActionController::Base.logger = logger + + begin + assert_blocked { post :index } + + assert_equal 1, logger.logged(:warn).size + assert_match(/CSRF token authenticity/, logger.logged(:warn).last) + ensure + ActionController::Base.logger = old_logger + end + end + def assert_blocked session[:something_like_user_id] = 1 yield @@ -184,14 +280,14 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase end test 'should emit a csrf-param meta tag and a csrf-token meta tag' do - ActiveSupport::SecureRandom.stubs(:base64).returns(@token + '<=?') + SecureRandom.stubs(:base64).returns(@token + '<=?') get :meta assert_select 'meta[name=?][content=?]', 'csrf-param', 'custom_authenticity_token' assert_select 'meta[name=?][content=?]', 'csrf-token', 'cf50faa3fe97702ca1ae<=?' end end -class RequestForgeryProtectionControllerUsingOldBehaviourTest < ActionController::TestCase +class RequestForgeryProtectionControllerUsingExceptionTest < ActionController::TestCase include RequestForgeryProtectionTests def assert_blocked assert_raises(ActionController::InvalidAuthenticityToken) do @@ -207,7 +303,7 @@ class FreeCookieControllerTest < ActionController::TestCase @response = ActionController::TestResponse.new @token = "cf50faa3fe97702ca1ae" - ActiveSupport::SecureRandom.stubs(:base64).returns(@token) + SecureRandom.stubs(:base64).returns(@token) end def test_should_not_render_form_with_token_tag @@ -221,7 +317,7 @@ class FreeCookieControllerTest < ActionController::TestCase end def test_should_allow_all_methods_without_token - [:post, :put, :delete].each do |method| + [:post, :patch, :put, :delete].each do |method| assert_nothing_raised { send(method, :index)} end end @@ -232,10 +328,6 @@ class FreeCookieControllerTest < ActionController::TestCase end end - - - - class CustomAuthenticityParamControllerTest < ActionController::TestCase def setup ActionController::Base.request_forgery_protection_token = :custom_token_name diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index c445285538..48e2d6491e 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -60,11 +60,6 @@ class RescueController < ActionController::Base render :text => exception.message end - # This is a Dispatcher exception and should be in ApplicationController. - rescue_from ActionController::RoutingError do - render :text => 'no way' - end - rescue_from ActionView::TemplateError do render :text => 'action_view templater error' end @@ -137,11 +132,11 @@ class RescueController < ActionController::Base end def io_error_in_view - raise ActionView::TemplateError.new(nil, {}, IOError.new('this is io error')) + raise ActionView::TemplateError.new(nil, IOError.new('this is io error')) end def zero_division_error_in_view - raise ActionView::TemplateError.new(nil, {}, ZeroDivisionError.new('this is zero division error')) + raise ActionView::TemplateError.new(nil, ZeroDivisionError.new('this is zero division error')) end protected @@ -338,29 +333,14 @@ class RescueTest < ActionDispatch::IntegrationTest end end - test 'rescue routing exceptions' do - raiser = proc { |env| raise ActionController::RoutingError, "Did not handle the request" } - @app = ActionDispatch::Rescue.new(raiser) do - rescue_from ActionController::RoutingError, lambda { |env| [200, {"Content-Type" => "text/html"}, ["Gotcha!"]] } - end - - get '/b00m' - assert_equal "Gotcha!", response.body - end - - test 'unrescued exception' do - raiser = proc { |env| raise ActionController::RoutingError, "Did not handle the request" } - @app = ActionDispatch::Rescue.new(raiser) - assert_raise(ActionController::RoutingError) { get '/b00m' } - end - private + def with_test_routing with_routing do |set| set.draw do - match 'foo', :to => ::RescueTest::TestController.action(:foo) - match 'invalid', :to => ::RescueTest::TestController.action(:invalid) - match 'b00m', :to => ::RescueTest::TestController.action(:b00m) + get 'foo', :to => ::RescueTest::TestController.action(:foo) + get 'invalid', :to => ::RescueTest::TestController.action(:invalid) + get 'b00m', :to => ::RescueTest::TestController.action(:b00m) end yield end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 6ea492cf8b..de1bff17eb 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -6,7 +6,6 @@ require 'active_support/core_ext/object/inclusion' 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 @@ -91,6 +90,15 @@ class ResourcesTest < ActionController::TestCase end end + def test_multiple_resources_with_options + expected_options = {:controller => 'threads', :action => 'index'} + + with_restful_routing :messages, :comments, expected_options.slice(:controller) do + assert_recognizes(expected_options, :path => 'comments') + assert_recognizes(expected_options, :path => 'messages') + end + end + def test_with_custom_conditions with_restful_routing :messages, :conditions => { :subdomain => 'app' } do assert @routes.recognize_path("/messages", :method => :get, :subdomain => 'app') @@ -101,7 +109,7 @@ class ResourcesTest < ActionController::TestCase expected_options = {:controller => 'messages', :action => 'show', :id => '1.1.1'} with_restful_routing :messages do - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes(expected_options, :path => 'messages/1.1.1', :method => :get) end end @@ -150,7 +158,7 @@ class ResourcesTest < ActionController::TestCase end def test_with_collection_actions - actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } + actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete, 'e' => :patch } with_routing do |set| set.draw do @@ -159,6 +167,7 @@ class ResourcesTest < ActionController::TestCase put :b, :on => :collection post :c, :on => :collection delete :d, :on => :collection + patch :e, :on => :collection end end @@ -177,7 +186,7 @@ class ResourcesTest < ActionController::TestCase end def test_with_collection_actions_and_name_prefix - actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } + actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete, 'e' => :patch } with_routing do |set| set.draw do @@ -187,6 +196,7 @@ class ResourcesTest < ActionController::TestCase put :b, :on => :collection post :c, :on => :collection delete :d, :on => :collection + patch :e, :on => :collection end end end @@ -233,7 +243,7 @@ class ResourcesTest < ActionController::TestCase end def test_with_collection_action_and_name_prefix_and_formatted - actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } + actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete, 'e' => :patch } with_routing do |set| set.draw do @@ -243,6 +253,7 @@ class ResourcesTest < ActionController::TestCase put :b, :on => :collection post :c, :on => :collection delete :d, :on => :collection + patch :e, :on => :collection end end end @@ -262,7 +273,7 @@ class ResourcesTest < ActionController::TestCase end def test_with_member_action - [:put, :post].each do |method| + [:patch, :put, :post].each do |method| with_restful_routing :messages, :member => { :mark => method } do mark_options = {:action => 'mark', :id => '1'} mark_path = "/messages/1/mark" @@ -286,7 +297,7 @@ class ResourcesTest < ActionController::TestCase end def test_member_when_override_paths_for_default_restful_actions_with - [:put, :post].each do |method| + [:patch, :put, :post].each do |method| with_restful_routing :messages, :member => { :mark => method }, :path_names => {:new => 'nuevo'} do mark_options = {:action => 'mark', :id => '1', :controller => "messages"} mark_path = "/messages/1/mark" @@ -303,7 +314,7 @@ class ResourcesTest < ActionController::TestCase end def test_with_two_member_actions_with_same_method - [:put, :post].each do |method| + [:patch, :put, :post].each do |method| with_routing do |set| set.draw do resources :messages do @@ -523,7 +534,7 @@ class ResourcesTest < ActionController::TestCase routes.each do |route| routes.each do |r| next if route === r # skip the comparison instance - assert distinct_routes?(route, r), "Duplicate Route: #{route}" + assert_not_equal [route.conditions, route.path.spec.to_s], [r.conditions, r.path.spec.to_s] end end end @@ -556,7 +567,7 @@ class ResourcesTest < ActionController::TestCase end def test_singleton_resource_with_member_action - [:put, :post].each do |method| + [:patch, :put, :post].each do |method| with_routing do |set| set.draw do resource :account do @@ -578,7 +589,7 @@ class ResourcesTest < ActionController::TestCase end def test_singleton_resource_with_two_member_actions_with_same_method - [:put, :post].each do |method| + [:patch, :put, :post].each do |method| with_routing do |set| set.draw do resource :account do @@ -643,17 +654,21 @@ class ResourcesTest < ActionController::TestCase end end - def test_should_not_allow_delete_or_put_on_collection_path + def test_should_not_allow_delete_or_patch_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_raise(ActionController::RoutingError) do + assert_raise(Assertion) do + assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :patch) + end + + assert_raise(Assertion) do assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :put) end - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes(options.merge(:action => 'destroy'), :path => collection_path, :method => :delete) end end @@ -665,7 +680,7 @@ class ResourcesTest < ActionController::TestCase scope '/threads/:thread_id' do resources :messages, :as => 'thread_messages' do get :search, :on => :collection - match :preview, :on => :new + get :preview, :on => :new end end end @@ -683,7 +698,7 @@ class ResourcesTest < ActionController::TestCase scope '/admin' do resource :account, :as => :admin_account do get :login, :on => :member - match :preview, :on => :new + get :preview, :on => :new end end end @@ -1338,17 +1353,8 @@ class ResourcesTest < ActionController::TestCase end def assert_not_recognizes(expected_options, path) - assert_raise ActionController::RoutingError, Assertion do + assert_raise Assertion do assert_recognizes(expected_options, path) end end - - def distinct_routes? (r1, r2) - if r1.conditions == r2.conditions and r1.constraints == r2.constraints then - if r1.segments.collect(&:to_s) == r2.segments.collect(&:to_s) then - return false - end - end - true - end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index aa9d193436..cd91064ab8 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1,31 +1,23 @@ # encoding: utf-8 require 'abstract_unit' require 'controller/fake_controllers' -require 'active_support/dependencies' require 'active_support/core_ext/object/with_options' class MilestonesController < ActionController::Base def index() head :ok end alias_method :show, :index - def rescue_action(e) raise e end end ROUTING = ActionDispatch::Routing -module RoutingTestHelpers - def url_for(set, options, recall = nil) - set.send(:url_for, options.merge(:only_path => true, :_path_segments => recall)) - end -end - # See RFC 3986, section 3.3 for allowed path characters. -class UriReservedCharactersRoutingTest < Test::Unit::TestCase +class UriReservedCharactersRoutingTest < ActiveSupport::TestCase include RoutingTestHelpers def setup @set = ActionDispatch::Routing::RouteSet.new @set.draw do - match ':controller/:action/:variable/*additional' + get ':controller/:action/:variable/*additional' end safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ]) @@ -67,11 +59,11 @@ end class MockController def self.build(helpers) Class.new do - def url_for(options) + def url_options + options = super options[:protocol] ||= "http" options[:host] ||= "test.host" - - super(options) + options end include helpers @@ -79,17 +71,197 @@ class MockController end end -class LegacyRouteSetTests < Test::Unit::TestCase +class LegacyRouteSetTests < ActiveSupport::TestCase include RoutingTestHelpers + include ActionDispatch::RoutingVerbs attr_reader :rs + alias :routes :rs def setup - @rs = ::ActionDispatch::Routing::RouteSet.new + @rs = ::ActionDispatch::Routing::RouteSet.new + @response = nil end - def teardown - @rs.clear! + def test_symbols_with_dashes + rs.draw do + get '/:artist/:song-omg', :to => lambda { |env| + resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + [200, {}, [resp]] + } + end + + hash = JSON.load get(URI('http://example.org/journey/faithfully-omg')) + assert_equal({"artist"=>"journey", "song"=>"faithfully"}, hash) + end + + def test_id_with_dash + rs.draw do + get '/journey/:id', :to => lambda { |env| + resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + [200, {}, [resp]] + } + end + + hash = JSON.load get(URI('http://example.org/journey/faithfully-omg')) + assert_equal({"id"=>"faithfully-omg"}, hash) + end + + def test_dash_with_custom_regexp + rs.draw do + get '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env| + resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + [200, {}, [resp]] + } + end + + hash = JSON.load get(URI('http://example.org/journey/123-omg')) + assert_equal({"artist"=>"journey", "song"=>"123"}, hash) + assert_equal 'Not Found', get(URI('http://example.org/journey/faithfully-omg')) + end + + def test_pre_dash + rs.draw do + get '/:artist/omg-:song', :to => lambda { |env| + resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + [200, {}, [resp]] + } + end + + hash = JSON.load get(URI('http://example.org/journey/omg-faithfully')) + assert_equal({"artist"=>"journey", "song"=>"faithfully"}, hash) + end + + def test_pre_dash_with_custom_regexp + rs.draw do + get '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env| + resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + [200, {}, [resp]] + } + end + + hash = JSON.load get(URI('http://example.org/journey/omg-123')) + assert_equal({"artist"=>"journey", "song"=>"123"}, hash) + assert_equal 'Not Found', get(URI('http://example.org/journey/omg-faithfully')) + end + + def test_star_paths_are_greedy + rs.draw do + get "/*path", :to => lambda { |env| + x = env["action_dispatch.request.path_parameters"][:path] + [200, {}, [x]] + }, :format => false + end + + u = URI('http://example.org/foo/bar.html') + assert_equal u.path.sub(/^\//, ''), get(u) + end + + def test_star_paths_are_greedy_but_not_too_much + rs.draw do + get "/*path", :to => lambda { |env| + x = JSON.dump env["action_dispatch.request.path_parameters"] + [200, {}, [x]] + } + end + + expected = { "path" => "foo/bar", "format" => "html" } + u = URI('http://example.org/foo/bar.html') + assert_equal expected, JSON.parse(get(u)) + end + + def test_optional_star_paths_are_greedy + rs.draw do + get "/(*filters)", :to => lambda { |env| + x = env["action_dispatch.request.path_parameters"][:filters] + [200, {}, [x]] + }, :format => false + end + + u = URI('http://example.org/ne_27.065938,-80.6092/sw_25.489856,-82.542794') + assert_equal u.path.sub(/^\//, ''), get(u) + end + + def test_optional_star_paths_are_greedy_but_not_too_much + rs.draw do + get "/(*filters)", :to => lambda { |env| + x = JSON.dump env["action_dispatch.request.path_parameters"] + [200, {}, [x]] + } + end + + expected = { "filters" => "ne_27.065938,-80.6092/sw_25.489856,-82", + "format" => "542794" } + u = URI('http://example.org/ne_27.065938,-80.6092/sw_25.489856,-82.542794') + assert_equal expected, JSON.parse(get(u)) + end + + def test_regexp_precidence + @rs.draw do + get '/whois/:domain', :constraints => { + :domain => /\w+\.[\w\.]+/ }, + :to => lambda { |env| [200, {}, %w{regexp}] } + + get '/whois/:id', :to => lambda { |env| [200, {}, %w{id}] } + end + + assert_equal 'regexp', get(URI('http://example.org/whois/example.org')) + assert_equal 'id', get(URI('http://example.org/whois/123')) + end + + def test_class_and_lambda_constraints + subdomain = Class.new { + def matches? request + request.subdomain.present? and request.subdomain != 'clients' + end + } + + @rs.draw do + get '/', :constraints => subdomain.new, + :to => lambda { |env| [200, {}, %w{default}] } + get '/', :constraints => { :subdomain => 'clients' }, + :to => lambda { |env| [200, {}, %w{clients}] } + end + + assert_equal 'default', get(URI('http://www.example.org/')) + assert_equal 'clients', get(URI('http://clients.example.org/')) + end + + def test_lambda_constraints + @rs.draw do + get '/', :constraints => lambda { |req| + req.subdomain.present? and req.subdomain != "clients" }, + :to => lambda { |env| [200, {}, %w{default}] } + + get '/', :constraints => lambda { |req| + req.subdomain.present? && req.subdomain == "clients" }, + :to => lambda { |env| [200, {}, %w{clients}] } + end + + assert_equal 'default', get(URI('http://www.example.org/')) + assert_equal 'clients', get(URI('http://clients.example.org/')) + end + + def test_empty_string_match + rs.draw do + get '/:username', :constraints => { :username => /[^\/]+/ }, + :to => lambda { |e| [200, {}, ['foo']] } + end + assert_equal 'Not Found', get(URI('http://example.org/')) + assert_equal 'foo', get(URI('http://example.org/hello')) + end + + def test_non_greedy_glob_regexp + params = nil + rs.draw do + get '/posts/:id(/*filters)', :constraints => { :filters => /.+?/ }, + :to => lambda { |e| + params = e["action_dispatch.request.path_parameters"] + [200, {}, ['foo']] + } + end + assert_equal 'foo', get(URI('http://example.org/posts/1/foo.js')) + assert_equal({:id=>"1", :filters=>"foo", :format=>"js"}, params) end def test_draw_with_block_arity_one_raises @@ -99,7 +271,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_default_setup - @rs.draw { match '/:controller(/:action(/:id))' } + @rs.draw { get '/:controller(/:action(/:id))' } 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")) @@ -117,51 +289,21 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_ignores_leading_slash @rs.clear! - @rs.draw { match '/:controller(/:action(/:id))'} + @rs.draw { get '/:controller(/:action(/:id))'} test_default_setup end - def test_time_recognition - # We create many routes to make situation more realistic - @rs = ::ActionDispatch::Routing::RouteSet.new - @rs.draw { - root :to => "search#new", :as => "frontpage" - resources :videos do - resources :comments - resource :file, :controller => 'video_file' - resource :share, :controller => 'video_shares' - resource :abuse, :controller => 'video_abuses' - end - resources :abuses, :controller => 'video_abuses' - resources :video_uploads - resources :video_visits - - resources :users do - resource :settings - resources :videos - end - resources :channels do - resources :videos, :controller => 'channel_videos' - end - resource :session - resource :lost_password - match 'search' => 'search#index', :as => 'search' - resources :pages - match ':controller/:action/:id' - } - end - def test_route_with_colon_first rs.draw do - match '/:controller/:action/:id', :action => 'index', :id => nil - match ':url', :controller => 'tiny_url', :action => 'translate' + get '/:controller/:action/:id', :action => 'index', :id => nil + get ':url', :controller => 'tiny_url', :action => 'translate' end end def test_route_with_regexp_for_controller rs.draw do - match ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/ - match '/:controller(/:action(/:id))' + get ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/ + get '/:controller(/:action(/:id))' end assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"}, @@ -175,7 +317,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_route_with_regexp_and_captures_for_controller rs.draw do - match '/:controller(/:action(/:id))', :controller => /admin\/(accounts|users)/ + get '/:controller(/:action(/:id))', :controller => /admin\/(accounts|users)/ end assert_equal({:controller => "admin/accounts", :action => "index"}, rs.recognize_path("/admin/accounts")) assert_equal({:controller => "admin/users", :action => "index"}, rs.recognize_path("/admin/users")) @@ -184,7 +326,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_route_with_regexp_and_dot rs.draw do - match ':controller/:action/:file', + get ':controller/:action/:file', :controller => /admin|user/, :action => /upload|download/, :defaults => {:file => nil}, @@ -214,7 +356,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_with_option rs.draw do - match 'page/:title' => 'content#show_page', :as => 'page' + get 'page/:title' => 'content#show_page', :as => 'page' end assert_equal("http://test.host/page/new%20stuff", @@ -223,7 +365,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_with_default rs.draw do - match 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page' + get 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page' end assert_equal("http://test.host/page/AboutRails", @@ -233,7 +375,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_with_path_prefix rs.draw do scope "my" do - match 'page' => 'content#show_page', :as => 'page' + get 'page' => 'content#show_page', :as => 'page' end end @@ -244,7 +386,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_with_blank_path_prefix rs.draw do scope "" do - match 'page' => 'content#show_page', :as => 'page' + get 'page' => 'content#show_page', :as => 'page' end end @@ -254,7 +396,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_with_nested_controller rs.draw do - match 'admin/user' => 'admin/user#index', :as => "users" + get 'admin/user' => 'admin/user#index', :as => "users" end assert_equal("http://test.host/admin/user", @@ -263,7 +405,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_optimised_named_route_with_host rs.draw do - match 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com' + get 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com' end routes = setup_for_named_route routes.expects(:url_for).with({ @@ -282,7 +424,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_without_hash rs.draw do - match ':controller/:action/:id', :as => 'normal' + get ':controller/:action/:id', :as => 'normal' end end @@ -295,11 +437,20 @@ class LegacyRouteSetTests < Test::Unit::TestCase assert_equal("/", routes.send(:root_path)) end + def test_named_route_root_without_hash + rs.draw do + root "hello#index" + end + routes = setup_for_named_route + assert_equal("http://test.host/", routes.send(:root_url)) + assert_equal("/", routes.send(:root_path)) + end + def test_named_route_with_regexps rs.draw do - match 'page/:year/:month/:day/:title' => 'page#show', :as => 'article', + get 'page/:year/:month/:day/:title' => 'page#show', :as => 'article', :year => /\d+/, :month => /\d+/, :day => /\d+/ - match ':controller/:action/:id' + get ':controller/:action/:id' end routes = setup_for_named_route @@ -309,7 +460,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_changing_controller - @rs.draw { match ':controller/:action/:id' } + @rs.draw { get ':controller/:action/:id' } assert_equal '/admin/stuff/show/10', url_for(rs, {:controller => 'stuff', :action => 'show', :id => 10}, @@ -318,8 +469,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_paths_escaped rs.draw do - match 'file/*path' => 'content#show_file', :as => 'path' - match ':controller/:action/:id' + get 'file/*path' => 'content#show_file', :as => 'path' + get ':controller/:action/:id' end # No + to space in URI escaping, only for query params. @@ -335,7 +486,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_paths_slashes_unescaped_with_ordered_parameters rs.draw do - match '/file/*path' => 'content#index', :as => 'path' + get '/file/*path' => 'content#index', :as => 'path' end # No / to %2F in URI, only for query params. @@ -344,14 +495,14 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_non_controllers_cannot_be_matched rs.draw do - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_raise(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") } end def test_should_list_options_diff_when_routing_constraints_dont_match rs.draw do - match 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post' + get 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post' end assert_raise(ActionController::RoutingError) do url_for(rs, { :controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post" }) @@ -360,7 +511,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_dynamic_path_allowed rs.draw do - match '*path' => 'content#show_file' + get '*path' => 'content#show_file' end assert_equal '/pages/boo', @@ -369,7 +520,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_dynamic_recall_paths_allowed rs.draw do - match '*path' => 'content#show_file' + get '*path' => 'content#show_file' end assert_equal '/pages/boo', @@ -378,8 +529,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_backwards rs.draw do - match 'page/:id(/:action)' => 'pages#show' - match ':controller(/:action(/:id))' + get 'page/:id(/:action)' => 'pages#show' + get ':controller(/:action(/:id))' end assert_equal '/page/20', url_for(rs, { :id => 20 }, { :controller => 'pages', :action => 'show' }) @@ -389,8 +540,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_route_with_fixnum_default rs.draw do - match 'page(/:id)' => 'content#show_page', :id => 1 - match ':controller/:action/:id' + get 'page(/:id)' => 'content#show_page', :id => 1 + get ':controller/:action/:id' end assert_equal '/page', url_for(rs, { :controller => 'content', :action => 'show_page' }) @@ -406,15 +557,15 @@ class LegacyRouteSetTests < Test::Unit::TestCase # For newer revision def test_route_with_text_default rs.draw do - match 'page/:id' => 'content#show_page', :id => 1 - match ':controller/:action/:id' + get 'page/:id' => 'content#show_page', :id => 1 + get ':controller/:action/:id' end assert_equal '/page/foo', url_for(rs, { :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 - token.force_encoding(Encoding::BINARY) if token.respond_to?(:force_encoding) + token.force_encoding(Encoding::BINARY) escaped_token = CGI::escape(token) assert_equal '/page/' + escaped_token, url_for(rs, { :controller => 'content', :action => 'show_page', :id => token }) @@ -422,13 +573,13 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_action_expiry - @rs.draw { match ':controller(/:action(/:id))' } + @rs.draw { get ':controller(/:action(/:id))' } assert_equal '/content', url_for(rs, { :controller => 'content' }, { :controller => 'content', :action => 'show' }) end def test_requirement_should_prevent_optional_id rs.draw do - match 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post' + get 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post' end assert_equal '/post/10', url_for(rs, { :controller => 'post', :action => 'show', :id => 10 }) @@ -440,11 +591,11 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_both_requirement_and_optional rs.draw do - match('test(/:year)' => 'post#show', :as => 'blog', + get('test(/:year)' => 'post#show', :as => 'blog', :defaults => { :year => nil }, :constraints => { :year => /\d{4}/ } ) - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_equal '/test', url_for(rs, { :controller => 'post', :action => 'show' }) @@ -455,8 +606,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_set_to_nil_forgets rs.draw do - match 'pages(/:year(/:month(/:day)))' => 'content#list_pages', :month => nil, :day => nil - match ':controller/:action/:id' + get 'pages(/:year(/:month(/:day)))' => 'content#list_pages', :month => nil, :day => nil + get ':controller/:action/:id' end assert_equal '/pages/2005', @@ -498,8 +649,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_named_route_method rs.draw do - match 'categories' => 'content#categories', :as => 'categories' - match ':controller(/:action(/:id))' + get 'categories' => 'content#categories', :as => 'categories' + get ':controller(/:action(/:id))' end assert_equal '/categories', url_for(rs, { :controller => 'content', :action => 'categories' }) @@ -513,9 +664,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_nil_defaults rs.draw do - match 'journal' => 'content#list_journal', + get 'journal' => 'content#list_journal', :date => nil, :user_id => nil - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_equal '/journal', url_for(rs, { @@ -531,11 +682,12 @@ class LegacyRouteSetTests < Test::Unit::TestCase match '/match' => 'books#get', :via => :get match '/match' => 'books#post', :via => :post match '/match' => 'books#put', :via => :put + match '/match' => 'books#patch', :via => :patch match '/match' => 'books#delete', :via => :delete end end - %w(GET POST PUT DELETE).each do |request_method| + %w(GET PATCH POST PUT DELETE).each do |request_method| define_method("test_request_method_recognized_with_#{request_method}") do setup_request_method_routes_for(request_method) params = rs.recognize_path("/match", :method => request_method) @@ -546,7 +698,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_recognize_array_of_methods rs.draw do match '/match' => 'books#get_or_post', :via => [:get, :post] - match '/match' => 'books#not_get_or_post' + put '/match' => 'books#not_get_or_post' end params = rs.recognize_path("/match", :method => :post) @@ -558,10 +710,10 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_subpath_recognized rs.draw do - match '/books/:id/edit' => 'subpath_books#edit' - match '/items/:id/:action' => 'subpath_books' - match '/posts/new/:action' => 'subpath_books' - match '/posts/:id' => 'subpath_books#show' + get '/books/:id/edit' => 'subpath_books#edit' + get '/items/:id/:action' => 'subpath_books' + get '/posts/new/:action' => 'subpath_books' + get '/posts/:id' => 'subpath_books#show' end hash = rs.recognize_path "/books/17/edit" @@ -583,9 +735,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_subpath_generated rs.draw do - match '/books/:id/edit' => 'subpath_books#edit' - match '/items/:id/:action' => 'subpath_books' - match '/posts/new/:action' => 'subpath_books' + get '/books/:id/edit' => 'subpath_books#edit' + get '/items/:id/:action' => 'subpath_books' + get '/posts/new/:action' => 'subpath_books' end assert_equal "/books/7/edit", url_for(rs, { :controller => "subpath_books", :id => 7, :action => "edit" }) @@ -595,7 +747,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_failed_constraints_raises_exception_with_violated_constraints rs.draw do - match 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ } + get 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ } end assert_raise(ActionController::RoutingError) do @@ -606,11 +758,11 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_routes_changed_correctly_after_clear rs = ::ActionDispatch::Routing::RouteSet.new rs.draw do - match 'ca' => 'ca#aa' - match 'cb' => 'cb#ab' - match 'cc' => 'cc#ac' - match ':controller/:action/:id' - match ':controller/:action/:id.:format' + get 'ca' => 'ca#aa' + get 'cb' => 'cb#ab' + get 'cc' => 'cc#ac' + get ':controller/:action/:id' + get ':controller/:action/:id.:format' end hash = rs.recognize_path "/cc" @@ -619,10 +771,10 @@ class LegacyRouteSetTests < Test::Unit::TestCase assert_equal %w(cc ac), [hash[:controller], hash[:action]] rs.draw do - match 'cb' => 'cb#ab' - match 'cc' => 'cc#ac' - match ':controller/:action/:id' - match ':controller/:action/:id.:format' + get 'cb' => 'cb#ab' + get 'cc' => 'cc#ac' + get ':controller/:action/:id' + get ':controller/:action/:id.:format' end hash = rs.recognize_path "/cc" @@ -647,29 +799,29 @@ class RouteSetTest < ActiveSupport::TestCase @default_route_set ||= begin set = ROUTING::RouteSet.new set.draw do - match '/:controller(/:action(/:id))' + get '/:controller(/:action(/:id))' end set end end def test_generate_extras - set.draw { match ':controller/(:action(/:id))' } + set.draw { get ':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 { |e| e.to_s }.sort end def test_extra_keys - set.draw { match ':controller/:action/:id' } + set.draw { get ':controller/:action/:id' } extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal %w(that this), extras.map { |e| e.to_s }.sort end def test_generate_extras_not_first set.draw do - match ':controller/:action/:id.:format' - match ':controller/:action/:id' + get ':controller/:action/:id.:format' + get ':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 @@ -678,8 +830,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_not_first set.draw do - match ':controller/:action/:id.:format' - match ':controller/:action/:id' + get ':controller/:action/:id.:format' + get ':controller/:action/:id' end assert_equal "/foo/bar/15?this=hello", url_for(set, { :controller => "foo", :action => "bar", :id => 15, :this => "hello" }) @@ -687,8 +839,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_extra_keys_not_first set.draw do - match ':controller/:action/:id.:format' - match ':controller/:action/:id' + get ':controller/:action/:id.:format' + get ':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 { |e| e.to_s }.sort @@ -697,7 +849,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_draw assert_equal 0, set.routes.size set.draw do - match '/hello/world' => 'a#b' + get '/hello/world' => 'a#b' end assert_equal 1, set.routes.size end @@ -705,7 +857,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_draw_symbol_controller_name assert_equal 0, set.routes.size set.draw do - match '/users/index' => 'users#index' + get '/users/index' => 'users#index' end set.recognize_path('/users/index', :method => :get) assert_equal 1, set.routes.size @@ -714,48 +866,31 @@ class RouteSetTest < ActiveSupport::TestCase def test_named_draw assert_equal 0, set.routes.size set.draw do - match '/hello/world' => 'a#b', :as => 'hello' + get '/hello/world' => 'a#b', :as => 'hello' end assert_equal 1, set.routes.size assert_equal set.routes.first, set.named_routes[:hello] end - def test_later_named_routes_take_precedence + def test_earlier_named_routes_take_precedence set.draw do - match '/hello/world' => 'a#b', :as => 'hello' - match '/hello' => 'a#b', :as => 'hello' + get '/hello/world' => 'a#b', :as => 'hello' + get '/hello' => 'a#b', :as => 'hello' end - assert_equal set.routes.last, set.named_routes[:hello] + assert_equal set.routes.first, set.named_routes[:hello] end def setup_named_route_test set.draw do - match '/people(/:id)' => 'people#show', :as => 'show' - match '/people' => 'people#index', :as => 'index' - match '/people/go/:foo/:bar/joe(/:id)' => 'people#multi', :as => 'multi' - match '/admin/users' => 'admin/users#index', :as => "users" + get '/people(/:id)' => 'people#show', :as => 'show' + get '/people' => 'people#index', :as => 'index' + get '/people/go/:foo/:bar/joe(/:id)' => 'people#multi', :as => 'multi' + get '/admin/users' => 'admin/users#index', :as => "users" end MockController.build(set.url_helpers).new 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 @@ -767,7 +902,6 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal "http://test.host/admin/users", controller.send(:users_url) assert_equal '/admin/users', controller.send(:users_path) - assert_equal '/admin/users', url_for(set, controller.send(:hash_for_users_url), { :controller => 'users', :action => 'index' }) end def test_named_route_url_method_with_anchor @@ -833,7 +967,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_draw_default_route set.draw do - match '/:controller/:action/:id' + get '/:controller/:action/:id' end assert_equal 1, set.routes.size @@ -847,8 +981,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_with_parameter_shell set.draw do - match 'page/:id' => 'pages#show', :id => /\d+/ - match '/:controller(/:action(/:id))' + get 'page/:id' => 'pages#show', :id => /\d+/ + get '/:controller(/:action(/:id))' end assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages')) @@ -862,7 +996,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_on_request_object_with_anchors_are_valid assert_nothing_raised do set.draw do - match 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ } + get 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ } end end end @@ -870,27 +1004,27 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_with_anchor_chars_are_invalid assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /^\d+/ + get 'page/:id' => 'pages#show', :id => /^\d+/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\A\d+/ + get 'page/:id' => 'pages#show', :id => /\A\d+/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\d+$/ + get 'page/:id' => 'pages#show', :id => /\d+$/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\d+\Z/ + get 'page/:id' => 'pages#show', :id => /\d+\Z/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\d+\z/ + get 'page/:id' => 'pages#show', :id => /\d+\z/ end end end @@ -905,7 +1039,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_recognize_with_encoded_id_and_regex set.draw do - match 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/ + get 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/ end assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10')) @@ -918,6 +1052,7 @@ class RouteSetTest < ActiveSupport::TestCase post "/people" => "people#create" get "/people/:id" => "people#show", :as => "person" put "/people/:id" => "people#update" + patch "/people/:id" => "people#update" delete "/people/:id" => "people#destroy" end @@ -930,6 +1065,9 @@ class RouteSetTest < ActiveSupport::TestCase params = set.recognize_path("/people/5", :method => :put) assert_equal("update", params[:action]) + params = set.recognize_path("/people/5", :method => :patch) + assert_equal("update", params[:action]) + assert_raise(ActionController::UnknownHttpMethod) { set.recognize_path("/people", :method => :bacon) } @@ -942,6 +1080,10 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal("update", params[:action]) assert_equal("5", params[:id]) + params = set.recognize_path("/people/5", :method => :patch) + assert_equal("update", params[:action]) + assert_equal("5", params[:id]) + params = set.recognize_path("/people/5", :method => :delete) assert_equal("destroy", params[:action]) assert_equal("5", params[:id]) @@ -968,7 +1110,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_typo_recognition set.draw do - match 'articles/:year/:month/:day/:title' => 'articles#permalink', + get 'articles/:year/:month/:day/:title' => 'articles#permalink', :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/ end @@ -983,7 +1125,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_routing_traversal_does_not_load_extra_classes assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded" set.draw do - match '/profile' => 'profile#index' + get '/profile' => 'profile#index' end set.recognize_path("/profile") rescue nil @@ -995,6 +1137,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do get "people/:id" => "people#show", :as => "person" put "people/:id" => "people#update" + patch "people/:id" => "people#update" get "people/:id(.:format)" => "people#show" end @@ -1005,6 +1148,9 @@ class RouteSetTest < ActiveSupport::TestCase params = set.recognize_path("/people/5", :method => :put) assert_equal("update", params[:action]) + params = set.recognize_path("/people/5", :method => :patch) + assert_equal("update", params[:action]) + params = set.recognize_path("/people/5.png", :method => :get) assert_equal("show", params[:action]) assert_equal("5", params[:id]) @@ -1013,8 +1159,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_default_action set.draw do - match "/people", :controller => "people", :action => "index" - match "/people/list", :controller => "people", :action => "list" + get "/people", :controller => "people", :action => "index" + get "/people/list", :controller => "people", :action => "list" end url = url_for(set, { :controller => "people", :action => "list" }) @@ -1033,7 +1179,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do namespace 'api' do - match 'inventory' => 'products#inventory' + get 'inventory' => 'products#inventory' end end @@ -1058,7 +1204,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_namespace_with_path_prefix set.draw do scope :module => "api", :path => "prefix" do - match 'inventory' => 'products#inventory' + get 'inventory' => 'products#inventory' end end @@ -1070,7 +1216,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_namespace_with_blank_path_prefix set.draw do scope :module => "api", :path => "" do - match 'inventory' => 'products#inventory' + get 'inventory' => 'products#inventory' end end @@ -1080,7 +1226,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_generate_changes_controller_module - set.draw { match ':controller/:action/:id' } + set.draw { get ':controller/:action/:id' } current = { :controller => "bling/bloop", :action => "bap", :id => 9 } assert_equal "/foo/bar/baz/7", @@ -1089,7 +1235,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_id_is_sticky_when_it_ought_to_be set.draw do - match ':controller/:id/:action' + get ':controller/:id/:action' end url = url_for(set, { :action => "destroy" }, { :controller => "people", :action => "show", :id => "7" }) @@ -1098,8 +1244,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_use_static_path_when_possible set.draw do - match 'about' => "welcome#about" - match ':controller/:action/:id' + get 'about' => "welcome#about" + get ':controller/:action/:id' end url = url_for(set, { :controller => "welcome", :action => "about" }, @@ -1109,7 +1255,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_generate - set.draw { match ':controller/:action/:id' } + set.draw { get ':controller/:action/:id' } args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } assert_equal "/foo/bar/7?x=y", url_for(set, args) @@ -1120,7 +1266,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_path_prefix set.draw do scope "my" do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end @@ -1131,7 +1277,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_blank_path_prefix set.draw do scope "" do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end @@ -1141,9 +1287,9 @@ class RouteSetTest < ActiveSupport::TestCase def test_named_routes_are_never_relative_to_modules set.draw do - match "/connection/manage(/:action)" => 'connection/manage#index' - match "/connection/connection" => "connection/connection#index" - match '/connection' => 'connection#index', :as => 'family_connection' + get "/connection/manage(/:action)" => 'connection/manage#index' + get "/connection/connection" => "connection/connection#index" + get '/connection' => 'connection#index', :as => 'family_connection' end url = url_for(set, { :controller => "connection" }, { :controller => 'connection/manage' }) @@ -1155,7 +1301,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_action_left_off_when_id_is_recalled set.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end assert_equal '/books', url_for(set, {:controller => 'books', :action => 'index'}, @@ -1165,8 +1311,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_query_params_will_be_shown_when_recalled set.draw do - match 'show_weblog/:parameter' => 'weblog#show' - match ':controller(/:action(/:id))' + get 'show_weblog/:parameter' => 'weblog#show' + get ':controller(/:action(/:id))' end assert_equal '/weblog/edit?parameter=1', url_for(set, {:action => 'edit', :parameter => 1}, @@ -1176,7 +1322,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_format_is_not_inherit set.draw do - match '/posts(.:format)' => 'posts#index' + get '/posts(.:format)' => 'posts#index' end assert_equal '/posts', url_for(set, @@ -1191,7 +1337,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_expiry_determination_should_consider_values_with_to_param - set.draw { match 'projects/:project_id/:controller/:action' } + set.draw { get 'projects/:project_id/:controller/:action' } assert_equal '/projects/1/weblog/show', url_for(set, { :action => 'show', :project_id => 1 }, { :controller => 'weblog', :action => 'show', :project_id => '1' }) @@ -1201,7 +1347,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do resources :projects do member do - match 'milestones' => 'milestones#index', :as => 'milestones' + get 'milestones' => 'milestones#index', :as => 'milestones' end end end @@ -1234,7 +1380,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_with_unsupported_regexp_options_must_error assert_raise ArgumentError do set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => { :name => /(david|jamis)/m } end end @@ -1243,13 +1389,13 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_with_supported_options_must_not_error assert_nothing_raised do set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => { :name => /(david|jamis)/i } end end assert_nothing_raised do set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => { :name => / # Desperately overcommented regexp ( #Either david #The Creator @@ -1260,9 +1406,22 @@ class RouteSetTest < ActiveSupport::TestCase end end + def test_route_with_subdomain_and_constraints_must_receive_params + name_param = nil + set.draw do + get 'page/:name' => 'pages#show', :constraints => lambda {|request| + name_param = request.params[:name] + return true + } + end + assert_equal({:controller => 'pages', :action => 'show', :name => 'mypage'}, + set.recognize_path('http://subdomain.example.org/page/mypage')) + assert_equal(name_param, 'mypage') + end + def test_route_requirement_recognize_with_ignore_case set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => /(david|jamis)/i} end assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis')) @@ -1274,7 +1433,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_requirement_generate_with_ignore_case set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => /(david|jamis)/i} end @@ -1289,7 +1448,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_requirement_recognize_with_extended_syntax set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => / # Desperately overcommented regexp ( #Either david #The Creator @@ -1309,7 +1468,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_requirement_with_xi_modifiers set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => / # Desperately overcommented regexp ( #Either david #The Creator @@ -1327,8 +1486,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_routes_with_symbols set.draw do - match 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol - match 'named' , :controller => :pages, :action => :show, :name => :as_symbol, :as => :named + get 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol + get 'named' , :controller => :pages, :action => :show, :name => :as_symbol, :as => :named end assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/unnamed')) assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/named')) @@ -1336,8 +1495,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_regexp_chunk_should_add_question_mark_for_optionals set.draw do - match '/' => 'foo#index' - match '/hello' => 'bar#index' + get '/' => 'foo#index' + get '/hello' => 'bar#index' end assert_equal '/', url_for(set, { :controller => 'foo' }) @@ -1349,7 +1508,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_assign_route_options_with_anchor_chars set.draw do - match '/cars/:action/:person/:car/', :controller => 'cars' + get '/cars/:action/:person/:car/', :controller => 'cars' end assert_equal '/cars/buy/1/2', url_for(set, { :controller => 'cars', :action => 'buy', :person => '1', :car => '2' }) @@ -1359,7 +1518,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_segmentation_of_dot_path set.draw do - match '/books/:action.rss', :controller => 'books' + get '/books/:action.rss', :controller => 'books' end assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list' }) @@ -1369,7 +1528,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_segmentation_of_dynamic_dot_path set.draw do - match '/books(/:action(.:format))', :controller => 'books' + get '/books(/:action(.:format))', :controller => 'books' end assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list', :format => 'rss' }) @@ -1385,7 +1544,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_slashes_are_implied @set = nil - set.draw { match("/:controller(/:action(/:id))") } + set.draw { get("/:controller(/:action(/:id))") } assert_equal '/content', url_for(set, { :controller => 'content', :action => 'index' }) assert_equal '/content/list', url_for(set, { :controller => 'content', :action => 'list' }) @@ -1470,13 +1629,13 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_default_params set.draw do - match 'dummy/page/:page' => 'dummy#show' - match 'dummy/dots/page.:page' => 'dummy#dots' - match 'ibocorp(/:page)' => 'ibocorp#show', + get 'dummy/page/:page' => 'dummy#show' + get 'dummy/dots/page.:page' => 'dummy#dots' + get 'ibocorp(/:page)' => 'ibocorp#show', :constraints => { :page => /\d+/ }, :defaults => { :page => 1 } - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_equal '/ibocorp', url_for(set, { :controller => 'ibocorp', :action => "show", :page => 1 }) @@ -1484,17 +1643,17 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_optional_params_recalls_last_request set.draw do - match "blog/", :controller => "blog", :action => "index" + get "blog/", :controller => "blog", :action => "index" - match "blog(/:year(/:month(/:day)))", + get "blog(/:year(/:month(/:day)))", :controller => "blog", :action => "show_date", :constraints => { :year => /(19|20)\d\d/, :month => /[01]?\d/, :day => /[0-3]?\d/ }, :day => nil, :month => nil - match "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/ - match "blog/:controller/:action(/:id)" - match "*anything", :controller => "blog", :action => "unknown_request" + get "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/ + get "blog/:controller/:action(/:id)" + get "*anything", :controller => "blog", :action => "unknown_request" end assert_equal({:controller => "blog", :action => "index"}, set.recognize_path("/blog")) @@ -1542,7 +1701,7 @@ class RackMountIntegrationTests < ActiveSupport::TestCase root :to => 'users#index' end - match '/blog(/:year(/:month(/:day)))' => 'posts#show_date', + get '/blog(/:year(/:month(/:day)))' => 'posts#show_date', :constraints => { :year => /(19|20)\d\d/, :month => /[01]?\d/, @@ -1551,37 +1710,37 @@ class RackMountIntegrationTests < ActiveSupport::TestCase :day => nil, :month => nil - match 'archive/:year', :controller => 'archive', :action => 'index', + get 'archive/:year', :controller => 'archive', :action => 'index', :defaults => { :year => nil }, :constraints => { :year => /\d{4}/ }, :as => "blog" resources :people - match 'legacy/people' => "people#index", :legacy => "true" + get 'legacy/people' => "people#index", :legacy => "true" - match 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol - match 'id_default(/:id)' => "foo#id_default", :id => 1 + get 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol + get 'id_default(/:id)' => "foo#id_default", :id => 1 match 'get_or_post' => "foo#get_or_post", :via => [:get, :post] - match 'optional/:optional' => "posts#index" - match 'projects/:project_id' => "project#index", :as => "project" - match 'clients' => "projects#index" + get 'optional/:optional' => "posts#index" + get 'projects/:project_id' => "project#index", :as => "project" + get 'clients' => "projects#index" - match 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i - match 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { + get 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i + get 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { :postalcode => /# Postcode format \d{5} #Prefix (-\d{4})? #Suffix /x }, :as => "geocode" - match 'news(.:format)' => "news#index" + get 'news(.:format)' => "news#index" - match 'comment/:id(/:action)' => "comments#show" - match 'ws/:controller(/:action(/:id))', :ws => true - match 'account(/:action)' => "account#subscription" - match 'pages/:page_id/:controller(/:action(/:id))' - match ':controller/ping', :action => 'ping' - match ':controller(/:action(/:id))(.:format)' + get 'comment/:id(/:action)' => "comments#show" + get 'ws/:controller(/:action(/:id))', :ws => true + get 'account(/:action)' => "account#subscription" + get 'pages/:page_id/:controller(/:action(/:id))' + get ':controller/ping', :action => 'ping' + match ':controller(/:action(/:id))(.:format)', :via => :all root :to => "news#index" } @@ -1665,114 +1824,6 @@ class RackMountIntegrationTests < ActiveSupport::TestCase assert_raise(ActionController::RoutingError) { @routes.recognize_path('/none', :method => :get) } end - def test_generate - assert_equal '/admin/users', url_for(@routes, { :use_route => 'admin_users' }) - assert_equal '/admin/users', url_for(@routes, { :controller => 'admin/users' }) - assert_equal '/admin/users', url_for(@routes, { :controller => 'admin/users', :action => 'index' }) - assert_equal '/admin/users', url_for(@routes, { :action => 'index' }, { :controller => 'admin/users' }) - assert_equal '/admin/users', url_for(@routes, { :controller => 'users', :action => 'index' }, { :controller => 'admin/accounts' }) - assert_equal '/people', url_for(@routes, { :controller => '/people', :action => 'index' }, { :controller => 'admin/accounts' }) - - assert_equal '/admin/posts', url_for(@routes, { :controller => 'admin/posts' }) - assert_equal '/admin/posts/new', url_for(@routes, { :controller => 'admin/posts', :action => 'new' }) - - assert_equal '/blog/2009', url_for(@routes, { :controller => 'posts', :action => 'show_date', :year => 2009 }) - assert_equal '/blog/2009/1', url_for(@routes, { :controller => 'posts', :action => 'show_date', :year => 2009, :month => 1 }) - assert_equal '/blog/2009/1/1', url_for(@routes, { :controller => 'posts', :action => 'show_date', :year => 2009, :month => 1, :day => 1 }) - - assert_equal '/archive/2010', url_for(@routes, { :controller => 'archive', :action => 'index', :year => '2010' }) - assert_equal '/archive', url_for(@routes, { :controller => 'archive', :action => 'index' }) - assert_equal '/archive?year=january', url_for(@routes, { :controller => 'archive', :action => 'index', :year => 'january' }) - - assert_equal '/people', url_for(@routes, { :controller => 'people', :action => 'index' }) - assert_equal '/people', url_for(@routes, { :action => 'index' }, { :controller => 'people' }) - assert_equal '/people', url_for(@routes, { :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people', url_for(@routes, { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people', url_for(@routes, {}, { :controller => 'people', :action => 'index' }) - assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people/new', url_for(@routes, { :use_route => 'new_person' }) - assert_equal '/people/new', url_for(@routes, { :controller => 'people', :action => 'new' }) - assert_equal '/people/1', url_for(@routes, { :use_route => 'person', :id => '1' }) - assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people/1.xml', url_for(@routes, { :controller => 'people', :action => 'show', :id => '1', :format => 'xml' }) - assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show', :id => 1 }) - assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show', :id => Model.new('1') }) - assert_equal '/people/1', url_for(@routes, { :action => 'show', :id => '1' }, { :controller => 'people', :action => 'index' }) - assert_equal '/people/1', url_for(@routes, { :action => 'show', :id => 1 }, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people', url_for(@routes, { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people/1', url_for(@routes, {}, { :controller => 'people', :action => 'show', :id => '1' }) - assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'index', :id => '1' }) - assert_equal '/people/1/edit', url_for(@routes, { :controller => 'people', :action => 'edit', :id => '1' }) - assert_equal '/people/1/edit.xml', url_for(@routes, { :controller => 'people', :action => 'edit', :id => '1', :format => 'xml' }) - assert_equal '/people/1/edit', url_for(@routes, { :use_route => 'edit_person', :id => '1' }) - assert_equal '/people/1?legacy=true', url_for(@routes, { :controller => 'people', :action => 'show', :id => '1', :legacy => 'true' }) - assert_equal '/people?legacy=true', url_for(@routes, { :controller => 'people', :action => 'index', :legacy => 'true' }) - - assert_equal '/id_default/2', url_for(@routes, { :controller => 'foo', :action => 'id_default', :id => '2' }) - assert_equal '/id_default', url_for(@routes, { :controller => 'foo', :action => 'id_default', :id => '1' }) - assert_equal '/id_default', url_for(@routes, { :controller => 'foo', :action => 'id_default', :id => 1 }) - assert_equal '/id_default', url_for(@routes, { :controller => 'foo', :action => 'id_default' }) - assert_equal '/optional/bar', url_for(@routes, { :controller => 'posts', :action => 'index', :optional => 'bar' }) - assert_equal '/posts', url_for(@routes, { :controller => 'posts', :action => 'index' }) - - assert_equal '/project', url_for(@routes, { :controller => 'project', :action => 'index' }) - assert_equal '/projects/1', url_for(@routes, { :controller => 'project', :action => 'index', :project_id => '1' }) - assert_equal '/projects/1', url_for(@routes, { :controller => 'project', :action => 'index'}, {:project_id => '1' }) - assert_raise(ActionController::RoutingError) { url_for(@routes, { :use_route => 'project', :controller => 'project', :action => 'index' }) } - assert_equal '/projects/1', url_for(@routes, { :use_route => 'project', :controller => 'project', :action => 'index', :project_id => '1' }) - assert_equal '/projects/1', url_for(@routes, { :use_route => 'project', :controller => 'project', :action => 'index' }, { :project_id => '1' }) - - assert_equal '/clients', url_for(@routes, { :controller => 'projects', :action => 'index' }) - assert_equal '/clients?project_id=1', url_for(@routes, { :controller => 'projects', :action => 'index', :project_id => '1' }) - assert_equal '/clients', url_for(@routes, { :controller => 'projects', :action => 'index' }, { :project_id => '1' }) - assert_equal '/clients', url_for(@routes, { :action => 'index' }, { :controller => 'projects', :action => 'index', :project_id => '1' }) - - assert_equal '/comment/20', url_for(@routes, { :id => 20 }, { :controller => 'comments', :action => 'show' }) - assert_equal '/comment/20', url_for(@routes, { :controller => 'comments', :id => 20, :action => 'show' }) - assert_equal '/comments/boo', url_for(@routes, { :controller => 'comments', :action => 'boo' }) - - assert_equal '/ws/posts/show/1', url_for(@routes, { :controller => 'posts', :action => 'show', :id => '1', :ws => true }) - assert_equal '/ws/posts', url_for(@routes, { :controller => 'posts', :action => 'index', :ws => true }) - - assert_equal '/account', url_for(@routes, { :controller => 'account', :action => 'subscription' }) - assert_equal '/account/billing', url_for(@routes, { :controller => 'account', :action => 'billing' }) - - assert_equal '/pages/1/notes/show/1', url_for(@routes, { :page_id => '1', :controller => 'notes', :action => 'show', :id => '1' }) - assert_equal '/pages/1/notes/list', url_for(@routes, { :page_id => '1', :controller => 'notes', :action => 'list' }) - assert_equal '/pages/1/notes', url_for(@routes, { :page_id => '1', :controller => 'notes', :action => 'index' }) - assert_equal '/pages/1/notes', url_for(@routes, { :page_id => '1', :controller => 'notes' }) - assert_equal '/notes', url_for(@routes, { :page_id => nil, :controller => 'notes' }) - assert_equal '/notes', url_for(@routes, { :controller => 'notes' }) - assert_equal '/notes/print', url_for(@routes, { :controller => 'notes', :action => 'print' }) - assert_equal '/notes/print', url_for(@routes, {}, { :controller => 'notes', :action => 'print' }) - - assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes' }, { :controller => 'notes', :id => '1' }) - assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes' }, { :controller => 'notes', :id => '1', :foo => 'bar' }) - assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes' }, { :controller => 'notes', :id => '1' }) - assert_equal '/notes/index/1', url_for(@routes, { :action => 'index' }, { :controller => 'notes', :id => '1' }) - assert_equal '/notes/index/1', url_for(@routes, {}, { :controller => 'notes', :id => '1' }) - assert_equal '/notes/show/1', url_for(@routes, {}, { :controller => 'notes', :action => 'show', :id => '1' }) - assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes', :id => '1' }, { :foo => 'bar' }) - assert_equal '/posts', url_for(@routes, { :controller => 'posts' }, { :controller => 'notes', :action => 'show', :id => '1' }) - assert_equal '/notes/list', url_for(@routes, { :action => 'list' }, { :controller => 'notes', :action => 'show', :id => '1' }) - - assert_equal '/posts/ping', url_for(@routes, { :controller => 'posts', :action => 'ping' }) - assert_equal '/posts/show/1', url_for(@routes, { :controller => 'posts', :action => 'show', :id => '1' }) - assert_equal '/posts', url_for(@routes, { :controller => 'posts' }) - assert_equal '/posts', url_for(@routes, { :controller => 'posts', :action => 'index' }) - assert_equal '/posts', url_for(@routes, { :controller => 'posts' }, { :controller => 'posts', :action => 'index' }) - assert_equal '/posts/create', url_for(@routes, { :action => 'create' }, { :controller => 'posts' }) - assert_equal '/posts?foo=bar', url_for(@routes, { :controller => 'posts', :foo => 'bar' }) - assert_equal '/posts?foo%5B%5D=bar&foo%5B%5D=baz', url_for(@routes, { :controller => 'posts', :foo => ['bar', 'baz'] }) - assert_equal '/posts?page=2', url_for(@routes, { :controller => 'posts', :page => 2 }) - assert_equal '/posts?q%5Bfoo%5D%5Ba%5D=b', url_for(@routes, { :controller => 'posts', :q => { :foo => { :a => 'b'}} }) - - assert_equal '/news.rss', url_for(@routes, { :controller => 'news', :action => 'index', :format => 'rss' }) - - - assert_raise(ActionController::RoutingError) { url_for(@routes, { :action => 'index' }) } - end - def test_generate_extras assert_equal ['/people', []], @routes.generate_extras(:controller => 'people') assert_equal ['/people', [:foo]], @routes.generate_extras(:controller => 'people', :foo => 'bar') diff --git a/actionpack/test/controller/runner_test.rb b/actionpack/test/controller/runner_test.rb index 24c220dcd5..3e9383abb2 100644 --- a/actionpack/test/controller/runner_test.rb +++ b/actionpack/test/controller/runner_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'action_dispatch/testing/integration' module ActionDispatch - class RunnerTest < Test::Unit::TestCase + class RunnerTest < ActiveSupport::TestCase class MyRunner include Integration::Runner diff --git a/actionpack/test/controller/selector_test.rb b/actionpack/test/controller/selector_test.rb index 8ce9e43402..5e302da212 100644 --- a/actionpack/test/controller/selector_test.rb +++ b/actionpack/test/controller/selector_test.rb @@ -7,7 +7,7 @@ require 'abstract_unit' require 'controller/fake_controllers' require 'action_controller/vendor/html-scanner' -class SelectorTest < Test::Unit::TestCase +class SelectorTest < ActiveSupport::TestCase # # Basic selector: element, id, class, attributes. # diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index c7c8360ae6..6fc3556e31 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -23,10 +23,6 @@ class SendFileController < ActionController::Base def data send_data(file_data, options) end - - def multibyte_text_data - send_data("Кирилица\n祝您好運.", options) - end end class SendFileTest < ActionController::TestCase @@ -61,7 +57,7 @@ class SendFileTest < ActionController::TestCase require 'stringio' output = StringIO.new output.binmode - output.string.force_encoding(file_data.encoding) if output.string.respond_to?(:force_encoding) + output.string.force_encoding(file_data.encoding) assert_nothing_raised { response.body_parts.each { |part| output << part.to_s } } assert_equal file_data, output.string end @@ -138,6 +134,36 @@ class SendFileTest < ActionController::TestCase @controller.headers = {} assert_raise(ArgumentError){ @controller.send(:send_file_headers!, options) } end + + def test_send_file_headers_guess_type_from_extension + { + 'image.png' => 'image/png', + 'image.jpeg' => 'image/jpeg', + 'image.jpg' => 'image/jpeg', + 'image.tif' => 'image/tiff', + 'image.gif' => 'image/gif', + 'movie.mpg' => 'video/mpeg', + 'file.zip' => 'application/zip', + 'file.unk' => 'application/octet-stream', + 'zip' => 'application/octet-stream' + }.each do |filename,expected_type| + options = { :filename => filename } + @controller.headers = {} + @controller.send(:send_file_headers!, options) + assert_equal expected_type, @controller.content_type + end + end + + def test_send_file_with_default_content_disposition_header + process('data') + assert_equal 'attachment', @controller.headers['Content-Disposition'] + end + + def test_send_file_without_content_disposition_header + @controller.options = {:disposition => nil} + process('data') + assert_nil @controller.headers['Content-Disposition'] + end %w(file data).each do |method| define_method "test_send_#{method}_status" do diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb new file mode 100644 index 0000000000..13ab19ed8f --- /dev/null +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -0,0 +1,71 @@ +require 'abstract_unit' + +module ShowExceptions + class ShowExceptionsController < ActionController::Base + use ActionDispatch::ShowExceptions, ActionDispatch::PublicExceptions.new("#{FIXTURE_LOAD_PATH}/public") + use ActionDispatch::DebugExceptions + + before_filter :only => :another_boom do + request.env["action_dispatch.show_detailed_exceptions"] = true + end + + def boom + raise 'boom!' + end + + def another_boom + raise 'boom!' + end + + def show_detailed_exceptions? + request.local? + end + end + + class ShowExceptionsTest < ActionDispatch::IntegrationTest + test 'show error page from a remote ip' do + @app = ShowExceptionsController.action(:boom) + self.remote_addr = '208.77.188.166' + get '/' + assert_equal "500 error fixture\n", body + end + + test 'show diagnostics from a local ip if show_detailed_exceptions? is set to request.local?' do + @app = ShowExceptionsController.action(:boom) + ['127.0.0.1', '127.0.0.127', '::1', '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1%0'].each do |ip_address| + self.remote_addr = ip_address + get '/' + assert_match(/boom/, body) + end + end + + test 'show diagnostics from a remote ip when env is already set' do + @app = ShowExceptionsController.action(:another_boom) + self.remote_addr = '208.77.188.166' + get '/' + assert_match(/boom/, body) + end + end + + class ShowExceptionsOverridenController < ShowExceptionsController + private + + def show_detailed_exceptions? + params['detailed'] == '1' + end + end + + class ShowExceptionsOverridenTest < ActionDispatch::IntegrationTest + test 'show error page' do + @app = ShowExceptionsOverridenController.action(:boom) + get '/', {'detailed' => '0'} + assert_equal "500 error fixture\n", body + end + + test 'show diagnostics message' do + @app = ShowExceptionsOverridenController.action(:boom) + get '/', {'detailed' => '1'} + assert_match(/boom/, body) + end + end +end diff --git a/actionpack/test/controller/sweeper_test.rb b/actionpack/test/controller/sweeper_test.rb new file mode 100644 index 0000000000..0561efc62f --- /dev/null +++ b/actionpack/test/controller/sweeper_test.rb @@ -0,0 +1,16 @@ +require 'abstract_unit' + + +class SweeperTest < ActionController::TestCase + + class ::AppSweeper < ActionController::Caching::Sweeper; end + + def test_sweeper_should_not_ignore_unknown_method_calls + sweeper = ActionController::Caching::Sweeper.send(:new) + assert_raise NameError do + sweeper.instance_eval do + some_method_that_doesnt_exist + end + end + end +end diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_case_test.rb index 5896222a0a..0d6d303b51 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -1,8 +1,7 @@ require 'abstract_unit' require 'controller/fake_controllers' -require 'active_support/ordered_hash' -class TestTest < ActionController::TestCase +class TestCaseTest < ActionController::TestCase class TestController < ActionController::Base def no_op render :text => 'dummy' @@ -46,10 +45,18 @@ class TestTest < ActionController::TestCase render :text => request.fullpath end + def test_format + render :text => request.format + end + def test_query_string render :text => request.query_string end + def test_protocol + render :text => request.protocol + end + def test_html_output render :text => <<HTML <html> @@ -116,13 +123,11 @@ XML def test_assigns @foo = "foo" + @foo_hash = {:foo => :bar} render :nothing => true end private - def rescue_action(e) - raise e - end def generate_url(opts) url_for(opts.merge(:action => "test_uri")) @@ -137,38 +142,73 @@ XML @request.env['PATH_INFO'] = nil @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| r.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end end + class ViewAssignsController < ActionController::Base + def test_assigns + @foo = "foo" + render :nothing => true + end + + def view_assigns + { "bar" => "bar" } + end + end + def test_raw_post_handling - params = ActiveSupport::OrderedHash[:page, {:name => 'page name'}, 'some key', 123] + params = Hash[: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 = ActiveSupport::OrderedHash[:page, { :name => 'page name' }, 'some key', 123] + params = Hash[:page, { :name => 'page name' }, 'some key', 123] post :render_body, params.dup assert_equal params.to_query, @response.body end + def test_document_body_and_params_with_post + post :test_params, :id => 1 + assert_equal("{\"id\"=>\"1\", \"controller\"=>\"test_case_test/test\", \"action\"=>\"test_params\"}", @response.body) + end + + def test_document_body_with_post + post :render_body, "document body" + assert_equal "document body", @response.body + end + + def test_document_body_with_put + put :render_body, "document body" + assert_equal "document body", @response.body + end + + def test_head + head :test_params + assert_equal 200, @response.status + end + + def test_head_params_as_sting + assert_raise(NoMethodError) { head :test_params, "document body", :id => 10 } + 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" } + process :set_flash, "GET", nil, nil, { "test" => "value" } assert_equal '>value<', flash['test'] end def test_process_with_flash_now - process :set_flash_now, nil, nil, { "test_now" => "value_now" } + process :set_flash_now, "GET", nil, nil, { "test_now" => "value_now" } assert_equal '>value_now<', flash['test_now'] end @@ -181,13 +221,33 @@ XML end def test_process_with_session_arg - process :no_op, nil, { 'string' => 'value1', :symbol => 'value2' } + process :no_op, "GET", nil, { 'string' => 'value1', :symbol => 'value2' } assert_equal 'value1', session['string'] assert_equal 'value1', session[:string] assert_equal 'value2', session['symbol'] assert_equal 'value2', session[:symbol] end + def test_process_merges_session_arg + session[:foo] = 'bar' + get :no_op, nil, { :bar => 'baz' } + assert_equal 'bar', session[:foo] + assert_equal 'baz', session[:bar] + end + + def test_merged_session_arg_is_retained_across_requests + get :no_op, nil, { :foo => 'bar' } + assert_equal 'bar', session[:foo] + get :no_op + assert_equal 'bar', session[:foo] + end + + def test_process_overwrites_existing_session_arg + session[:foo] = 'bar' + get :no_op, nil, { :foo => 'baz' } + assert_equal 'baz', session[:foo] + end + def test_session_is_cleared_from_controller_after_reset_session process :set_session process :reset_the_session @@ -208,22 +268,29 @@ XML def test_process_with_request_uri_with_no_params process :test_uri - assert_equal "/test_test/test/test_uri", @response.body + assert_equal "/test_case_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 + process :test_uri, "GET", :id => 7 + assert_equal "/test_case_test/test/test_uri/7", @response.body + end + + def test_process_with_old_api + assert_deprecated do + process :test_uri, :id => 7 + assert_equal "/test_case_test/test/test_uri/7", @response.body + end end def test_process_with_request_uri_with_params_with_explicit_uri @request.env['PATH_INFO'] = "/explicit/uri" - process :test_uri, :id => 7 + process :test_uri, "GET", :id => 7 assert_equal "/explicit/uri", @response.body end def test_process_with_query_string - process :test_query_string, :q => 'test' + process :test_query_string, "GET", :q => 'test' assert_equal "q=test", @response.body end @@ -235,9 +302,9 @@ XML end def test_multiple_calls - process :test_only_one_param, :left => true + process :test_only_one_param, "GET", :left => true assert_equal "OK", @response.body - process :test_only_one_param, :right => true + process :test_only_one_param, "GET", :right => true assert_equal "OK", @response.body end @@ -250,6 +317,19 @@ XML assert_equal "foo", assigns("foo") assert_equal "foo", assigns[:foo] assert_equal "foo", assigns["foo"] + + # but the assigned variable should not have its own keys stringified + expected_hash = { :foo => :bar } + assert_equal expected_hash, assigns(:foo_hash) + end + + def test_view_assigns + @controller = ViewAssignsController.new + process :test_assigns + assert_equal nil, assigns(:foo) + assert_equal nil, assigns[:foo] + assert_equal "bar", assigns(:bar) + assert_equal "bar", assigns[:bar] end def test_assert_tag_tag @@ -468,7 +548,7 @@ XML with_routing do |set| set.draw do namespace :admin do - match 'user' => 'user#index' + get 'user' => 'user#index' end end @@ -478,7 +558,7 @@ XML def test_assert_routing_with_glob with_routing do |set| - set.draw { match('*path' => "pages#show") } + set.draw { get('*path' => "pages#show") } assert_routing('/company/about', { :controller => 'pages', :action => 'show', :path => 'company/about' }) end end @@ -487,24 +567,60 @@ XML 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', + {'controller' => 'test_case_test/test', 'action' => 'test_params', 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}}, parsed_params ) end + def test_params_passing_with_fixnums + get :test_params, :page => {:name => "Page name", :month => 4, :year => 2004, :day => 6} + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}}, + parsed_params + ) + end + + def test_params_passing_with_fixnums_when_not_html_request + get :test_params, :format => 'json', :count => 999 + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'format' => 'json', 'count' => 999 }, + parsed_params + ) + end + + def test_params_passing_path_parameter_is_string_when_not_html_request + get :test_params, :format => 'json', :id => 1 + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'format' => 'json', 'id' => '1' }, + parsed_params + ) + end + def test_params_passing_with_frozen_values assert_nothing_raised do - get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze + get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze, :deepfreeze => { :frozen => 'icy'.freeze }.freeze end parsed_params = eval(@response.body) assert_equal( - {'controller' => 'test_test/test', 'action' => 'test_params', - 'frozen' => 'icy', 'frozens' => ['icy']}, + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'frozen' => 'icy', 'frozens' => ['icy'], 'deepfreeze' => { 'frozen' => 'icy' }}, parsed_params ) end + def test_params_passing_doesnt_modify_in_place + page = {:name => "Page name", :month => 4, :year => 2004, :day => 6} + get :test_params, :page => page + assert_equal 2004, page[:year] + end + def test_id_converted_to_string get :test_params, :id => 20, :foo => Object.new assert_kind_of String, @request.path_parameters['id'] @@ -513,8 +629,8 @@ XML def test_array_path_parameter_handled_properly with_routing do |set| set.draw do - match 'file/*path', :to => 'test_test/test#test_params' - match ':controller/:action' + get 'file/*path', :to => 'test_case_test/test#test_params' + get ':controller/:action' end get :test_params, :path => ['hello', 'world'] @@ -582,14 +698,41 @@ XML assert_nil @request.symbolized_path_parameters[:id] end + def test_request_protocol_is_reset_after_request + get :test_protocol + assert_equal "http://", @response.body + + @request.env["HTTPS"] = "on" + get :test_protocol + assert_equal "https://", @response.body + + @request.env.delete("HTTPS") + get :test_protocol + assert_equal "http://", @response.body + end + + def test_request_format + get :test_format, :format => 'html' + assert_equal 'text/html', @response.body + + get :test_format, :format => 'json' + assert_equal 'application/json', @response.body + + get :test_format, :format => 'xml' + assert_equal 'application/xml', @response.body + + get :test_format + assert_equal 'text/html', @response.body + end + def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set - @request.cookies['foo'] = 'bar' + cookies['foo'] = 'bar' get :no_op assert_equal 'bar', cookies['foo'] end def test_should_detect_if_cookie_is_deleted - @request.cookies['foo'] = 'bar' + cookies['foo'] = 'bar' get :delete_cookie assert_nil cookies['foo'] end @@ -602,7 +745,6 @@ XML 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}" @@ -613,20 +755,15 @@ XML FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart' - if RUBY_VERSION < '1.9' - READ_BINARY = 'rb' - READ_PLAIN = 'r' - else - READ_BINARY = 'rb:binary' - READ_PLAIN = 'r:binary' - end + READ_BINARY = 'rb:binary' + READ_PLAIN = 'r:binary' def test_test_uploaded_file filename = 'mona_lisa.jpg' path = "#{FILES_DIR}/#{filename}" content_type = 'image/png' expected = File.read(path) - expected.force_encoding(Encoding::BINARY) if expected.respond_to?(:force_encoding) + expected.force_encoding(Encoding::BINARY) file = Rack::Test::UploadedFile.new(path, content_type) assert_equal filename, file.original_filename @@ -640,6 +777,13 @@ XML end + def test_fixture_path_is_accessed_from_self_instead_of_active_support_test_case + TestCaseTest.stubs(:fixture_path).returns(FILES_DIR) + + uploaded_file = fixture_file_upload('/mona_lisa.jpg', 'image/png') + assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read + end + def test_test_uploaded_file_with_binary filename = 'mona_lisa.jpg' path = "#{FILES_DIR}/#{filename}" @@ -715,6 +859,22 @@ class CrazyNameTest < ActionController::TestCase end end +class CrazySymbolNameTest < ActionController::TestCase + tests :content + + def test_set_controller_class_using_symbol + assert_equal ContentController, self.class.controller_class + end +end + +class CrazyStringNameTest < ActionController::TestCase + tests 'content' + + def test_set_controller_class_using_string + assert_equal ContentController, self.class.controller_class + end +end + class NamedRoutesControllerTest < ActionController::TestCase tests ContentController @@ -726,3 +886,24 @@ class NamedRoutesControllerTest < ActionController::TestCase end end end + +class AnonymousControllerTest < ActionController::TestCase + def setup + @controller = Class.new(ActionController::Base) do + def index + render :text => params[:controller] + end + end.new + + @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| + r.draw do + get ':controller(/:action(/:id))' + end + end + end + + def test_controller_name + get :index + assert_equal 'anonymous', @response.body + end +end
\ No newline at end of file diff --git a/actionpack/test/controller/url_for_integration_test.rb b/actionpack/test/controller/url_for_integration_test.rb new file mode 100644 index 0000000000..6c2311e7a5 --- /dev/null +++ b/actionpack/test/controller/url_for_integration_test.rb @@ -0,0 +1,177 @@ +# encoding: utf-8 +require 'abstract_unit' +require 'controller/fake_controllers' +require 'active_support/core_ext/object/with_options' + +module ActionPack + class URLForIntegrationTest < ActiveSupport::TestCase + include RoutingTestHelpers + + Model = Struct.new(:to_param) + + Mapping = lambda { + namespace :admin do + resources :users, :posts + end + + namespace 'api' do + root :to => 'users#index' + end + + get '/blog(/:year(/:month(/:day)))' => 'posts#show_date', + :constraints => { + :year => /(19|20)\d\d/, + :month => /[01]?\d/, + :day => /[0-3]?\d/ + }, + :day => nil, + :month => nil + + get 'archive/:year', :controller => 'archive', :action => 'index', + :defaults => { :year => nil }, + :constraints => { :year => /\d{4}/ }, + :as => "blog" + + resources :people + #match 'legacy/people' => "people#index", :legacy => "true" + + get 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol + get 'id_default(/:id)' => "foo#id_default", :id => 1 + match 'get_or_post' => "foo#get_or_post", :via => [:get, :post] + get 'optional/:optional' => "posts#index" + get 'projects/:project_id' => "project#index", :as => "project" + get 'clients' => "projects#index" + + get 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i + get 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { + :postalcode => /# Postcode format + \d{5} #Prefix + (-\d{4})? #Suffix + /x + }, :as => "geocode" + + get 'news(.:format)' => "news#index" + + get 'comment/:id(/:action)' => "comments#show" + get 'ws/:controller(/:action(/:id))', :ws => true + get 'account(/:action)' => "account#subscription" + get 'pages/:page_id/:controller(/:action(/:id))' + get ':controller/ping', :action => 'ping' + get ':controller(/:action(/:id))(.:format)' + root :to => "news#index" + } + + def setup + @routes = ActionDispatch::Routing::RouteSet.new + @routes.draw(&Mapping) + end + + [ + ['/admin/users',[ { :use_route => 'admin_users' }]], + ['/admin/users',[ { :controller => 'admin/users' }]], + ['/admin/users',[ { :controller => 'admin/users', :action => 'index' }]], + ['/admin/users',[ { :action => 'index' }, { :controller => 'admin/users' }]], + ['/admin/users',[ { :controller => 'users', :action => 'index' }, { :controller => 'admin/accounts' }]], + ['/people',[ { :controller => '/people', :action => 'index' }, { :controller => 'admin/accounts' }]], + + ['/admin/posts',[ { :controller => 'admin/posts' }]], + ['/admin/posts/new',[ { :controller => 'admin/posts', :action => 'new' }]], + + ['/blog/2009',[ { :controller => 'posts', :action => 'show_date', :year => 2009 }]], + ['/blog/2009/1',[ { :controller => 'posts', :action => 'show_date', :year => 2009, :month => 1 }]], + ['/blog/2009/1/1',[ { :controller => 'posts', :action => 'show_date', :year => 2009, :month => 1, :day => 1 }]], + + ['/archive/2010',[ { :controller => 'archive', :action => 'index', :year => '2010' }]], + ['/archive',[ { :controller => 'archive', :action => 'index' }]], + ['/archive?year=january',[ { :controller => 'archive', :action => 'index', :year => 'january' }]], + + ['/people',[ { :controller => 'people', :action => 'index' }]], + ['/people',[ { :action => 'index' }, { :controller => 'people' }]], + ['/people',[ { :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people',[ { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people',[ {}, { :controller => 'people', :action => 'index' }]], + ['/people/1',[ { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people/new',[ { :use_route => 'new_person' }]], + ['/people/new',[ { :controller => 'people', :action => 'new' }]], + ['/people/1',[ { :use_route => 'person', :id => '1' }]], + ['/people/1',[ { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people/1.xml',[ { :controller => 'people', :action => 'show', :id => '1', :format => 'xml' }]], + ['/people/1',[ { :controller => 'people', :action => 'show', :id => 1 }]], + ['/people/1',[ { :controller => 'people', :action => 'show', :id => Model.new('1') }]], + ['/people/1',[ { :action => 'show', :id => '1' }, { :controller => 'people', :action => 'index' }]], + ['/people/1',[ { :action => 'show', :id => 1 }, { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people',[ { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people/1',[ {}, { :controller => 'people', :action => 'show', :id => '1' }]], + ['/people/1',[ { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'index', :id => '1' }]], + ['/people/1/edit',[ { :controller => 'people', :action => 'edit', :id => '1' }]], + ['/people/1/edit.xml',[ { :controller => 'people', :action => 'edit', :id => '1', :format => 'xml' }]], + ['/people/1/edit',[ { :use_route => 'edit_person', :id => '1' }]], + ['/people/1?legacy=true',[ { :controller => 'people', :action => 'show', :id => '1', :legacy => 'true' }]], + ['/people?legacy=true',[ { :controller => 'people', :action => 'index', :legacy => 'true' }]], + + ['/id_default/2',[ { :controller => 'foo', :action => 'id_default', :id => '2' }]], + ['/id_default',[ { :controller => 'foo', :action => 'id_default', :id => '1' }]], + ['/id_default',[ { :controller => 'foo', :action => 'id_default', :id => 1 }]], + ['/id_default',[ { :controller => 'foo', :action => 'id_default' }]], + ['/optional/bar',[ { :controller => 'posts', :action => 'index', :optional => 'bar' }]], + ['/posts',[ { :controller => 'posts', :action => 'index' }]], + + ['/project',[ { :controller => 'project', :action => 'index' }]], + ['/projects/1',[ { :controller => 'project', :action => 'index', :project_id => '1' }]], + ['/projects/1',[ { :controller => 'project', :action => 'index'}, {:project_id => '1' }]], + ['/projects/1',[ { :use_route => 'project', :controller => 'project', :action => 'index', :project_id => '1' }]], + ['/projects/1',[ { :use_route => 'project', :controller => 'project', :action => 'index' }, { :project_id => '1' }]], + + ['/clients',[ { :controller => 'projects', :action => 'index' }]], + ['/clients?project_id=1',[ { :controller => 'projects', :action => 'index', :project_id => '1' }]], + ['/clients',[ { :controller => 'projects', :action => 'index' }, { :project_id => '1' }]], + ['/clients',[ { :action => 'index' }, { :controller => 'projects', :action => 'index', :project_id => '1' }]], + + ['/comment/20',[ { :id => 20 }, { :controller => 'comments', :action => 'show' }]], + ['/comment/20',[ { :controller => 'comments', :id => 20, :action => 'show' }]], + ['/comments/boo',[ { :controller => 'comments', :action => 'boo' }]], + + ['/ws/posts/show/1',[ { :controller => 'posts', :action => 'show', :id => '1', :ws => true }]], + ['/ws/posts',[ { :controller => 'posts', :action => 'index', :ws => true }]], + + ['/account',[ { :controller => 'account', :action => 'subscription' }]], + ['/account/billing',[ { :controller => 'account', :action => 'billing' }]], + + ['/pages/1/notes/show/1',[ { :page_id => '1', :controller => 'notes', :action => 'show', :id => '1' }]], + ['/pages/1/notes/list',[ { :page_id => '1', :controller => 'notes', :action => 'list' }]], + ['/pages/1/notes',[ { :page_id => '1', :controller => 'notes', :action => 'index' }]], + ['/pages/1/notes',[ { :page_id => '1', :controller => 'notes' }]], + ['/notes',[ { :page_id => nil, :controller => 'notes' }]], + ['/notes',[ { :controller => 'notes' }]], + ['/notes/print',[ { :controller => 'notes', :action => 'print' }]], + ['/notes/print',[ {}, { :controller => 'notes', :action => 'print' }]], + + ['/notes/index/1',[ { :controller => 'notes' }, { :controller => 'notes', :id => '1' }]], + ['/notes/index/1',[ { :controller => 'notes' }, { :controller => 'notes', :id => '1', :foo => 'bar' }]], + ['/notes/index/1',[ { :controller => 'notes' }, { :controller => 'notes', :id => '1' }]], + ['/notes/index/1',[ { :action => 'index' }, { :controller => 'notes', :id => '1' }]], + ['/notes/index/1',[ {}, { :controller => 'notes', :id => '1' }]], + ['/notes/show/1',[ {}, { :controller => 'notes', :action => 'show', :id => '1' }]], + ['/notes/index/1',[ { :controller => 'notes', :id => '1' }, { :foo => 'bar' }]], + ['/posts',[ { :controller => 'posts' }, { :controller => 'notes', :action => 'show', :id => '1' }]], + ['/notes/list',[ { :action => 'list' }, { :controller => 'notes', :action => 'show', :id => '1' }]], + + ['/posts/ping',[ { :controller => 'posts', :action => 'ping' }]], + ['/posts/show/1',[ { :controller => 'posts', :action => 'show', :id => '1' }]], + ['/posts',[ { :controller => 'posts' }]], + ['/posts',[ { :controller => 'posts', :action => 'index' }]], + ['/posts',[ { :controller => 'posts' }, { :controller => 'posts', :action => 'index' }]], + ['/posts/create',[ { :action => 'create' }, { :controller => 'posts' }]], + ['/posts?foo=bar',[ { :controller => 'posts', :foo => 'bar' }]], + ['/posts?foo%5B%5D=bar&foo%5B%5D=baz', [{ :controller => 'posts', :foo => ['bar', 'baz'] }]], + ['/posts?page=2', [{ :controller => 'posts', :page => 2 }]], + ['/posts?q%5Bfoo%5D%5Ba%5D=b', [{ :controller => 'posts', :q => { :foo => { :a => 'b'}} }]], + + ['/news.rss', [{ :controller => 'news', :action => 'index', :format => 'rss' }]], + ].each_with_index do |(url, params), i| + define_method("test_#{url.gsub(/\W/, '_')}_#{i}") do + assert_equal url, url_for(@routes, *params), params.inspect + end + end + end +end diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index 3f3d6dcc2f..b2cb5f80d5 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -5,7 +5,7 @@ module AbstractController class UrlForTests < ActionController::TestCase class W - include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { match ':controller(/:action(/:id(.:format)))' } }.url_helpers + include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { get ':controller(/:action(/:id(.:format)))' } }.url_helpers end def teardown @@ -16,6 +16,14 @@ module AbstractController W.default_url_options[:host] = 'www.basecamphq.com' end + def add_port! + W.default_url_options[:port] = 3000 + end + + def add_numeric_host! + W.default_url_options[:host] = '127.0.0.1' + end + def test_exception_is_thrown_without_host assert_raise ArgumentError do W.new.url_for :controller => 'c', :action => 'a', :id => 'i' @@ -67,6 +75,35 @@ module AbstractController ) end + def test_subdomain_may_be_object + model = mock(:to_param => 'api') + add_host! + assert_equal('http://api.basecamphq.com/c/a/i', + W.new.url_for(:subdomain => model, :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_subdomain_may_be_removed + add_host! + assert_equal('http://basecamphq.com/c/a/i', + W.new.url_for(:subdomain => false, :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_multiple_subdomains_may_be_removed + W.default_url_options[:host] = 'mobile.www.api.basecamphq.com' + assert_equal('http://basecamphq.com/c/a/i', + W.new.url_for(:subdomain => false, :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_subdomain_may_be_accepted_with_numeric_host + add_numeric_host! + assert_equal('http://127.0.0.1/c/a/i', + W.new.url_for(:subdomain => 'api', :controller => 'c', :action => 'a', :id => 'i') + ) + end + def test_domain_may_be_changed add_host! assert_equal('http://www.37signals.com/c/a/i', @@ -88,6 +125,14 @@ module AbstractController ) end + def test_default_port + add_host! + add_port! + assert_equal('http://www.basecamphq.com:3000/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i') + ) + end + def test_protocol add_host! assert_equal('https://www.basecamphq.com/c/a/i', @@ -165,8 +210,8 @@ module AbstractController def test_named_routes with_routing do |set| set.draw do - match 'this/is/verbose', :to => 'home#index', :as => :no_args - match 'home/sweet/home/:user', :to => 'home#index', :as => :home + get 'this/is/verbose', :to => 'home#index', :as => :no_args + get 'home/sweet/home/:user', :to => 'home#index', :as => :home end # We need to create a new class in order to install the new named route. @@ -186,7 +231,7 @@ module AbstractController def test_relative_url_root_is_respected_for_named_routes with_routing do |set| set.draw do - match '/home/sweet/home/:user', :to => 'home#index', :as => :home + get '/home/sweet/home/:user', :to => 'home#index', :as => :home end kls = Class.new { include set.url_helpers } @@ -200,8 +245,8 @@ module AbstractController def test_only_path with_routing do |set| set.draw do - match 'home/sweet/home/:user', :to => 'home#index', :as => :home - match ':controller/:action/:id' + get 'home/sweet/home/:user', :to => 'home#index', :as => :home + get ':controller/:action/:id' end # We need to create a new class in order to install the new named route. @@ -268,8 +313,8 @@ module AbstractController def test_named_routes_with_nil_keys with_routing do |set| set.draw do - match 'posts.:format', :to => 'posts#index', :as => :posts - match '/', :to => 'posts#index', :as => :main + get 'posts.:format', :to => 'posts#index', :as => :posts + get '/', :to => 'posts#index', :as => :main end # We need to create a new class in order to install the new named route. @@ -293,8 +338,8 @@ module AbstractController first_class.default_url_options[:host] = first_host second_class.default_url_options[:host] = second_host - assert_equal first_class.default_url_options[:host], first_host - assert_equal second_class.default_url_options[:host], second_host + assert_equal first_host, first_class.default_url_options[:host] + assert_equal second_host, second_class.default_url_options[:host] end def test_with_stringified_keys diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index 89de4c1da4..cc3706aeee 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -21,7 +21,7 @@ class UrlRewriterTests < ActionController::TestCase @rewriter = Rewriter.new(@request) #.new(@request, @params) @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| r.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end end @@ -70,9 +70,9 @@ class UrlRewriterTests < ActionController::TestCase ) end - def test_anchor_should_be_cgi_escaped + def test_anchor_should_be_uri_escaped assert_equal( - 'http://test.host/c/a/i#anc%2Fhor', + 'http://test.host/c/a/i#anc/hor', @rewriter.rewrite(@routes, :controller => 'c', :action => 'a', :id => 'i', :anchor => Struct.new(:to_param).new('anc/hor')) ) end diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb index 3de1849db8..40f6dc6f0f 100644 --- a/actionpack/test/controller/view_paths_test.rb +++ b/actionpack/test/controller/view_paths_test.rb @@ -3,7 +3,6 @@ require 'abstract_unit' class ViewLoadPathsTest < ActionController::TestCase 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 @@ -16,33 +15,22 @@ class ViewLoadPathsTest < ActionController::TestCase end end - class Test::SubController < ActionController::Base - layout 'test/sub' - def hello_world; render(:template => 'test/hello_world'); end + module Test + class SubController < ActionController::Base + layout 'test/sub' + def hello_world; render(:template => 'test/hello_world'); end + end end def setup - # TestController.view_paths = nil - @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new - @controller = TestController.new - # Following is needed in order to setup @controller.template object properly - @controller.send :assign_shortcuts, @request, @response - @controller.send :initialize_template_class, @response - - # Track the last warning. - @old_behavior = ActiveSupport::Deprecation.behavior - @last_message = nil - ActiveSupport::Deprecation.behavior = Proc.new { |message, callback| @last_message = message } - @paths = TestController.view_paths end def teardown TestController.view_paths = @paths - ActiveSupport::Deprecation.behavior = @old_behavior end def expand(array) @@ -179,7 +167,7 @@ class ViewLoadPathsTest < ActionController::TestCase assert_nothing_raised { C.append_view_path 'c/path' } assert_paths C, "c/path" end - + def test_lookup_context_accessor assert_equal ["test"], TestController.new.lookup_context.prefixes end diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 621fb79915..c0b9833603 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -18,8 +18,6 @@ class WebServiceTest < ActionDispatch::IntegrationTest s << "#{k}#{value}" end end - - def rescue_action(e) raise end end def setup @@ -30,7 +28,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_check_parameters with_test_route_set do get "/" - assert_blank @controller.response.body + assert_equal '', @controller.response.body end end @@ -162,7 +160,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_use_xml_ximple_with_empty_request with_test_route_set do assert_nothing_raised { post "/", "", {'CONTENT_TYPE' => 'application/xml'} } - assert_blank @controller.response.body + assert_equal '', @controller.response.body end end @@ -256,7 +254,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match '/', :to => 'web_service_test/test#assign_parameters' + match '/', :to => 'web_service_test/test#assign_parameters', :via => :all end yield end diff --git a/actionpack/test/dispatch/callbacks_test.rb b/actionpack/test/dispatch/callbacks_test.rb index eed2eca2ab..f767b07e75 100644 --- a/actionpack/test/dispatch/callbacks_test.rb +++ b/actionpack/test/dispatch/callbacks_test.rb @@ -27,6 +27,12 @@ class DispatcherTest < ActiveSupport::TestCase dispatch assert_equal 4, Foo.a assert_equal 4, Foo.b + + dispatch do |env| + raise "error" + end rescue nil + assert_equal 6, Foo.a + assert_equal 6, Foo.b end def test_to_prepare_and_cleanup_delegation @@ -44,8 +50,9 @@ class DispatcherTest < ActiveSupport::TestCase private def dispatch(&block) - @dispatcher ||= ActionDispatch::Callbacks.new(block || DummyApp.new) - @dispatcher.call({'rack.input' => StringIO.new('')}) + ActionDispatch::Callbacks.new(block || DummyApp.new).call( + {'rack.input' => StringIO.new('')} + ) end end diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index e42c39f527..2467654a70 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -38,6 +38,8 @@ class CookiesTest < ActionController::TestCase head :ok end + alias delete_cookie logout + def delete_cookie_with_path cookies.delete("user_name", :path => '/beaten') head :ok @@ -148,12 +150,49 @@ class CookiesTest < ActionController::TestCase @request.host = "www.nextangle.com" end + def test_each + request.cookie_jar['foo'] = :bar + list = [] + request.cookie_jar.each do |k,v| + list << [k, v] + end + + assert_equal [['foo', :bar]], list + end + + def test_enumerable + request.cookie_jar['foo'] = :bar + actual = request.cookie_jar.map { |k,v| [k.to_s, v.to_s] } + assert_equal [['foo', 'bar']], actual + end + + def test_key_methods + assert !request.cookie_jar.key?(:foo) + assert !request.cookie_jar.has_key?("foo") + + request.cookie_jar[:foo] = :bar + assert request.cookie_jar.key?(:foo) + assert request.cookie_jar.has_key?("foo") + end + def test_setting_cookie get :authenticate assert_cookie_header "user_name=david; path=/" assert_equal({"user_name" => "david"}, @response.cookies) end + def test_setting_the_same_value_to_cookie + request.cookies[:user_name] = 'david' + get :authenticate + assert response.cookies.empty? + end + + def test_setting_the_same_value_to_permanent_cookie + request.cookies[:user_name] = 'Jamie' + get :set_permanent_cookie + assert response.cookies, 'user_name' => 'Jamie' + end + def test_setting_with_escapable_characters get :set_with_with_escapable_characters assert_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/" @@ -185,8 +224,8 @@ class CookiesTest < ActionController::TestCase assert_equal({"user_name" => "david"}, @response.cookies) end - def test_setting_cookie_with_secure_in_development - Rails.env.stubs(:development?).returns(true) + def test_setting_cookie_with_secure_when_always_write_cookie_is_true + ActionDispatch::Cookies::CookieJar.any_instance.stubs(:always_write_cookie).returns(true) get :authenticate_with_secure assert_cookie_header "user_name=david; path=/; secure" assert_equal({"user_name" => "david"}, @response.cookies) @@ -210,16 +249,37 @@ class CookiesTest < ActionController::TestCase end def test_expiring_cookie + request.cookies[:user_name] = 'Joe' get :logout assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" assert_equal({"user_name" => nil}, @response.cookies) end def test_delete_cookie_with_path + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_path assert_cookie_header "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT" end + def test_delete_unexisting_cookie + request.cookies.clear + get :delete_cookie + assert @response.cookies.empty? + end + + def test_deleted_cookie_predicate + cookies[:user_name] = 'Joe' + cookies.delete("user_name") + assert cookies.deleted?("user_name") + assert_equal false, cookies.deleted?("another") + end + + def test_deleted_cookie_predicate_with_mismatching_options + cookies[:user_name] = 'Joe' + cookies.delete("user_name", :path => "/path") + assert_equal false, cookies.deleted?("user_name", :path => "/different") + end + def test_cookies_persist_throughout_request response = get :authenticate assert response.headers["Set-Cookie"] =~ /user_name=david/ @@ -248,6 +308,7 @@ class CookiesTest < ActionController::TestCase end def test_delete_and_set_cookie + request.cookies[:user_name] = 'Joe' get :delete_and_set_cookie assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT" assert_equal({"user_name" => "david"}, @response.cookies) @@ -351,6 +412,7 @@ class CookiesTest < ActionController::TestCase end def test_deleting_cookie_with_all_domain_option + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domain assert_response :success assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" @@ -377,6 +439,7 @@ class CookiesTest < ActionController::TestCase end def test_deleting_cookie_with_all_domain_option_and_tld_length + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domain_and_tld assert_response :success assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" @@ -405,6 +468,7 @@ class CookiesTest < ActionController::TestCase def test_deletings_cookie_with_several_preset_domains_using_one_of_these_domains @request.host = "example2.com" + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domains assert_response :success assert_cookie_header "user_name=; domain=example2.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" @@ -412,72 +476,113 @@ class CookiesTest < ActionController::TestCase def test_deletings_cookie_with_several_preset_domains_using_other_domain @request.host = "other-domain.com" + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domains assert_response :success assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" end - def test_cookies_hash_is_indifferent_access - get :symbol_key - assert_equal "david", cookies[:user_name] - assert_equal "david", cookies['user_name'] - get :string_key - assert_equal "dhh", cookies[:user_name] - assert_equal "dhh", cookies['user_name'] + get :symbol_key + assert_equal "david", cookies[:user_name] + assert_equal "david", cookies['user_name'] + get :string_key + assert_equal "dhh", cookies[:user_name] + assert_equal "dhh", cookies['user_name'] end def test_setting_request_cookies_is_indifferent_access - @request.cookies.clear - @request.cookies[:user_name] = "andrew" + cookies.clear + cookies[:user_name] = "andrew" get :string_key_mock - assert_equal "david", cookies[:user_name] + assert_equal "david", cookies['user_name'] - @request.cookies.clear - @request.cookies['user_name'] = "andrew" + cookies.clear + cookies['user_name'] = "andrew" get :symbol_key_mock - assert_equal "david", cookies['user_name'] + assert_equal "david", cookies[:user_name] end def test_cookies_retained_across_requests get :symbol_key - assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"] + assert_cookie_header "user_name=david; path=/" assert_equal "david", cookies[:user_name] get :noop assert_nil @response.headers["Set-Cookie"] - assert_equal "user_name=david", @request.env['HTTP_COOKIE'] assert_equal "david", cookies[:user_name] get :noop assert_nil @response.headers["Set-Cookie"] - assert_equal "user_name=david", @request.env['HTTP_COOKIE'] assert_equal "david", cookies[:user_name] end def test_cookies_can_be_cleared get :symbol_key - assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"] assert_equal "david", cookies[:user_name] - @request.cookies.clear + cookies.clear get :noop - assert_nil @response.headers["Set-Cookie"] - assert_nil @request.env['HTTP_COOKIE'] assert_nil cookies[:user_name] get :symbol_key - assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"] assert_equal "david", cookies[:user_name] end - def test_cookies_are_escaped - @request.cookies[:user_ids] = '1;2' + def test_can_set_http_cookie_header + @request.env['HTTP_COOKIE'] = 'user_name=david' + get :noop + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + + get :noop + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + + @request.env['HTTP_COOKIE'] = 'user_name=andrew' + get :noop + assert_equal 'andrew', cookies['user_name'] + assert_equal 'andrew', cookies[:user_name] + end + + def test_can_set_request_cookies + @request.cookies['user_name'] = 'david' + get :noop + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + + get :noop + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + + @request.cookies[:user_name] = 'andrew' + get :noop + assert_equal 'andrew', cookies['user_name'] + assert_equal 'andrew', cookies[:user_name] + end + + def test_cookies_precedence_over_http_cookie + @request.env['HTTP_COOKIE'] = 'user_name=andrew' + get :authenticate + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + + get :noop + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + end + + def test_cookies_precedence_over_request_cookies + @request.cookies['user_name'] = 'andrew' + get :authenticate + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] + get :noop - assert_equal "user_ids=1%3B2", @request.env['HTTP_COOKIE'] - assert_equal "1;2", cookies[:user_ids] + assert_equal 'david', cookies['user_name'] + assert_equal 'david', cookies[:user_name] end private @@ -499,99 +604,3 @@ class CookiesTest < ActionController::TestCase end end end - -class CookiesIntegrationTest < ActionDispatch::IntegrationTest - SessionKey = '_myapp_session' - SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33' - - class TestController < ActionController::Base - def dont_set_cookies - head :ok - end - - def set_cookies - cookies["that"] = "hello" - head :ok - end - end - - def test_setting_cookies_raises_after_stream_back_to_client - with_test_route_set do - get '/set_cookies' - assert_raise(ActionDispatch::ClosedError) { - request.cookie_jar['alert'] = 'alert' - cookies['alert'] = 'alert' - } - end - end - - def test_setting_cookies_raises_after_stream_back_to_client_even_without_cookies - with_test_route_set do - get '/dont_set_cookies' - assert_raise(ActionDispatch::ClosedError) { - request.cookie_jar['alert'] = 'alert' - } - end - end - - def test_setting_permanent_cookies_raises_after_stream_back_to_client - with_test_route_set do - get '/set_cookies' - assert_raise(ActionDispatch::ClosedError) { - request.cookie_jar.permanent['alert'] = 'alert' - cookies['alert'] = 'alert' - } - end - end - - def test_setting_permanent_cookies_raises_after_stream_back_to_client_even_without_cookies - with_test_route_set do - get '/dont_set_cookies' - assert_raise(ActionDispatch::ClosedError) { - request.cookie_jar.permanent['alert'] = 'alert' - } - end - end - - def test_setting_signed_cookies_raises_after_stream_back_to_client - with_test_route_set do - get '/set_cookies' - assert_raise(ActionDispatch::ClosedError) { - request.cookie_jar.signed['alert'] = 'alert' - cookies['alert'] = 'alert' - } - end - end - - def test_setting_signed_cookies_raises_after_stream_back_to_client_even_without_cookies - with_test_route_set do - get '/dont_set_cookies' - assert_raise(ActionDispatch::ClosedError) { - request.cookie_jar.signed['alert'] = 'alert' - } - end - end - - private - - # Overwrite get to send SessionSecret in env hash - def get(path, parameters = nil, env = {}) - env["action_dispatch.secret_token"] ||= SessionSecret - super - end - - def with_test_route_set - with_routing do |set| - set.draw do - match ':action', :to => CookiesIntegrationTest::TestController - end - - @app = self.class.build_app(set) do |middleware| - middleware.use ActionDispatch::Cookies - middleware.delete "ActionDispatch::ShowExceptions" - end - - yield - end - end -end diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb new file mode 100644 index 0000000000..6ff651ad52 --- /dev/null +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -0,0 +1,163 @@ +require 'abstract_unit' + +class DebugExceptionsTest < ActionDispatch::IntegrationTest + + class Boomer + attr_accessor :closed + + def initialize(detailed = false) + @detailed = detailed + @closed = false + end + + def each + end + + def close + @closed = true + end + + def call(env) + env['action_dispatch.show_detailed_exceptions'] = @detailed + req = ActionDispatch::Request.new(env) + case req.path + when "/pass" + [404, { "X-Cascade" => "pass" }, self] + when "/not_found" + raise AbstractController::ActionNotFound + when "/runtime_error" + raise RuntimeError + when "/method_not_allowed" + raise ActionController::MethodNotAllowed + when "/not_implemented" + raise ActionController::NotImplemented + when "/unprocessable_entity" + raise ActionController::InvalidAuthenticityToken + when "/not_found_original_exception" + raise ActionView::Template::Error.new('template', AbstractController::ActionNotFound.new) + when "/bad_request" + raise ActionController::BadRequest + else + raise "puke!" + end + end + end + + ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false)) + DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true)) + + test 'skip diagnosis if not showing detailed exceptions' do + @app = ProductionApp + assert_raise RuntimeError do + get "/", {}, {'action_dispatch.show_exceptions' => true} + end + end + + test 'skip diagnosis if not showing exceptions' do + @app = DevelopmentApp + assert_raise RuntimeError do + get "/", {}, {'action_dispatch.show_exceptions' => false} + end + end + + test 'raise an exception on cascade pass' do + @app = ProductionApp + assert_raise ActionController::RoutingError do + get "/pass", {}, {'action_dispatch.show_exceptions' => true} + end + end + + test 'closes the response body on cascade pass' do + boomer = Boomer.new(false) + @app = ActionDispatch::DebugExceptions.new(boomer) + assert_raise ActionController::RoutingError do + get "/pass", {}, {'action_dispatch.show_exceptions' => true} + end + assert boomer.closed, "Expected to close the response body" + end + + test "rescue with diagnostics message" do + @app = DevelopmentApp + + get "/", {}, {'action_dispatch.show_exceptions' => true} + assert_response 500 + assert_match(/puke/, body) + + get "/not_found", {}, {'action_dispatch.show_exceptions' => true} + assert_response 404 + assert_match(/#{AbstractController::ActionNotFound.name}/, body) + + get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true} + assert_response 405 + assert_match(/ActionController::MethodNotAllowed/, body) + + get "/bad_request", {}, {'action_dispatch.show_exceptions' => true} + assert_response 400 + assert_match(/ActionController::BadRequest/, body) + end + + test "does not show filtered parameters" do + @app = DevelopmentApp + + get "/", {"foo"=>"bar"}, {'action_dispatch.show_exceptions' => true, + 'action_dispatch.parameter_filter' => [:foo]} + assert_response 500 + assert_match(""foo"=>"[FILTERED]"", body) + end + + test "show registered original exception for wrapped exceptions" do + @app = DevelopmentApp + + get "/not_found_original_exception", {}, {'action_dispatch.show_exceptions' => true} + assert_response 404 + assert_match(/AbstractController::ActionNotFound/, body) + end + + test "show the controller name in the diagnostics template when controller name is present" do + @app = DevelopmentApp + get("/runtime_error", {}, { + 'action_dispatch.show_exceptions' => true, + 'action_dispatch.request.parameters' => { + 'action' => 'show', + 'id' => 'unknown', + 'controller' => 'featured_tile' + } + }) + assert_response 500 + assert_match(/RuntimeError\n in FeaturedTileController/, body) + end + + test "sets the HTTP charset parameter" do + @app = DevelopmentApp + + get "/", {}, {'action_dispatch.show_exceptions' => true} + assert_equal "text/html; charset=utf-8", response.headers["Content-Type"] + end + + test 'uses logger from env' do + @app = DevelopmentApp + output = StringIO.new + get "/", {}, {'action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => Logger.new(output)} + assert_match(/puke/, output.rewind && output.read) + end + + test 'uses backtrace cleaner from env' do + @app = DevelopmentApp + cleaner = stub(:clean => ['passed backtrace cleaner']) + get "/", {}, {'action_dispatch.show_exceptions' => true, 'action_dispatch.backtrace_cleaner' => cleaner} + assert_match(/passed backtrace cleaner/, body) + end + + test 'logs exception backtrace when all lines silenced' do + output = StringIO.new + backtrace_cleaner = ActiveSupport::BacktraceCleaner.new + backtrace_cleaner.add_silencer { true } + + env = {'action_dispatch.show_exceptions' => true, + 'action_dispatch.logger' => Logger.new(output), + 'action_dispatch.backtrace_cleaner' => backtrace_cleaner} + + get "/", {}, env + assert_operator((output.rewind && output.read).lines.count, :>, 10) + end +end diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index ec6ba494dc..bc7cad8db5 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -13,4 +13,9 @@ class HeaderTest < ActiveSupport::TestCase assert_equal "text/plain", @headers["CONTENT_TYPE"] assert_equal "text/plain", @headers["HTTP_CONTENT_TYPE"] end + + test "fetch" do + assert_equal "text/plain", @headers.fetch("content-type", nil) + assert_equal "not found", @headers.fetch('not-found', 'not found') + end end diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb index b6c08ffc33..bd078d2b21 100644 --- a/actionpack/test/dispatch/mapper_test.rb +++ b/actionpack/test/dispatch/mapper_test.rb @@ -4,10 +4,12 @@ module ActionDispatch module Routing class MapperTest < ActiveSupport::TestCase class FakeSet - attr_reader :routes + attr_reader :routes, :draw_paths + alias :set :routes def initialize @routes = [] + @draw_paths = [] end def resources_path_names @@ -35,10 +37,17 @@ module ActionDispatch Mapper.new FakeSet.new end + def test_mapping_requirements + options = { :controller => 'foo', :action => 'bar', :via => :get } + m = Mapper::Mapping.new FakeSet.new, {}, '/store/:name(*rest)', options + _, _, requirements, _ = m.to_route + assert_equal(/.+?/, requirements[:rest]) + end + def test_map_slash fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/', :to => 'posts#index', :as => :main + mapper.get '/', :to => 'posts#index', :as => :main assert_equal '/', fakeset.conditions.first[:path_info] end @@ -47,14 +56,14 @@ module ActionDispatch mapper = Mapper.new fakeset # FIXME: is this a desired behavior? - mapper.match '/one/two/', :to => 'posts#index', :as => :main + mapper.get '/one/two/', :to => 'posts#index', :as => :main assert_equal '/one/two(.:format)', fakeset.conditions.first[:path_info] end def test_map_wildcard fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path', :to => 'pages#show' + mapper.get '/*path', :to => 'pages#show' assert_equal '/*path(.:format)', fakeset.conditions.first[:path_info] assert_equal(/.+?/, fakeset.requirements.first[:path]) end @@ -62,7 +71,7 @@ module ActionDispatch def test_map_wildcard_with_other_element fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path/foo/:bar', :to => 'pages#show' + mapper.get '/*path/foo/:bar', :to => 'pages#show' assert_equal '/*path/foo/:bar(.:format)', fakeset.conditions.first[:path_info] assert_nil fakeset.requirements.first[:path] end @@ -70,7 +79,7 @@ module ActionDispatch def test_map_wildcard_with_multiple_wildcard fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*foo/*bar', :to => 'pages#show' + mapper.get '/*foo/*bar', :to => 'pages#show' assert_equal '/*foo/*bar(.:format)', fakeset.conditions.first[:path_info] assert_nil fakeset.requirements.first[:foo] assert_equal(/.+?/, fakeset.requirements.first[:bar]) @@ -79,10 +88,17 @@ module ActionDispatch def test_map_wildcard_with_format_false fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path', :to => 'pages#show', :format => false + mapper.get '/*path', :to => 'pages#show', :format => false assert_equal '/*path', fakeset.conditions.first[:path_info] assert_nil fakeset.requirements.first[:path] end + + def test_map_wildcard_with_format_true + fakeset = FakeSet.new + mapper = Mapper.new fakeset + mapper.get '/*path', :to => 'pages#show', :format => true + assert_equal '/*path.:format', fakeset.conditions.first[:path_info] + end end end end diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb index 831f3db3e2..948a690979 100644 --- a/actionpack/test/dispatch/middleware_stack_test.rb +++ b/actionpack/test/dispatch/middleware_stack_test.rb @@ -45,7 +45,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BazMiddleware, @stack.last.klass assert_equal([true, {:foo => "bar"}], @stack.last.args) end - + test "use should push middleware class with block arguments onto the stack" do proc = Proc.new {} assert_difference "@stack.size" do @@ -54,7 +54,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BlockMiddleware, @stack.last.klass assert_equal proc, @stack.last.block end - + test "insert inserts middleware at the integer index" do @stack.insert(1, BazMiddleware) assert_equal BazMiddleware, @stack[1].klass @@ -81,6 +81,17 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BazMiddleware, @stack[0].klass end + test "swaps one middleware out for same middleware class" do + assert_equal FooMiddleware, @stack[0].klass + @stack.swap(FooMiddleware, FooMiddleware, Proc.new { |env| [500, {}, ['error!']] }) + assert_equal FooMiddleware, @stack[0].klass + end + + test "unshift adds a new middleware at the beginning of the stack" do + @stack.unshift :"MiddlewareStackTest::BazMiddleware" + assert_equal BazMiddleware, @stack.first.klass + end + test "raise an error on invalid index" do assert_raise RuntimeError do @stack.insert("HiyaMiddleware", BazMiddleware) diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 11cf68fdb3..e3f9faaa64 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -52,7 +52,7 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse application with trailing star" do accept = "application/*" - expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::RSS, Mime::ATOM, Mime::YAML, Mime::URL_ENCODED_FORM, Mime::JSON, Mime::PDF] + expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::RSS, Mime::ATOM, Mime::YAML, Mime::URL_ENCODED_FORM, Mime::JSON, Mime::PDF, Mime::ZIP] parsed = Mime::Type.parse(accept) assert_equal expect, parsed end @@ -69,6 +69,18 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal expect, Mime::Type.parse(accept) end + test "parse single media range with q" do + accept = "text/html;q=0.9" + expect = [Mime::HTML] + assert_equal expect, Mime::Type.parse(accept) + end + + test "parse arbitarry media type parameters" do + accept = 'multipart/form-data; boundary="simple boundary"' + expect = [Mime::MULTIPART_FORM] + assert_equal expect, Mime::Type.parse(accept) + end + # Accept header send with user HTTP_USER_AGENT: Sunrise/0.42j (Windows XP) test "parse broken acceptlines" do accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/*,,*/*;q=0.5" @@ -86,12 +98,43 @@ class MimeTypeTest < ActiveSupport::TestCase test "custom type" do begin - Mime::Type.register("image/gif", :gif) + Mime::Type.register("image/foo", :foo) assert_nothing_raised do - assert_equal Mime::GIF, Mime::SET.last + assert_equal Mime::FOO, Mime::SET.last + end + ensure + Mime::Type.unregister(:FOO) + end + end + + test "custom type with type aliases" do + begin + Mime::Type.register "text/foobar", :foobar, ["text/foo", "text/bar"] + %w[text/foobar text/foo text/bar].each do |type| + assert_equal Mime::FOOBAR, type end ensure - Mime::Type.unregister(:gif) + Mime::Type.unregister(:FOOBAR) + end + end + + test "custom type with extension aliases" do + begin + Mime::Type.register "text/foobar", :foobar, [], [:foo, "bar"] + %w[foobar foo bar].each do |extension| + assert_equal Mime::FOOBAR, Mime::EXTENSION_LOOKUP[extension] + end + ensure + Mime::Type.unregister(:FOOBAR) + end + end + + test "register alias" do + begin + Mime::Type.register_alias "application/xhtml+xml", :foobar + assert_equal Mime::HTML, Mime::EXTENSION_LOOKUP['foobar'] + ensure + Mime::Type.unregister(:FOOBAR) end end @@ -107,8 +150,10 @@ class MimeTypeTest < ActiveSupport::TestCase # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) } + types.each do |type| mime = Mime.const_get(type.to_s.upcase) + assert mime.respond_to?("#{type}?"), "#{mime.inspect} does not respond to #{type}?" assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?" invalid_types = types - [type] invalid_types.delete(:html) if Mime::Type.html_types.include?(type) diff --git a/actionpack/test/dispatch/mount_test.rb b/actionpack/test/dispatch/mount_test.rb index 1a032539b9..536e35ab2e 100644 --- a/actionpack/test/dispatch/mount_test.rb +++ b/actionpack/test/dispatch/mount_test.rb @@ -37,6 +37,11 @@ class TestRoutingMount < ActionDispatch::IntegrationTest assert_equal "/sprockets -- /omg", response.body end + def test_mounting_works_with_nested_script_name + get "/foo/sprockets/omg", {}, 'SCRIPT_NAME' => '/foo', 'PATH_INFO' => '/sprockets/omg' + assert_equal "/foo/sprockets -- /omg", response.body + end + def test_mounting_works_with_scope get "/its_a/sprocket/omg" assert_equal "/its_a/sprocket -- /omg", response.body @@ -51,4 +56,4 @@ class TestRoutingMount < ActionDispatch::IntegrationTest get "/fakeengine" assert_equal "OK", response.body end -end
\ No newline at end of file +end diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index b28a058250..ab2f7612ce 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -25,11 +25,12 @@ module TestGenerationPrefix @routes ||= begin routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/posts/:id", :to => "inside_engine_generating#show", :as => :post - match "/posts", :to => "inside_engine_generating#index", :as => :posts - match "/url_to_application", :to => "inside_engine_generating#url_to_application" - match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" - match "/conflicting_url", :to => "inside_engine_generating#conflicting" + get "/posts/:id", :to => "inside_engine_generating#show", :as => :post + get "/posts", :to => "inside_engine_generating#index", :as => :posts + get "/url_to_application", :to => "inside_engine_generating#url_to_application" + get "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" + get "/conflicting_url", :to => "inside_engine_generating#conflicting" + get "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test end routes @@ -50,10 +51,12 @@ module TestGenerationPrefix scope "/:omg", :omg => "awesome" do mount BlogEngine => "/blog", :as => "blog_engine" end - match "/generate", :to => "outside_engine_generating#index" - match "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine" - match "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for" - match "/conflicting_url", :to => "outside_engine_generating#conflicting" + get "/posts/:id", :to => "outside_engine_generating#post", :as => :post + get "/generate", :to => "outside_engine_generating#index" + get "/polymorphic_path_for_app", :to => "outside_engine_generating#polymorphic_path_for_app" + get "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine" + get "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for" + get "/conflicting_url", :to => "outside_engine_generating#conflicting" root :to => "outside_engine_generating#index" end @@ -101,6 +104,7 @@ module TestGenerationPrefix class ::OutsideEngineGeneratingController < ActionController::Base include BlogEngine.routes.mounted_helpers + include RailsApplication.routes.url_helpers def index render :text => blog_engine.post_path(:id => 1) @@ -110,6 +114,10 @@ module TestGenerationPrefix render :text => blog_engine.polymorphic_path(Post.new) end + def polymorphic_path_for_app + render :text => polymorphic_path(Post.new) + end + def polymorphic_with_url_for render :text => blog_engine.url_for(Post.new) end @@ -145,6 +153,8 @@ module TestGenerationPrefix RailsApplication.routes.default_url_options = {} end + include BlogEngine.routes.mounted_helpers + # Inside Engine test "[ENGINE] generating engine's url use SCRIPT_NAME from request" do get "/pure-awesomeness/blog/posts/1" @@ -201,12 +211,21 @@ module TestGenerationPrefix assert_equal "/awesome/blog/posts/1", last_response.body end + test "polymorphic_path_for_app" do + get "/polymorphic_path_for_app" + assert_equal "/posts/1", last_response.body + end + test "[APP] generating engine's url with url_for(@post)" do get "/polymorphic_with_url_for" assert_equal "http://example.org/awesome/blog/posts/1", last_response.body end # Inside any Object + test "[OBJECT] proxy route should override respond_to?() as expected" do + assert_respond_to blog_engine, :named_helper_that_should_be_invoked_only_in_respond_to_test_path + end + test "[OBJECT] generating engine's route includes prefix" do assert_equal "/awesome/blog/posts/1", engine_object.post_path(:id => 1) end @@ -263,7 +282,7 @@ module TestGenerationPrefix @routes ||= begin routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/posts/:id", :to => "posts#show", :as => :post + get "/posts/:id", :to => "posts#show", :as => :post end routes diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb index eaabc1feb3..ce9ccfcee8 100644 --- a/actionpack/test/dispatch/reloader_test.rb +++ b/actionpack/test/dispatch/reloader_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class ReloaderTest < Test::Unit::TestCase +class ReloaderTest < ActiveSupport::TestCase Reloader = ActionDispatch::Reloader def test_prepare_callbacks @@ -43,6 +43,29 @@ class ReloaderTest < Test::Unit::TestCase assert_respond_to body, :close end + def test_returned_body_object_always_responds_to_close_even_if_called_twice + body = call_and_return_body + assert_respond_to body, :close + body.close + + body = call_and_return_body + assert_respond_to body, :close + body.close + end + + def test_condition_specifies_when_to_reload + i, j = 0, 0, 0, 0 + Reloader.to_prepare { |*args| i += 1 } + Reloader.to_cleanup { |*args| j += 1 } + app = Reloader.new(lambda { |env| [200, {}, []] }, lambda { i < 3 }) + 5.times do + resp = app.call({}) + resp[2].close + end + assert_equal 3, i + assert_equal 3, j + end + def test_returned_body_object_behaves_like_underlying_object body = call_and_return_body do b = MyBody.new @@ -116,6 +139,15 @@ class ReloaderTest < Test::Unit::TestCase assert cleaned end + def test_prepend_prepare_callback + i = 10 + Reloader.to_prepare { i += 1 } + Reloader.to_prepare(:prepend => true) { i = 0 } + + Reloader.prepare! + assert_equal 1, i + end + def test_cleanup_callbacks_are_called_on_exceptions cleaned = false Reloader.to_cleanup { cleaned = true } @@ -132,7 +164,8 @@ class ReloaderTest < Test::Unit::TestCase private def call_and_return_body(&block) - @reloader ||= Reloader.new(block || proc {[200, {}, 'response']}) + @response ||= 'response' + @reloader ||= Reloader.new(block || proc {[200, {}, @response]}) @reloader.call({'rack.input' => StringIO.new('')})[2] end end diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index d854d55173..302bff0696 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -32,13 +32,21 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest test "logs error if parsing unsuccessful" do with_test_routing do + output = StringIO.new + json = "[\"person]\": {\"name\": \"David\"}}" + post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output)} + assert_response :error + output.rewind && err = output.read + assert err =~ /Error occurred while parsing request parameters/ + end + end + + test "occurring a parse error if parsing unsuccessful" do + with_test_routing do begin - $stderr = StringIO.new + $stderr = StringIO.new # suppress the log json = "[\"person]\": {\"name\": \"David\"}}" - post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => true} - assert_response :error - $stderr.rewind && err = $stderr.read - assert err =~ /Error occurred while parsing request parameters/ + assert_raise(MultiJson::DecodeError) { post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => false} } ensure $stderr = STDERR end @@ -57,7 +65,7 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::JsonParamsParsingTest::TestController + post ':action', :to => ::JsonParamsParsingTest::TestController end yield end @@ -110,7 +118,7 @@ class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing(controller) with_routing do |set| set.draw do - match ':action', :to => controller + post ':action', :to => controller end yield end diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 560ea00923..63c5ea26a6 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -89,7 +89,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest # Rack doesn't handle multipart/mixed for us. files = params['files'] - files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding) + files.force_encoding('ASCII-8BIT') assert_equal 19756, files.size end @@ -144,7 +144,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => 'multipart_params_parsing_test/test' + post ':action', :to => 'multipart_params_parsing_test/test' end yield end diff --git a/actionpack/test/dispatch/request/query_string_parsing_test.rb b/actionpack/test/dispatch/request/query_string_parsing_test.rb index f6a1475d04..c3f009ab15 100644 --- a/actionpack/test/dispatch/request/query_string_parsing_test.rb +++ b/actionpack/test/dispatch/request/query_string_parsing_test.rb @@ -105,11 +105,22 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest ) end + test "ambiguous query string returns a bad request" do + with_routing do |set| + set.draw do + get ':action', :to => ::QueryStringParsingTest::TestController + end + + get "/parse", nil, "QUERY_STRING" => "foo[]=bar&foo[4]=bar" + assert_response :bad_request + end + end + private def assert_parses(expected, actual) with_routing do |set| set.draw do - match ':action', :to => ::QueryStringParsingTest::TestController + get ':action', :to => ::QueryStringParsingTest::TestController end get "/parse", actual diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb new file mode 100644 index 0000000000..4d24456ba6 --- /dev/null +++ b/actionpack/test/dispatch/request/session_test.rb @@ -0,0 +1,48 @@ +require 'abstract_unit' +require 'action_dispatch/middleware/session/abstract_store' + +module ActionDispatch + class Request + class SessionTest < ActiveSupport::TestCase + def test_create_adds_itself_to_env + env = {} + s = Session.create(store, env, {}) + assert_equal s, env[Rack::Session::Abstract::ENV_SESSION_KEY] + end + + def test_to_hash + env = {} + s = Session.create(store, env, {}) + s['foo'] = 'bar' + assert_equal 'bar', s['foo'] + assert_equal({'foo' => 'bar'}, s.to_hash) + end + + def test_create_merges_old + env = {} + s = Session.create(store, env, {}) + s['foo'] = 'bar' + + s1 = Session.create(store, env, {}) + refute_equal s, s1 + assert_equal 'bar', s1['foo'] + end + + def test_find + env = {} + assert_nil Session.find(env) + + s = Session.create(store, env, {}) + assert_equal s, Session.find(env) + end + + private + def store + Class.new { + def load_session(env); [1, {}]; end + def session_exists?(env); true; end + }.new + end + end + end +end diff --git a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb index 04a0fb6f34..e9b59f55a7 100644 --- a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb @@ -126,11 +126,22 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest assert_parses expected, query end + test "ambiguous params returns a bad request" do + with_routing do |set| + set.draw do + post ':action', :to => ::UrlEncodedParamsParsingTest::TestController + end + + post "/parse", "foo[]=bar&foo[4]=bar" + assert_response :bad_request + end + end + private def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::UrlEncodedParamsParsingTest::TestController + post ':action', :to => ::UrlEncodedParamsParsingTest::TestController end yield end @@ -146,8 +157,6 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest end def assert_utf8(object) - return unless "ruby".encoding_aware? - correct_encoding = Encoding.default_internal unless object.is_a?(Hash) diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb index 38453dfe48..84823e2896 100644 --- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb @@ -41,7 +41,7 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest test "parses single file" do with_test_routing do - xml = "<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar></person>" + xml = "<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{::Base64.encode64('ABC')}</avatar></person>" post "/parse", xml, default_headers assert_response :ok @@ -54,13 +54,21 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest test "logs error if parsing unsuccessful" do with_test_routing do + output = StringIO.new + xml = "<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{::Base64.encode64('ABC')}</avatar></pineapple>" + post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output)) + assert_response :error + output.rewind && err = output.read + assert err =~ /Error occurred while parsing request parameters/ + end + end + + test "occurring a parse error if parsing unsuccessful" do + with_test_routing do begin - $stderr = StringIO.new - xml = "<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar></pineapple>" - post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => true) - assert_response :error - $stderr.rewind && err = $stderr.read - assert err =~ /Error occurred while parsing request parameters/ + $stderr = StringIO.new # suppress the log + xml = "<person><name>David</name></pineapple>" + assert_raise(REXML::ParseException) { post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => false) } ensure $stderr = STDERR end @@ -72,8 +80,8 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest <person> <name>David</name> <avatars> - <avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar> - <avatar type='file' name='you.gif' content_type='image/gif'>#{ActiveSupport::Base64.encode64('DEF')}</avatar> + <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 @@ -98,7 +106,7 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::XmlParamsParsingTest::TestController + post ':action', :to => ::XmlParamsParsingTest::TestController end yield end @@ -147,7 +155,7 @@ class RootLessXmlParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::RootLessXmlParamsParsingTest::TestController + post ':action', :to => ::RootLessXmlParamsParsingTest::TestController end yield end diff --git a/actionpack/test/dispatch/request_id_test.rb b/actionpack/test/dispatch/request_id_test.rb new file mode 100644 index 0000000000..a8050b4fab --- /dev/null +++ b/actionpack/test/dispatch/request_id_test.rb @@ -0,0 +1,65 @@ +require 'abstract_unit' + +class RequestIdTest < ActiveSupport::TestCase + test "passing on the request id from the outside" do + assert_equal "external-uu-rid", stub_request('HTTP_X_REQUEST_ID' => 'external-uu-rid').uuid + end + + test "ensure that only alphanumeric uurids are accepted" do + assert_equal "X-Hacked-HeaderStuff", stub_request('HTTP_X_REQUEST_ID' => '; X-Hacked-Header: Stuff').uuid + end + + test "ensure that 255 char limit on the request id is being enforced" do + assert_equal "X" * 255, stub_request('HTTP_X_REQUEST_ID' => 'X' * 500).uuid + end + + test "generating a request id when none is supplied" do + assert_match(/\w+-\w+-\w+-\w+-\w+/, stub_request.uuid) + end + + private + + def stub_request(env = {}) + ActionDispatch::RequestId.new(lambda { |environment| [ 200, environment, [] ] }).call(env) + ActionDispatch::Request.new(env) + end +end + +class RequestIdResponseTest < ActionDispatch::IntegrationTest + class TestController < ActionController::Base + def index + head :ok + end + end + + test "request id is passed all the way to the response" do + with_test_route_set do + get '/' + assert_match(/\w+/, @response.headers["X-Request-Id"]) + end + end + + test "request id given on request is passed all the way to the response" do + with_test_route_set do + get '/', {}, 'HTTP_X_REQUEST_ID' => 'X' * 500 + assert_equal "X" * 255, @response.headers["X-Request-Id"] + end + end + + + private + + def with_test_route_set + with_routing do |set| + set.draw do + get '/', :to => ::RequestIdResponseTest::TestController.action(:index) + end + + @app = self.class.build_app(set) do |middleware| + middleware.use ActionDispatch::RequestId + end + + yield + end + end +end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 25b1b4f745..54fc1b208d 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -15,6 +15,7 @@ class RequestTest < ActiveSupport::TestCase assert_equal 'http://www.example.com', url_for assert_equal 'http://api.example.com', url_for(:subdomain => 'api') + assert_equal 'http://example.com', url_for(:subdomain => false) assert_equal 'http://www.ror.com', url_for(:domain => 'ror.com') assert_equal 'http://api.ror.co.uk', url_for(:host => 'www.ror.co.uk', :subdomain => 'api', :tld_length => 2) assert_equal 'http://www.example.com:8080', url_for(:port => 8080) @@ -34,37 +35,40 @@ class RequestTest < ActiveSupport::TestCase assert_equal '1.2.3.4', request.remote_ip request = stub_request 'REMOTE_ADDR' => '1.2.3.4', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' - assert_equal '1.2.3.4', request.remote_ip + 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + assert_equal '3.4.5.6', request.remote_ip request = stub_request 'REMOTE_ADDR' => '127.0.0.1', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' assert_equal '3.4.5.6', request.remote_ip - request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6' + request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,unknown' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '172.16.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request '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 + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '127.0.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1' - assert_equal 'unknown', request.remote_ip + assert_equal nil, request.remote_ip - request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4' + request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 172.31.4.4' assert_equal '3.4.5.6', request.remote_ip + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address' + assert_equal nil, request.remote_ip + request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1', 'HTTP_CLIENT_IP' => '2.2.2.2' e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) { @@ -84,34 +88,141 @@ class RequestTest < ActiveSupport::TestCase :ip_spoofing_check => false assert_equal '2.2.2.2', request.remote_ip - request = stub_request 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9' + request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 8.8.8.8' assert_equal '9.9.9.9', request.remote_ip end - test "remote ip with user specified trusted proxies" do - @trusted_proxies = /^67\.205\.106\.73$/i + test "remote ip v6" do + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip - request = stub_request 'REMOTE_ADDR' => '67.205.106.73', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => '::1', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1, ::1, fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,::1' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, fc00::' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', + 'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334' + e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) { + request.remote_ip + } + assert_match(/IP spoofing attack/, e.message) + assert_match(/HTTP_X_FORWARDED_FOR="fe80:0000:0000:0000:0202:b3ff:fe1e:8329"/, e.message) + assert_match(/HTTP_CLIENT_IP="2001:0db8:85a3:0000:0000:8a2e:0370:7334"/, e.message) + + # Turn IP Spoofing detection off. + # This is useful for sites that are aimed at non-IP clients. The typical + # example is WAP. Since the cellular network is not IP based, it's a + # leap of faith to assume that their proxies are ever going to set the + # HTTP_CLIENT_IP/HTTP_X_FORWARDED_FOR headers properly. + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', + 'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + :ip_spoofing_check => false + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + end + + test "remote ip when the remote ip middleware returns nil" do + request = stub_request 'REMOTE_ADDR' => '127.0.0.1' + assert_equal '127.0.0.1', request.remote_ip + end + + test "remote ip with user specified trusted proxies String" do + @trusted_proxies = "67.205.106.73" + + request = stub_request 'REMOTE_ADDR' => '3.4.5.6', + 'HTTP_X_FORWARDED_FOR' => '67.205.106.73' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'REMOTE_ADDR' => '172.16.0.1,67.205.106.73', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + 'HTTP_X_FORWARDED_FOR' => '67.205.106.73' + assert_equal '172.16.0.1', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => '67.205.106.73,3.4.5.6', + 'HTTP_X_FORWARDED_FOR' => '67.205.106.73' assert_equal '3.4.5.6', request.remote_ip - request = stub_request 'REMOTE_ADDR' => '67.205.106.73,172.16.0.1', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,67.205.106.73' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 67.205.106.73' assert_equal '3.4.5.6', request.remote_ip + end - request = stub_request 'REMOTE_ADDR' => '67.205.106.74,172.16.0.1', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' - assert_equal '67.205.106.74', request.remote_ip + test "remote ip v6 with user specified trusted proxies String" do + @trusted_proxies = 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' - request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,67.205.106.73' - assert_equal 'unknown', request.remote_ip + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip - request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 67.205.106.73' + request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal nil, request.remote_ip + end + + test "remote ip with user specified trusted proxies Regexp" do + @trusted_proxies = /^67\.205\.106\.73$/i + + request = stub_request 'REMOTE_ADDR' => '67.205.106.73', + 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' assert_equal '3.4.5.6', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73, 10.0.0.1, 9.9.9.9, 3.4.5.6' + assert_equal nil, request.remote_ip + end + + test "remote ip v6 with user specified trusted proxies Regexp" do + @trusted_proxies = /^fe80:0000:0000:0000:0202:b3ff:fe1e:8329$/i + + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal nil, request.remote_ip end test "domains" do @@ -308,14 +419,14 @@ class RequestTest < ActiveSupport::TestCase end test "String request methods" do - [:get, :post, :put, :delete].each do |method| + [:get, :post, :patch, :put, :delete].each do |method| request = stub_request 'REQUEST_METHOD' => method.to_s.upcase assert_equal method.to_s.upcase, request.method end end test "Symbol forms of request methods via method_symbol" do - [:get, :post, :put, :delete].each do |method| + [:get, :post, :patch, :put, :delete].each do |method| request = stub_request 'REQUEST_METHOD' => method.to_s.upcase assert_equal method, request.method_symbol end @@ -329,7 +440,7 @@ class RequestTest < ActiveSupport::TestCase end test "allow method hacking on post" do - %w(GET OPTIONS PUT POST DELETE).each do |method| + %w(GET OPTIONS PATCH PUT POST DELETE).each do |method| request = stub_request "REQUEST_METHOD" => method.to_s.upcase assert_equal(method == "HEAD" ? "GET" : method, request.method) end @@ -343,7 +454,7 @@ class RequestTest < ActiveSupport::TestCase end test "restrict method hacking" do - [:get, :put, :delete].each do |method| + [:get, :patch, :put, :delete].each do |method| request = stub_request 'REQUEST_METHOD' => method.to_s.upcase, 'action_dispatch.request.request_parameters' => { :_method => 'put' } assert_equal method.to_s.upcase, request.method @@ -358,6 +469,13 @@ class RequestTest < ActiveSupport::TestCase assert request.head? end + test "post masquerading as patch" do + request = stub_request 'REQUEST_METHOD' => 'PATCH', "rack.methodoverride.original_method" => "POST" + assert_equal "POST", request.method + assert_equal "PATCH", request.request_method + assert request.patch? + end + test "post masquerading as put" do request = stub_request 'REQUEST_METHOD' => 'PUT', "rack.methodoverride.original_method" => "POST" assert_equal "POST", request.method @@ -443,7 +561,7 @@ class RequestTest < ActiveSupport::TestCase begin request = stub_request(mock_rack_env) request.parameters - rescue TypeError + rescue ActionController::BadRequest # rack will raise a TypeError when parsing this query string end assert_equal({}, request.parameters) @@ -468,6 +586,12 @@ class RequestTest < ActiveSupport::TestCase assert request.formats.empty? end + test "formats with xhr request" do + request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" + request.expects(:parameters).at_least_once.returns({}) + assert_equal [Mime::JS], request.formats + end + test "ignore_accept_header" do ActionDispatch::Request.ignore_accept_header = true @@ -606,6 +730,30 @@ class RequestTest < ActiveSupport::TestCase assert_equal "/authenticate?secret", path end + test "original_fullpath returns ORIGINAL_FULLPATH" do + request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar") + + path = request.original_fullpath + assert_equal "/foo?bar", path + end + + test "original_url returns url built using ORIGINAL_FULLPATH" do + request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar", + 'HTTP_HOST' => "example.org", + 'rack.url_scheme' => "http") + + url = request.original_url + assert_equal "http://example.org/foo?bar", url + end + + test "original_fullpath returns fullpath if ORIGINAL_FULLPATH is not present" do + request = stub_request('PATH_INFO' => "/foo", + 'QUERY_STRING' => "bar") + + path = request.original_fullpath + assert_equal "/foo?bar", path + end + protected def stub_request(env = {}) diff --git a/actionpack/test/dispatch/response_body_is_proc_test.rb b/actionpack/test/dispatch/response_body_is_proc_test.rb deleted file mode 100644 index fd94832624..0000000000 --- a/actionpack/test/dispatch/response_body_is_proc_test.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'abstract_unit' - -class ResponseBodyIsProcTest < ActionDispatch::IntegrationTest - class TestController < ActionController::Base - def test - self.response_body = proc { |response, output| - output.write 'Hello' - } - end - end - - def test_simple_get - with_test_route_set do - assert_deprecated do - get '/test' - end - assert_response :success - assert_equal 'Hello', response.body - end - end - - private - - def with_test_route_set(options = {}) - with_routing do |set| - set.draw do - match ':action', :to => ::ResponseBodyIsProcTest::TestController - end - - @app = self.class.build_app(set) do |middleware| - middleware.delete "ActionDispatch::ShowExceptions" - end - - yield - end - end -end diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 5abbaf74fe..82d1200f8e 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -5,6 +5,12 @@ class ResponseTest < ActiveSupport::TestCase @response = ActionDispatch::Response.new end + def test_response_body_encoding + body = ["hello".encode('utf-8')] + response = ActionDispatch::Response.new 200, {}, body + assert_equal Encoding::UTF_8, response.body.encoding + end + test "simple output" do @response.body = "Hello, World!" @@ -130,6 +136,17 @@ class ResponseTest < ActiveSupport::TestCase assert_equal('application/xml; charset=utf-16', resp.headers['Content-Type']) end + + test "read content type without charset" do + original = ActionDispatch::Response.default_charset + begin + ActionDispatch::Response.default_charset = 'utf-16' + resp = ActionDispatch::Response.new(200, { "Content-Type" => "text/xml" }) + assert_equal('utf-16', resp.charset) + ensure + ActionDispatch::Response.default_charset = original + end + end end class ResponseIntegrationTest < ActionDispatch::IntegrationTest diff --git a/actionpack/test/dispatch/routing_assertions_test.rb b/actionpack/test/dispatch/routing_assertions_test.rb index 9f95d82129..aea4489852 100644 --- a/actionpack/test/dispatch/routing_assertions_test.rb +++ b/actionpack/test/dispatch/routing_assertions_test.rb @@ -3,6 +3,7 @@ require 'controller/fake_controllers' class SecureArticlesController < ArticlesController; end class BlockArticlesController < ArticlesController; end +class QueryArticlesController < ArticlesController; end class RoutingAssertionsTest < ActionController::TestCase @@ -18,6 +19,10 @@ class RoutingAssertionsTest < ActionController::TestCase scope 'block', :constraints => lambda { |r| r.ssl? } do resources :articles, :controller => 'block_articles' end + + scope 'query', :constraints => lambda { |r| r.params[:use_query] == 'true' } do + resources :articles, :controller => 'query_articles' + end end end @@ -42,26 +47,33 @@ class RoutingAssertionsTest < ActionController::TestCase def test_assert_recognizes_with_extras assert_recognizes({ :controller => 'articles', :action => 'index', :page => '1' }, '/articles', { :page => '1' }) end - + def test_assert_recognizes_with_method assert_recognizes({ :controller => 'articles', :action => 'create' }, { :path => '/articles', :method => :post }) assert_recognizes({ :controller => 'articles', :action => 'update', :id => '1' }, { :path => '/articles/1', :method => :put }) end def test_assert_recognizes_with_hash_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'http://test.host/secure/articles') end - assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'https://test.host/secure/articles') + assert_recognizes({ :controller => 'secure_articles', :action => 'index', :protocol => 'https://' }, 'https://test.host/secure/articles') end def test_assert_recognizes_with_block_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes({ :controller => 'block_articles', :action => 'index' }, 'http://test.host/block/articles') end assert_recognizes({ :controller => 'block_articles', :action => 'index' }, 'https://test.host/block/articles') end + def test_assert_recognizes_with_query_constraint + assert_raise(Assertion) do + assert_recognizes({ :controller => 'query_articles', :action => 'index', :use_query => 'false' }, '/query/articles', { :use_query => 'false' }) + end + assert_recognizes({ :controller => 'query_articles', :action => 'index', :use_query => 'true' }, '/query/articles', { :use_query => 'true' }) + end + def test_assert_routing assert_routing('/articles', :controller => 'articles', :action => 'index') end @@ -75,14 +87,14 @@ class RoutingAssertionsTest < ActionController::TestCase end def test_assert_routing_with_hash_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_routing('http://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' }) end - assert_routing('https://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' }) + assert_routing('https://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index', :protocol => 'https://' }) end def test_assert_routing_with_block_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_routing('http://test.host/block/articles', { :controller => 'block_articles', :action => 'index' }) end assert_routing('https://test.host/block/articles', { :controller => 'block_articles', :action => 'index' }) @@ -95,7 +107,7 @@ class RoutingAssertionsTest < ActionController::TestCase end assert_routing('/artikel', :controller => 'articles', :action => 'index') - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_routing('/articles', { :controller => 'articles', :action => 'index' }) end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index ba7506721f..00d09282ca 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1,3 +1,4 @@ +# encoding: UTF-8 require 'erb' require 'abstract_unit' require 'controller/fake_controllers' @@ -57,45 +58,46 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "remove", :action => :destroy, :as => :remove end - match 'account/logout' => redirect("/logout"), :as => :logout_redirect - match 'account/login', :to => redirect("/login") - match 'secure', :to => redirect("/secure/login") + get 'account/logout' => redirect("/logout"), :as => :logout_redirect + get 'account/login', :to => redirect("/login") + get 'secure', :to => redirect("/secure/login") - match 'mobile', :to => redirect(:subdomain => 'mobile') - match 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '') - match 'new_documentation', :to => redirect(:path => '/documentation/new') - match 'super_new_documentation', :to => redirect(:host => 'super-docs.com') + get 'mobile', :to => redirect(:subdomain => 'mobile') + get 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '') + get 'new_documentation', :to => redirect(:path => '/documentation/new') + get 'super_new_documentation', :to => redirect(:host => 'super-docs.com') - match 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}') - match 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}') + get 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}') + get 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}') - match 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector) + get 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector) constraints(lambda { |req| true }) do - match 'account/overview' + get 'account/overview' end - match '/account/nested/overview' - match 'sign_in' => "sessions#new" + get '/account/nested/overview' + get 'sign_in' => "sessions#new" - match 'account/modulo/:name', :to => redirect("/%{name}s") - match 'account/proc/:name', :to => redirect {|params| "/#{params[:name].pluralize}" } - match 'account/proc_req' => redirect {|params, req| "/#{req.method}" } + get 'account/modulo/:name', :to => redirect("/%{name}s") + get 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" } + get 'account/proc_req' => redirect {|params, req| "/#{req.method}" } - match 'account/google' => redirect('http://www.google.com/', :status => 302) + get 'account/google' => redirect('http://www.google.com/', :status => 302) match 'openid/login', :via => [:get, :post], :to => "openid#login" controller(:global) do get 'global/hide_notice' - match 'global/export', :to => :export, :as => :export_request - match '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ } - match 'global/:action' + get 'global/export', :to => :export, :as => :export_request + get '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ } + get 'global/:action' end - match "/local/:action", :controller => "local" + get "/local/:action", :controller => "local" - match "/projects/status(.:format)" + get "/projects/status(.:format)" + get "/404", :to => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["NOT FOUND"]] } constraints(:ip => /192\.168\.1\.\d\d\d/) do get 'admin' => "queenbee#index" @@ -169,6 +171,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post :preview, :on => :collection end end + + post 'new', :action => 'new', :on => :collection, :as => :new end resources :replies do @@ -280,25 +284,25 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp + get 'sprockets.js' => ::TestRoutingMapper::SprocketsApp - match 'people/:id/update', :to => 'people#update', :as => :update_person - match '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person + get 'people/:id/update', :to => 'people#update', :as => :update_person + get '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person # misc - match 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article + get 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article # default params - match 'inline_pages/(:id)', :to => 'pages#show', :id => 'home' - match 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' } + get 'inline_pages/(:id)', :to => 'pages#show', :id => 'home' + get 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' } defaults :id => 'home' do - match 'scoped_pages/(:id)', :to => 'pages#show' + get 'scoped_pages/(:id)', :to => 'pages#show' end namespace :account do - match 'shorthand' - match 'description', :to => :description, :as => "description" - match ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback + get 'shorthand' + get 'description', :to => :description, :as => "description" + get ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback resource :subscription, :credit, :credit_card root :to => "account#index" @@ -321,7 +325,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest controller :articles do scope '/articles', :as => 'article' do scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do - match '/:id', :to => :with_id, :as => "" + get '/:id', :to => :with_id, :as => "" end end end @@ -330,7 +334,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :rooms end - match '/info' => 'projects#info', :as => 'info' + get '/info' => 'projects#info', :as => 'info' namespace :admin do scope '(:locale)', :locale => /en|pl/ do @@ -339,6 +343,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end scope '(:locale)', :locale => /en|pl/ do + get "registrations/new" resources :descriptions root :to => 'projects#index' end @@ -363,7 +368,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest scope :path => 'api' do resource :me - match '/' => 'mes#index' + get '/' => 'mes#index' end get "(/:username)/followers" => "followers#index" @@ -376,7 +381,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - match "whatever/:controller(/:action(/:id))", :id => /\d+/ + get "whatever/:controller(/:action(/:id))", :id => /\d+/ resource :profile do get :settings @@ -409,7 +414,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest namespace :private do root :to => redirect('/private/index') - match "index", :to => 'private#index' + get "index", :to => 'private#index' end scope :only => [:index, :show] do @@ -477,6 +482,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get :preview, :on => :member end + resources :profiles, :param => :username do + get :details, :on => :member + resources :messages + end + scope :as => "routes" do get "/c/:id", :as => :collision, :to => "collision#show" get "/collision", :to => "collision#show" @@ -486,7 +496,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "/forced_collision", :as => :forced_collision, :to => "forced_collision#show" end - match '/purchases/:token/:filename', + get '/purchases/:token/:filename', :to => 'purchases#fetch', :token => /[[:alnum:]]{10}/, :filename => /(.+)/, @@ -497,13 +507,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end scope '/countries/:country', :constraints => lambda { |params, req| params[:country].in?(["all", "France"]) } do - match '/', :to => 'countries#index' - match '/cities', :to => 'countries#cities' + get '/', :to => 'countries#index' + get '/cities', :to => 'countries#cities' end - match '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' } + get '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' } - match '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/ + get '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/ + + scope '/italians' do + get '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor + get '/sculptors', :to => 'italians#sculptors' + get '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/} + end end end @@ -521,6 +537,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest "GET" end + def ip + "127.0.0.1" + end + def x_header @env["HTTP_X_HEADER"] || "" end @@ -571,52 +591,42 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest include Routes.url_helpers def test_logout - with_test_routes do - delete '/logout' - assert_equal 'sessions#destroy', @response.body + delete '/logout' + assert_equal 'sessions#destroy', @response.body - assert_equal '/logout', logout_path - assert_equal '/logout', url_for(:controller => 'sessions', :action => 'destroy', :only_path => true) - end + assert_equal '/logout', logout_path + assert_equal '/logout', url_for(:controller => 'sessions', :action => 'destroy', :only_path => true) end def test_login - with_test_routes do - get '/login' - assert_equal 'sessions#new', @response.body - assert_equal '/login', login_path + get '/login' + assert_equal 'sessions#new', @response.body + assert_equal '/login', login_path - post '/login' - assert_equal 'sessions#create', @response.body + post '/login' + assert_equal 'sessions#create', @response.body - assert_equal '/login', url_for(:controller => 'sessions', :action => 'create', :only_path => true) - assert_equal '/login', url_for(:controller => 'sessions', :action => 'new', :only_path => true) + assert_equal '/login', url_for(:controller => 'sessions', :action => 'create', :only_path => true) + assert_equal '/login', url_for(:controller => 'sessions', :action => 'new', :only_path => true) - assert_equal 'http://rubyonrails.org/login', Routes.url_for(:controller => 'sessions', :action => 'create') - assert_equal 'http://rubyonrails.org/login', Routes.url_helpers.login_url - end + assert_equal 'http://rubyonrails.org/login', Routes.url_for(:controller => 'sessions', :action => 'create') + assert_equal 'http://rubyonrails.org/login', Routes.url_helpers.login_url end def test_login_redirect - with_test_routes do - get '/account/login' - verify_redirect 'http://www.example.com/login' - end + get '/account/login' + verify_redirect 'http://www.example.com/login' end def test_logout_redirect_without_to - with_test_routes do - assert_equal '/account/logout', logout_redirect_path - get '/account/logout' - verify_redirect 'http://www.example.com/logout' - end + assert_equal '/account/logout', logout_redirect_path + get '/account/logout' + verify_redirect 'http://www.example.com/logout' end def test_namespace_redirect - with_test_routes do - get '/private' - verify_redirect 'http://www.example.com/private/index' - end + get '/private' + verify_redirect 'http://www.example.com/private/index' end def test_namespace_with_controller_segment @@ -624,7 +634,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest self.class.stub_controllers do |routes| routes.draw do namespace :admin do - match '/:controller(/:action(/:id(.:format)))' + get '/:controller(/:action(/:id(.:format)))' end end end @@ -632,852 +642,775 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end def test_session_singleton_resource - with_test_routes do - get '/session' - assert_equal 'sessions#create', @response.body - assert_equal '/session', session_path + get '/session' + assert_equal 'sessions#create', @response.body + assert_equal '/session', session_path - post '/session' - assert_equal 'sessions#create', @response.body + post '/session' + assert_equal 'sessions#create', @response.body - put '/session' - assert_equal 'sessions#update', @response.body + put '/session' + assert_equal 'sessions#update', @response.body - delete '/session' - assert_equal 'sessions#destroy', @response.body + delete '/session' + assert_equal 'sessions#destroy', @response.body - get '/session/new' - assert_equal 'sessions#new', @response.body - assert_equal '/session/new', new_session_path + get '/session/new' + assert_equal 'sessions#new', @response.body + assert_equal '/session/new', new_session_path - get '/session/edit' - assert_equal 'sessions#edit', @response.body - assert_equal '/session/edit', edit_session_path + get '/session/edit' + assert_equal 'sessions#edit', @response.body + assert_equal '/session/edit', edit_session_path - post '/session/reset' - assert_equal 'sessions#reset', @response.body - assert_equal '/session/reset', reset_session_path - end + post '/session/reset' + assert_equal 'sessions#reset', @response.body + assert_equal '/session/reset', reset_session_path end def test_session_info_nested_singleton_resource - with_test_routes do - get '/session/info' - assert_equal 'infos#show', @response.body - assert_equal '/session/info', session_info_path - end + get '/session/info' + assert_equal 'infos#show', @response.body + assert_equal '/session/info', session_info_path end def test_member_on_resource - with_test_routes do - get '/session/crush' - assert_equal 'sessions#crush', @response.body - assert_equal '/session/crush', crush_session_path - end + get '/session/crush' + assert_equal 'sessions#crush', @response.body + assert_equal '/session/crush', crush_session_path end def test_redirect_modulo - with_test_routes do - get '/account/modulo/name' - verify_redirect 'http://www.example.com/names' - end + get '/account/modulo/name' + verify_redirect 'http://www.example.com/names' end def test_redirect_proc - with_test_routes do - get '/account/proc/person' - verify_redirect 'http://www.example.com/people' - end + get '/account/proc/person' + verify_redirect 'http://www.example.com/people' end def test_redirect_proc_with_request - with_test_routes do - get '/account/proc_req' - verify_redirect 'http://www.example.com/GET' - end + get '/account/proc_req' + verify_redirect 'http://www.example.com/GET' end def test_redirect_hash_with_subdomain - with_test_routes do - get '/mobile' - verify_redirect 'http://mobile.example.com/mobile' - end + get '/mobile' + verify_redirect 'http://mobile.example.com/mobile' end def test_redirect_hash_with_domain_and_path - with_test_routes do - get '/documentation' - verify_redirect 'http://www.example-documentation.com' - end + get '/documentation' + verify_redirect 'http://www.example-documentation.com' end def test_redirect_hash_with_path - with_test_routes do - get '/new_documentation' - verify_redirect 'http://www.example.com/documentation/new' - end + get '/new_documentation' + verify_redirect 'http://www.example.com/documentation/new' end def test_redirect_hash_with_host - with_test_routes do - get '/super_new_documentation?section=top' - verify_redirect 'http://super-docs.com/super_new_documentation?section=top' - end + get '/super_new_documentation?section=top' + verify_redirect 'http://super-docs.com/super_new_documentation?section=top' end def test_redirect_hash_path_substitution - with_test_routes do - get '/stores/iernest' - verify_redirect 'http://stores.example.com/iernest' - end + get '/stores/iernest' + verify_redirect 'http://stores.example.com/iernest' end def test_redirect_hash_path_substitution_with_catch_all - with_test_routes do - get '/stores/iernest/products' - verify_redirect 'http://stores.example.com/iernest/products' - end + get '/stores/iernest/products' + verify_redirect 'http://stores.example.com/iernest/products' end def test_redirect_class - with_test_routes do - get '/youtube_favorites/oHg5SJYRHA0/rick-rolld' - verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0' - end + get '/youtube_favorites/oHg5SJYRHA0/rick-rolld' + verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0' end def test_openid - with_test_routes do - get '/openid/login' - assert_equal 'openid#login', @response.body + get '/openid/login' + assert_equal 'openid#login', @response.body - post '/openid/login' - assert_equal 'openid#login', @response.body - end + post '/openid/login' + assert_equal 'openid#login', @response.body end def test_bookmarks - with_test_routes do - get '/bookmark/build' - assert_equal 'bookmarks#new', @response.body - assert_equal '/bookmark/build', bookmark_new_path - - post '/bookmark/create' - assert_equal 'bookmarks#create', @response.body - assert_equal '/bookmark/create', bookmark_path - - put '/bookmark/update' - assert_equal 'bookmarks#update', @response.body - assert_equal '/bookmark/update', bookmark_update_path - - get '/bookmark/remove' - assert_equal 'bookmarks#destroy', @response.body - assert_equal '/bookmark/remove', bookmark_remove_path - end + get '/bookmark/build' + assert_equal 'bookmarks#new', @response.body + assert_equal '/bookmark/build', bookmark_new_path + + post '/bookmark/create' + assert_equal 'bookmarks#create', @response.body + assert_equal '/bookmark/create', bookmark_path + + put '/bookmark/update' + assert_equal 'bookmarks#update', @response.body + assert_equal '/bookmark/update', bookmark_update_path + + get '/bookmark/remove' + assert_equal 'bookmarks#destroy', @response.body + assert_equal '/bookmark/remove', bookmark_remove_path end def test_pagemarks - with_test_routes do - get '/pagemark/build' - assert_equal 'pagemarks#new', @response.body - assert_equal '/pagemark/build', pagemark_new_path - - post '/pagemark/create' - assert_equal 'pagemarks#create', @response.body - assert_equal '/pagemark/create', pagemark_path - - put '/pagemark/update' - assert_equal 'pagemarks#update', @response.body - assert_equal '/pagemark/update', pagemark_update_path - - get '/pagemark/remove' - assert_equal 'pagemarks#destroy', @response.body - assert_equal '/pagemark/remove', pagemark_remove_path - end + get '/pagemark/build' + assert_equal 'pagemarks#new', @response.body + assert_equal '/pagemark/build', pagemark_new_path + + post '/pagemark/create' + assert_equal 'pagemarks#create', @response.body + assert_equal '/pagemark/create', pagemark_path + + put '/pagemark/update' + assert_equal 'pagemarks#update', @response.body + assert_equal '/pagemark/update', pagemark_update_path + + get '/pagemark/remove' + assert_equal 'pagemarks#destroy', @response.body + assert_equal '/pagemark/remove', pagemark_remove_path end def test_admin - with_test_routes do - get '/admin', {}, {'REMOTE_ADDR' => '192.168.1.100'} - assert_equal 'queenbee#index', @response.body + get '/admin', {}, {'REMOTE_ADDR' => '192.168.1.100'} + assert_equal 'queenbee#index', @response.body - get '/admin', {}, {'REMOTE_ADDR' => '10.0.0.100'} - assert_equal 'pass', @response.headers['X-Cascade'] + get '/admin', {}, {'REMOTE_ADDR' => '10.0.0.100'} + assert_equal 'pass', @response.headers['X-Cascade'] - get '/admin/accounts', {}, {'REMOTE_ADDR' => '192.168.1.100'} - assert_equal 'queenbee#accounts', @response.body + get '/admin/accounts', {}, {'REMOTE_ADDR' => '192.168.1.100'} + assert_equal 'queenbee#accounts', @response.body - get '/admin/accounts', {}, {'REMOTE_ADDR' => '10.0.0.100'} - assert_equal 'pass', @response.headers['X-Cascade'] + get '/admin/accounts', {}, {'REMOTE_ADDR' => '10.0.0.100'} + assert_equal 'pass', @response.headers['X-Cascade'] - get '/admin/passwords', {}, {'REMOTE_ADDR' => '192.168.1.100'} - assert_equal 'queenbee#passwords', @response.body + get '/admin/passwords', {}, {'REMOTE_ADDR' => '192.168.1.100'} + assert_equal 'queenbee#passwords', @response.body - get '/admin/passwords', {}, {'REMOTE_ADDR' => '10.0.0.100'} - assert_equal 'pass', @response.headers['X-Cascade'] - end + get '/admin/passwords', {}, {'REMOTE_ADDR' => '10.0.0.100'} + assert_equal 'pass', @response.headers['X-Cascade'] end def test_global - with_test_routes do - get '/global/dashboard' - assert_equal 'global#dashboard', @response.body + get '/global/dashboard' + assert_equal 'global#dashboard', @response.body - get '/global/export' - assert_equal 'global#export', @response.body + get '/global/export' + assert_equal 'global#export', @response.body - get '/global/hide_notice' - assert_equal 'global#hide_notice', @response.body + get '/global/hide_notice' + assert_equal 'global#hide_notice', @response.body - get '/export/123/foo.txt' - assert_equal 'global#export', @response.body + get '/export/123/foo.txt' + assert_equal 'global#export', @response.body - assert_equal '/global/export', export_request_path - assert_equal '/global/hide_notice', global_hide_notice_path - assert_equal '/export/123/foo.txt', export_download_path(:id => 123, :file => 'foo.txt') - end + assert_equal '/global/export', export_request_path + assert_equal '/global/hide_notice', global_hide_notice_path + assert_equal '/export/123/foo.txt', export_download_path(:id => 123, :file => 'foo.txt') end def test_local - with_test_routes do - get '/local/dashboard' - assert_equal 'local#dashboard', @response.body - end + get '/local/dashboard' + assert_equal 'local#dashboard', @response.body + end + + # tests the use of dup in url_for + def test_url_for_with_no_side_effects + # without dup, additional (and possibly unwanted) values will be present in the options (eg. :host) + original_options = {:controller => 'projects', :action => 'status'} + options = original_options.dup + + url_for options + + # verify that the options passed in have not changed from the original ones + assert_equal original_options, options + end + + def test_url_for_does_not_modify_controller + controller = '/projects' + options = {:controller => controller, :action => 'status', :only_path => true} + url = url_for(options) + + assert_equal '/projects/status', url + assert_equal '/projects', controller + end + + # tests the arguments modification free version of define_hash_access + def test_named_route_with_no_side_effects + original_options = { :host => 'test.host' } + options = original_options.dup + + profile_customer_url("customer_model", options) + + # verify that the options passed in have not changed from the original ones + assert_equal original_options, options end def test_projects_status - with_test_routes do - assert_equal '/projects/status', url_for(:controller => 'projects', :action => 'status', :only_path => true) - assert_equal '/projects/status.json', url_for(:controller => 'projects', :action => 'status', :format => 'json', :only_path => true) - end + assert_equal '/projects/status', url_for(:controller => 'projects', :action => 'status', :only_path => true) + assert_equal '/projects/status.json', url_for(:controller => 'projects', :action => 'status', :format => 'json', :only_path => true) end def test_projects - with_test_routes do - get '/projects' - assert_equal 'project#index', @response.body - assert_equal '/projects', projects_path + get '/projects' + assert_equal 'project#index', @response.body + assert_equal '/projects', projects_path - post '/projects' - assert_equal 'project#create', @response.body + post '/projects' + assert_equal 'project#create', @response.body - get '/projects.xml' - assert_equal 'project#index', @response.body - assert_equal '/projects.xml', projects_path(:format => 'xml') + get '/projects.xml' + assert_equal 'project#index', @response.body + assert_equal '/projects.xml', projects_path(:format => 'xml') - get '/projects/new' - assert_equal 'project#new', @response.body - assert_equal '/projects/new', new_project_path + get '/projects/new' + assert_equal 'project#new', @response.body + assert_equal '/projects/new', new_project_path - get '/projects/new.xml' - assert_equal 'project#new', @response.body - assert_equal '/projects/new.xml', new_project_path(:format => 'xml') + get '/projects/new.xml' + assert_equal 'project#new', @response.body + assert_equal '/projects/new.xml', new_project_path(:format => 'xml') - get '/projects/1' - assert_equal 'project#show', @response.body - assert_equal '/projects/1', project_path(:id => '1') + get '/projects/1' + assert_equal 'project#show', @response.body + assert_equal '/projects/1', project_path(:id => '1') - get '/projects/1.xml' - assert_equal 'project#show', @response.body - assert_equal '/projects/1.xml', project_path(:id => '1', :format => 'xml') + get '/projects/1.xml' + assert_equal 'project#show', @response.body + assert_equal '/projects/1.xml', project_path(:id => '1', :format => 'xml') - get '/projects/1/edit' - assert_equal 'project#edit', @response.body - assert_equal '/projects/1/edit', edit_project_path(:id => '1') - end + get '/projects/1/edit' + assert_equal 'project#edit', @response.body + assert_equal '/projects/1/edit', edit_project_path(:id => '1') + end + + def test_projects_with_post_action_and_new_path_on_collection + post '/projects/new' + assert_equal "project#new", @response.body + assert_equal "/projects/new", new_projects_path end def test_projects_involvements - with_test_routes do - get '/projects/1/involvements' - assert_equal 'involvements#index', @response.body - assert_equal '/projects/1/involvements', project_involvements_path(:project_id => '1') + get '/projects/1/involvements' + assert_equal 'involvements#index', @response.body + assert_equal '/projects/1/involvements', project_involvements_path(:project_id => '1') - get '/projects/1/involvements/new' - assert_equal 'involvements#new', @response.body - assert_equal '/projects/1/involvements/new', new_project_involvement_path(:project_id => '1') + get '/projects/1/involvements/new' + assert_equal 'involvements#new', @response.body + assert_equal '/projects/1/involvements/new', new_project_involvement_path(:project_id => '1') - get '/projects/1/involvements/1' - assert_equal 'involvements#show', @response.body - assert_equal '/projects/1/involvements/1', project_involvement_path(:project_id => '1', :id => '1') + get '/projects/1/involvements/1' + assert_equal 'involvements#show', @response.body + assert_equal '/projects/1/involvements/1', project_involvement_path(:project_id => '1', :id => '1') - put '/projects/1/involvements/1' - assert_equal 'involvements#update', @response.body + put '/projects/1/involvements/1' + assert_equal 'involvements#update', @response.body - delete '/projects/1/involvements/1' - assert_equal 'involvements#destroy', @response.body + delete '/projects/1/involvements/1' + assert_equal 'involvements#destroy', @response.body - get '/projects/1/involvements/1/edit' - assert_equal 'involvements#edit', @response.body - assert_equal '/projects/1/involvements/1/edit', edit_project_involvement_path(:project_id => '1', :id => '1') - end + get '/projects/1/involvements/1/edit' + assert_equal 'involvements#edit', @response.body + assert_equal '/projects/1/involvements/1/edit', edit_project_involvement_path(:project_id => '1', :id => '1') end def test_projects_attachments - with_test_routes do - get '/projects/1/attachments' - assert_equal 'attachments#index', @response.body - assert_equal '/projects/1/attachments', project_attachments_path(:project_id => '1') - end + get '/projects/1/attachments' + assert_equal 'attachments#index', @response.body + assert_equal '/projects/1/attachments', project_attachments_path(:project_id => '1') end def test_projects_participants - with_test_routes do - get '/projects/1/participants' - assert_equal 'participants#index', @response.body - assert_equal '/projects/1/participants', project_participants_path(:project_id => '1') - - put '/projects/1/participants/update_all' - assert_equal 'participants#update_all', @response.body - assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1') - end + get '/projects/1/participants' + assert_equal 'participants#index', @response.body + assert_equal '/projects/1/participants', project_participants_path(:project_id => '1') + + put '/projects/1/participants/update_all' + assert_equal 'participants#update_all', @response.body + assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1') end def test_projects_companies - with_test_routes do - get '/projects/1/companies' - assert_equal 'companies#index', @response.body - assert_equal '/projects/1/companies', project_companies_path(:project_id => '1') - - get '/projects/1/companies/1/people' - assert_equal 'people#index', @response.body - assert_equal '/projects/1/companies/1/people', project_company_people_path(:project_id => '1', :company_id => '1') - - get '/projects/1/companies/1/avatar' - assert_equal 'avatar#show', @response.body - assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1') - end + get '/projects/1/companies' + assert_equal 'companies#index', @response.body + assert_equal '/projects/1/companies', project_companies_path(:project_id => '1') + + get '/projects/1/companies/1/people' + assert_equal 'people#index', @response.body + assert_equal '/projects/1/companies/1/people', project_company_people_path(:project_id => '1', :company_id => '1') + + get '/projects/1/companies/1/avatar' + assert_equal 'avatar#show', @response.body + assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1') end def test_project_manager - with_test_routes do - get '/projects/1/manager' - assert_equal 'managers#show', @response.body - assert_equal '/projects/1/manager', project_super_manager_path(:project_id => '1') - - get '/projects/1/manager/new' - assert_equal 'managers#new', @response.body - assert_equal '/projects/1/manager/new', new_project_super_manager_path(:project_id => '1') - - post '/projects/1/manager/fire' - assert_equal 'managers#fire', @response.body - assert_equal '/projects/1/manager/fire', fire_project_super_manager_path(:project_id => '1') - end + get '/projects/1/manager' + assert_equal 'managers#show', @response.body + assert_equal '/projects/1/manager', project_super_manager_path(:project_id => '1') + + get '/projects/1/manager/new' + assert_equal 'managers#new', @response.body + assert_equal '/projects/1/manager/new', new_project_super_manager_path(:project_id => '1') + + post '/projects/1/manager/fire' + assert_equal 'managers#fire', @response.body + assert_equal '/projects/1/manager/fire', fire_project_super_manager_path(:project_id => '1') end def test_project_images - with_test_routes do - get '/projects/1/images' - assert_equal 'images#index', @response.body - assert_equal '/projects/1/images', project_funny_images_path(:project_id => '1') - - get '/projects/1/images/new' - assert_equal 'images#new', @response.body - assert_equal '/projects/1/images/new', new_project_funny_image_path(:project_id => '1') - - post '/projects/1/images/1/revise' - assert_equal 'images#revise', @response.body - assert_equal '/projects/1/images/1/revise', revise_project_funny_image_path(:project_id => '1', :id => '1') - end + get '/projects/1/images' + assert_equal 'images#index', @response.body + assert_equal '/projects/1/images', project_funny_images_path(:project_id => '1') + + get '/projects/1/images/new' + assert_equal 'images#new', @response.body + assert_equal '/projects/1/images/new', new_project_funny_image_path(:project_id => '1') + + post '/projects/1/images/1/revise' + assert_equal 'images#revise', @response.body + assert_equal '/projects/1/images/1/revise', revise_project_funny_image_path(:project_id => '1', :id => '1') end def test_projects_people - with_test_routes do - get '/projects/1/people' - assert_equal 'people#index', @response.body - assert_equal '/projects/1/people', project_people_path(:project_id => '1') - - get '/projects/1/people/1' - assert_equal 'people#show', @response.body - assert_equal '/projects/1/people/1', project_person_path(:project_id => '1', :id => '1') - - get '/projects/1/people/1/7a2dec8/avatar' - assert_equal 'avatars#show', @response.body - assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8') - - put '/projects/1/people/1/accessible_projects' - assert_equal 'people#accessible_projects', @response.body - assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1') - - post '/projects/1/people/1/resend' - assert_equal 'people#resend', @response.body - assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1') - - post '/projects/1/people/1/generate_new_password' - assert_equal 'people#generate_new_password', @response.body - assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1') - end + get '/projects/1/people' + assert_equal 'people#index', @response.body + assert_equal '/projects/1/people', project_people_path(:project_id => '1') + + get '/projects/1/people/1' + assert_equal 'people#show', @response.body + assert_equal '/projects/1/people/1', project_person_path(:project_id => '1', :id => '1') + + get '/projects/1/people/1/7a2dec8/avatar' + assert_equal 'avatars#show', @response.body + assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8') + + put '/projects/1/people/1/accessible_projects' + assert_equal 'people#accessible_projects', @response.body + assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1') + + post '/projects/1/people/1/resend' + assert_equal 'people#resend', @response.body + assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1') + + post '/projects/1/people/1/generate_new_password' + assert_equal 'people#generate_new_password', @response.body + assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1') end def test_projects_with_resources_path_names - with_test_routes do - get '/projects/info_about_correlation_indexes' - assert_equal 'project#correlation_indexes', @response.body - assert_equal '/projects/info_about_correlation_indexes', correlation_indexes_projects_path - end + get '/projects/info_about_correlation_indexes' + assert_equal 'project#correlation_indexes', @response.body + assert_equal '/projects/info_about_correlation_indexes', correlation_indexes_projects_path end def test_projects_posts - with_test_routes do - get '/projects/1/posts' - assert_equal 'posts#index', @response.body - assert_equal '/projects/1/posts', project_posts_path(:project_id => '1') - - get '/projects/1/posts/archive' - assert_equal 'posts#archive', @response.body - assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1') - - get '/projects/1/posts/toggle_view' - assert_equal 'posts#toggle_view', @response.body - assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1') - - post '/projects/1/posts/1/preview' - assert_equal 'posts#preview', @response.body - assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1') - - get '/projects/1/posts/1/subscription' - assert_equal 'subscriptions#show', @response.body - assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1') - - get '/projects/1/posts/1/comments' - assert_equal 'comments#index', @response.body - assert_equal '/projects/1/posts/1/comments', project_post_comments_path(:project_id => '1', :post_id => '1') - - post '/projects/1/posts/1/comments/preview' - assert_equal 'comments#preview', @response.body - assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1') - end + get '/projects/1/posts' + assert_equal 'posts#index', @response.body + assert_equal '/projects/1/posts', project_posts_path(:project_id => '1') + + get '/projects/1/posts/archive' + assert_equal 'posts#archive', @response.body + assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1') + + get '/projects/1/posts/toggle_view' + assert_equal 'posts#toggle_view', @response.body + assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1') + + post '/projects/1/posts/1/preview' + assert_equal 'posts#preview', @response.body + assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1') + + get '/projects/1/posts/1/subscription' + assert_equal 'subscriptions#show', @response.body + assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1') + + get '/projects/1/posts/1/comments' + assert_equal 'comments#index', @response.body + assert_equal '/projects/1/posts/1/comments', project_post_comments_path(:project_id => '1', :post_id => '1') + + post '/projects/1/posts/1/comments/preview' + assert_equal 'comments#preview', @response.body + assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1') end def test_replies - with_test_routes do - put '/replies/1/answer' - assert_equal 'replies#mark_as_answer', @response.body + put '/replies/1/answer' + assert_equal 'replies#mark_as_answer', @response.body - delete '/replies/1/answer' - assert_equal 'replies#unmark_as_answer', @response.body - end + delete '/replies/1/answer' + assert_equal 'replies#unmark_as_answer', @response.body end def test_resource_routes_with_only_and_except - with_test_routes do - get '/posts' - assert_equal 'posts#index', @response.body - assert_equal '/posts', posts_path - - get '/posts/1' - assert_equal 'posts#show', @response.body - assert_equal '/posts/1', post_path(:id => 1) - - get '/posts/1/comments' - assert_equal 'comments#index', @response.body - assert_equal '/posts/1/comments', post_comments_path(:post_id => 1) - - post '/posts' - assert_equal 'pass', @response.headers['X-Cascade'] - put '/posts/1' - assert_equal 'pass', @response.headers['X-Cascade'] - delete '/posts/1' - assert_equal 'pass', @response.headers['X-Cascade'] - delete '/posts/1/comments' - assert_equal 'pass', @response.headers['X-Cascade'] - end + get '/posts' + assert_equal 'posts#index', @response.body + assert_equal '/posts', posts_path + + get '/posts/1' + assert_equal 'posts#show', @response.body + assert_equal '/posts/1', post_path(:id => 1) + + get '/posts/1/comments' + assert_equal 'comments#index', @response.body + assert_equal '/posts/1/comments', post_comments_path(:post_id => 1) + + post '/posts' + assert_equal 'pass', @response.headers['X-Cascade'] + put '/posts/1' + assert_equal 'pass', @response.headers['X-Cascade'] + delete '/posts/1' + assert_equal 'pass', @response.headers['X-Cascade'] + delete '/posts/1/comments' + assert_equal 'pass', @response.headers['X-Cascade'] end def test_resource_routes_only_create_update_destroy - with_test_routes do - delete '/past' - assert_equal 'pasts#destroy', @response.body - assert_equal '/past', past_path - - put '/present' - assert_equal 'presents#update', @response.body - assert_equal '/present', present_path - - post '/future' - assert_equal 'futures#create', @response.body - assert_equal '/future', future_path - end + delete '/past' + assert_equal 'pasts#destroy', @response.body + assert_equal '/past', past_path + + patch '/present' + assert_equal 'presents#update', @response.body + assert_equal '/present', present_path + + put '/present' + assert_equal 'presents#update', @response.body + assert_equal '/present', present_path + + post '/future' + assert_equal 'futures#create', @response.body + assert_equal '/future', future_path end def test_resources_routes_only_create_update_destroy - with_test_routes do - post '/relationships' - assert_equal 'relationships#create', @response.body - assert_equal '/relationships', relationships_path - - delete '/relationships/1' - assert_equal 'relationships#destroy', @response.body - assert_equal '/relationships/1', relationship_path(1) - - put '/friendships/1' - assert_equal 'friendships#update', @response.body - assert_equal '/friendships/1', friendship_path(1) - end + post '/relationships' + assert_equal 'relationships#create', @response.body + assert_equal '/relationships', relationships_path + + delete '/relationships/1' + assert_equal 'relationships#destroy', @response.body + assert_equal '/relationships/1', relationship_path(1) + + patch '/friendships/1' + assert_equal 'friendships#update', @response.body + assert_equal '/friendships/1', friendship_path(1) + + put '/friendships/1' + assert_equal 'friendships#update', @response.body + assert_equal '/friendships/1', friendship_path(1) end def test_resource_with_slugs_in_ids - with_test_routes do - get '/posts/rails-rocks' - assert_equal 'posts#show', @response.body - assert_equal '/posts/rails-rocks', post_path(:id => 'rails-rocks') - end + get '/posts/rails-rocks' + assert_equal 'posts#show', @response.body + assert_equal '/posts/rails-rocks', post_path(:id => 'rails-rocks') end def test_resources_for_uncountable_names - with_test_routes do - assert_equal '/sheep', sheep_index_path - assert_equal '/sheep/1', sheep_path(1) - assert_equal '/sheep/new', new_sheep_path - assert_equal '/sheep/1/edit', edit_sheep_path(1) - assert_equal '/sheep/1/_it', _it_sheep_path(1) - end + assert_equal '/sheep', sheep_index_path + assert_equal '/sheep/1', sheep_path(1) + assert_equal '/sheep/new', new_sheep_path + assert_equal '/sheep/1/edit', edit_sheep_path(1) + assert_equal '/sheep/1/_it', _it_sheep_path(1) end def test_path_names - with_test_routes do - get '/pt/projetos' - assert_equal 'projects#index', @response.body - assert_equal '/pt/projetos', pt_projects_path - - get '/pt/projetos/1/editar' - assert_equal 'projects#edit', @response.body - assert_equal '/pt/projetos/1/editar', edit_pt_project_path(1) - - get '/pt/administrador' - assert_equal 'admins#show', @response.body - assert_equal '/pt/administrador', pt_admin_path - - get '/pt/administrador/novo' - assert_equal 'admins#new', @response.body - assert_equal '/pt/administrador/novo', new_pt_admin_path - - put '/pt/administrador/ativar' - assert_equal 'admins#activate', @response.body - assert_equal '/pt/administrador/ativar', activate_pt_admin_path - end + get '/pt/projetos' + assert_equal 'projects#index', @response.body + assert_equal '/pt/projetos', pt_projects_path + + get '/pt/projetos/1/editar' + assert_equal 'projects#edit', @response.body + assert_equal '/pt/projetos/1/editar', edit_pt_project_path(1) + + get '/pt/administrador' + assert_equal 'admins#show', @response.body + assert_equal '/pt/administrador', pt_admin_path + + get '/pt/administrador/novo' + assert_equal 'admins#new', @response.body + assert_equal '/pt/administrador/novo', new_pt_admin_path + + put '/pt/administrador/ativar' + assert_equal 'admins#activate', @response.body + assert_equal '/pt/administrador/ativar', activate_pt_admin_path end def test_path_option_override - with_test_routes do - get '/pt/projetos/novo/abrir' - assert_equal 'projects#open', @response.body - assert_equal '/pt/projetos/novo/abrir', open_new_pt_project_path - - put '/pt/projetos/1/fechar' - assert_equal 'projects#close', @response.body - assert_equal '/pt/projetos/1/fechar', close_pt_project_path(1) - end + get '/pt/projetos/novo/abrir' + assert_equal 'projects#open', @response.body + assert_equal '/pt/projetos/novo/abrir', open_new_pt_project_path + + put '/pt/projetos/1/fechar' + assert_equal 'projects#close', @response.body + assert_equal '/pt/projetos/1/fechar', close_pt_project_path(1) end def test_sprockets - with_test_routes do - get '/sprockets.js' - assert_equal 'javascripts', @response.body - end + get '/sprockets.js' + assert_equal 'javascripts', @response.body end def test_update_person_route - with_test_routes do - get '/people/1/update' - assert_equal 'people#update', @response.body + get '/people/1/update' + assert_equal 'people#update', @response.body - assert_equal '/people/1/update', update_person_path(:id => 1) - end + assert_equal '/people/1/update', update_person_path(:id => 1) end def test_update_project_person - with_test_routes do - get '/projects/1/people/2/update' - assert_equal 'people#update', @response.body + get '/projects/1/people/2/update' + assert_equal 'people#update', @response.body - assert_equal '/projects/1/people/2/update', update_project_person_path(:project_id => 1, :id => 2) - end + assert_equal '/projects/1/people/2/update', update_project_person_path(:project_id => 1, :id => 2) end def test_forum_products - with_test_routes do - get '/forum' - assert_equal 'forum/products#index', @response.body - assert_equal '/forum', forum_products_path - - get '/forum/basecamp' - assert_equal 'forum/products#show', @response.body - assert_equal '/forum/basecamp', forum_product_path(:id => 'basecamp') - - get '/forum/basecamp/questions' - assert_equal 'forum/questions#index', @response.body - assert_equal '/forum/basecamp/questions', forum_product_questions_path(:product_id => 'basecamp') - - get '/forum/basecamp/questions/1' - assert_equal 'forum/questions#show', @response.body - assert_equal '/forum/basecamp/questions/1', forum_product_question_path(:product_id => 'basecamp', :id => 1) - end + get '/forum' + assert_equal 'forum/products#index', @response.body + assert_equal '/forum', forum_products_path + + get '/forum/basecamp' + assert_equal 'forum/products#show', @response.body + assert_equal '/forum/basecamp', forum_product_path(:id => 'basecamp') + + get '/forum/basecamp/questions' + assert_equal 'forum/questions#index', @response.body + assert_equal '/forum/basecamp/questions', forum_product_questions_path(:product_id => 'basecamp') + + get '/forum/basecamp/questions/1' + assert_equal 'forum/questions#show', @response.body + assert_equal '/forum/basecamp/questions/1', forum_product_question_path(:product_id => 'basecamp', :id => 1) end def test_articles_perma - with_test_routes do - get '/articles/2009/08/18/rails-3' - assert_equal 'articles#show', @response.body + get '/articles/2009/08/18/rails-3' + assert_equal 'articles#show', @response.body - assert_equal '/articles/2009/8/18/rails-3', article_path(:year => 2009, :month => 8, :day => 18, :title => 'rails-3') - end + assert_equal '/articles/2009/8/18/rails-3', article_path(:year => 2009, :month => 8, :day => 18, :title => 'rails-3') end def test_account_namespace - with_test_routes do - get '/account/subscription' - assert_equal 'account/subscriptions#show', @response.body - assert_equal '/account/subscription', account_subscription_path - - get '/account/credit' - assert_equal 'account/credits#show', @response.body - assert_equal '/account/credit', account_credit_path - - get '/account/credit_card' - assert_equal 'account/credit_cards#show', @response.body - assert_equal '/account/credit_card', account_credit_card_path - end + get '/account/subscription' + assert_equal 'account/subscriptions#show', @response.body + assert_equal '/account/subscription', account_subscription_path + + get '/account/credit' + assert_equal 'account/credits#show', @response.body + assert_equal '/account/credit', account_credit_path + + get '/account/credit_card' + assert_equal 'account/credit_cards#show', @response.body + assert_equal '/account/credit_card', account_credit_card_path end def test_nested_namespace - with_test_routes do - get '/account/admin/subscription' - assert_equal 'account/admin/subscriptions#show', @response.body - assert_equal '/account/admin/subscription', account_admin_subscription_path - end + get '/account/admin/subscription' + assert_equal 'account/admin/subscriptions#show', @response.body + assert_equal '/account/admin/subscription', account_admin_subscription_path end def test_namespace_nested_in_resources - with_test_routes do - get '/clients/1/google/account' - assert_equal '/clients/1/google/account', client_google_account_path(1) - assert_equal 'google/accounts#show', @response.body - - get '/clients/1/google/account/secret/info' - assert_equal '/clients/1/google/account/secret/info', client_google_account_secret_info_path(1) - assert_equal 'google/secret/infos#show', @response.body - end + get '/clients/1/google/account' + assert_equal '/clients/1/google/account', client_google_account_path(1) + assert_equal 'google/accounts#show', @response.body + + get '/clients/1/google/account/secret/info' + assert_equal '/clients/1/google/account/secret/info', client_google_account_secret_info_path(1) + assert_equal 'google/secret/infos#show', @response.body end def test_namespace_with_options - with_test_routes do - get '/usuarios' - assert_equal '/usuarios', users_root_path - assert_equal 'users/home#index', @response.body - end + get '/usuarios' + assert_equal '/usuarios', users_root_path + assert_equal 'users/home#index', @response.body end def test_articles_with_id - with_test_routes do - get '/articles/rails/1' - assert_equal 'articles#with_id', @response.body + get '/articles/rails/1' + assert_equal 'articles#with_id', @response.body - get '/articles/123/1' - assert_equal 'pass', @response.headers['X-Cascade'] + get '/articles/123/1' + assert_equal 'pass', @response.headers['X-Cascade'] - assert_equal '/articles/rails/1', article_with_title_path(:title => 'rails', :id => 1) - end + assert_equal '/articles/rails/1', article_with_title_path(:title => 'rails', :id => 1) end def test_access_token_rooms - with_test_routes do - get '/12345/rooms' - assert_equal 'rooms#index', @response.body + get '/12345/rooms' + assert_equal 'rooms#index', @response.body - get '/12345/rooms/1' - assert_equal 'rooms#show', @response.body + get '/12345/rooms/1' + assert_equal 'rooms#show', @response.body - get '/12345/rooms/1/edit' - assert_equal 'rooms#edit', @response.body - end + get '/12345/rooms/1/edit' + assert_equal 'rooms#edit', @response.body end def test_root - with_test_routes do - assert_equal '/', root_path - get '/' - assert_equal 'projects#index', @response.body - end + assert_equal '/', root_path + get '/' + assert_equal 'projects#index', @response.body end def test_index - with_test_routes do - assert_equal '/info', info_path - get '/info' - assert_equal 'projects#info', @response.body - end + assert_equal '/info', info_path + get '/info' + assert_equal 'projects#info', @response.body end def test_match_shorthand_with_no_scope - with_test_routes do - assert_equal '/account/overview', account_overview_path - get '/account/overview' - assert_equal 'account#overview', @response.body - end + assert_equal '/account/overview', account_overview_path + get '/account/overview' + assert_equal 'account#overview', @response.body end def test_match_shorthand_inside_namespace - with_test_routes do - assert_equal '/account/shorthand', account_shorthand_path - get '/account/shorthand' - assert_equal 'account#shorthand', @response.body - end + assert_equal '/account/shorthand', account_shorthand_path + get '/account/shorthand' + assert_equal 'account#shorthand', @response.body end def test_dynamically_generated_helpers_on_collection_do_not_clobber_resources_url_helper - with_test_routes do - assert_equal '/replies', replies_path - end + assert_equal '/replies', replies_path end def test_scoped_controller_with_namespace_and_action - with_test_routes do - assert_equal '/account/twitter/callback', account_callback_path("twitter") - get '/account/twitter/callback' - assert_equal 'account/callbacks#twitter', @response.body + assert_equal '/account/twitter/callback', account_callback_path("twitter") + get '/account/twitter/callback' + assert_equal 'account/callbacks#twitter', @response.body - get '/account/whatever/callback' - assert_equal 'Not Found', @response.body - end + get '/account/whatever/callback' + assert_equal 'Not Found', @response.body end def test_convention_match_nested_and_with_leading_slash - with_test_routes do - assert_equal '/account/nested/overview', account_nested_overview_path - get '/account/nested/overview' - assert_equal 'account/nested#overview', @response.body - end + assert_equal '/account/nested/overview', account_nested_overview_path + get '/account/nested/overview' + assert_equal 'account/nested#overview', @response.body end def test_convention_with_explicit_end - with_test_routes do - get '/sign_in' - assert_equal 'sessions#new', @response.body - assert_equal '/sign_in', sign_in_path - end + get '/sign_in' + assert_equal 'sessions#new', @response.body + assert_equal '/sign_in', sign_in_path end def test_redirect_with_complete_url_and_status - with_test_routes do - get '/account/google' - verify_redirect 'http://www.google.com/', 302 - end + get '/account/google' + verify_redirect 'http://www.google.com/', 302 end def test_redirect_with_port previous_host, self.host = self.host, 'www.example.com:3000' - with_test_routes do - get '/account/login' - verify_redirect 'http://www.example.com:3000/login' - end + + get '/account/login' + verify_redirect 'http://www.example.com:3000/login' ensure self.host = previous_host end def test_normalize_namespaced_matches - with_test_routes do - assert_equal '/account/description', account_description_path + assert_equal '/account/description', account_description_path - get '/account/description' - assert_equal 'account#description', @response.body - end + get '/account/description' + assert_equal 'account#description', @response.body end def test_namespaced_roots - with_test_routes do - assert_equal '/account', account_root_path - get '/account' - assert_equal 'account/account#index', @response.body - end + assert_equal '/account', account_root_path + get '/account' + assert_equal 'account/account#index', @response.body end def test_optional_scoped_root - with_test_routes do - assert_equal '/en', root_path("en") - get '/en' - assert_equal 'projects#index', @response.body - end + assert_equal '/en', root_path("en") + get '/en' + assert_equal 'projects#index', @response.body end def test_optional_scoped_path - with_test_routes do - assert_equal '/en/descriptions', descriptions_path("en") - assert_equal '/descriptions', descriptions_path(nil) - assert_equal '/en/descriptions/1', description_path("en", 1) - assert_equal '/descriptions/1', description_path(nil, 1) + assert_equal '/en/descriptions', descriptions_path("en") + assert_equal '/descriptions', descriptions_path(nil) + assert_equal '/en/descriptions/1', description_path("en", 1) + assert_equal '/descriptions/1', description_path(nil, 1) - get '/en/descriptions' - assert_equal 'descriptions#index', @response.body + get '/en/descriptions' + assert_equal 'descriptions#index', @response.body - get '/descriptions' - assert_equal 'descriptions#index', @response.body + get '/descriptions' + assert_equal 'descriptions#index', @response.body - get '/en/descriptions/1' - assert_equal 'descriptions#show', @response.body + get '/en/descriptions/1' + assert_equal 'descriptions#show', @response.body - get '/descriptions/1' - assert_equal 'descriptions#show', @response.body - end + get '/descriptions/1' + assert_equal 'descriptions#show', @response.body end def test_nested_optional_scoped_path - with_test_routes do - assert_equal '/admin/en/descriptions', admin_descriptions_path("en") - assert_equal '/admin/descriptions', admin_descriptions_path(nil) - assert_equal '/admin/en/descriptions/1', admin_description_path("en", 1) - assert_equal '/admin/descriptions/1', admin_description_path(nil, 1) + assert_equal '/admin/en/descriptions', admin_descriptions_path("en") + assert_equal '/admin/descriptions', admin_descriptions_path(nil) + assert_equal '/admin/en/descriptions/1', admin_description_path("en", 1) + assert_equal '/admin/descriptions/1', admin_description_path(nil, 1) - get '/admin/en/descriptions' - assert_equal 'admin/descriptions#index', @response.body + get '/admin/en/descriptions' + assert_equal 'admin/descriptions#index', @response.body - get '/admin/descriptions' - assert_equal 'admin/descriptions#index', @response.body + get '/admin/descriptions' + assert_equal 'admin/descriptions#index', @response.body - get '/admin/en/descriptions/1' - assert_equal 'admin/descriptions#show', @response.body + get '/admin/en/descriptions/1' + assert_equal 'admin/descriptions#show', @response.body - get '/admin/descriptions/1' - assert_equal 'admin/descriptions#show', @response.body - end + get '/admin/descriptions/1' + assert_equal 'admin/descriptions#show', @response.body + end + + def test_nested_optional_path_shorthand + get '/registrations/new' + assert_nil @request.params[:locale] + + get '/en/registrations/new' + assert_equal 'en', @request.params[:locale] end def test_default_params - with_test_routes do - get '/inline_pages' - assert_equal 'home', @request.params[:id] + get '/inline_pages' + assert_equal 'home', @request.params[:id] - get '/default_pages' - assert_equal 'home', @request.params[:id] + get '/default_pages' + assert_equal 'home', @request.params[:id] - get '/scoped_pages' - assert_equal 'home', @request.params[:id] - end + get '/scoped_pages' + assert_equal 'home', @request.params[:id] end def test_resource_constraints - with_test_routes do - get '/products/1' - assert_equal 'pass', @response.headers['X-Cascade'] - get '/products' - assert_equal 'products#root', @response.body - get '/products/favorite' - assert_equal 'products#favorite', @response.body - get '/products/0001' - assert_equal 'products#show', @response.body - - get '/products/1/images' - assert_equal 'pass', @response.headers['X-Cascade'] - get '/products/0001/images' - assert_equal 'images#index', @response.body - get '/products/0001/images/0001' - assert_equal 'images#show', @response.body - - get '/dashboard', {}, {'REMOTE_ADDR' => '10.0.0.100'} - assert_equal 'pass', @response.headers['X-Cascade'] - get '/dashboard', {}, {'REMOTE_ADDR' => '192.168.1.100'} - assert_equal 'dashboards#show', @response.body - end + get '/products/1' + assert_equal 'pass', @response.headers['X-Cascade'] + get '/products' + assert_equal 'products#root', @response.body + get '/products/favorite' + assert_equal 'products#favorite', @response.body + get '/products/0001' + assert_equal 'products#show', @response.body + + get '/products/1/images' + assert_equal 'pass', @response.headers['X-Cascade'] + get '/products/0001/images' + assert_equal 'images#index', @response.body + get '/products/0001/images/0001' + assert_equal 'images#show', @response.body + + get '/dashboard', {}, {'REMOTE_ADDR' => '10.0.0.100'} + assert_equal 'pass', @response.headers['X-Cascade'] + get '/dashboard', {}, {'REMOTE_ADDR' => '192.168.1.100'} + assert_equal 'dashboards#show', @response.body end def test_root_works_in_the_resources_scope @@ -1487,731 +1420,651 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end def test_module_scope - with_test_routes do - get '/token' - assert_equal 'api/tokens#show', @response.body - assert_equal '/token', token_path - end + get '/token' + assert_equal 'api/tokens#show', @response.body + assert_equal '/token', token_path end def test_path_scope - with_test_routes do - get '/api/me' - assert_equal 'mes#show', @response.body - assert_equal '/api/me', me_path + get '/api/me' + assert_equal 'mes#show', @response.body + assert_equal '/api/me', me_path - get '/api' - assert_equal 'mes#index', @response.body - end + get '/api' + assert_equal 'mes#index', @response.body end def test_url_generator_for_generic_route - with_test_routes do - get 'whatever/foo/bar' - assert_equal 'foo#bar', @response.body + get 'whatever/foo/bar' + assert_equal 'foo#bar', @response.body - assert_equal 'http://www.example.com/whatever/foo/bar/1', - url_for(:controller => "foo", :action => "bar", :id => 1) - end + assert_equal 'http://www.example.com/whatever/foo/bar/1', + url_for(:controller => "foo", :action => "bar", :id => 1) end def test_url_generator_for_namespaced_generic_route - with_test_routes do - get 'whatever/foo/bar/show' - assert_equal 'foo/bar#show', @response.body + get 'whatever/foo/bar/show' + assert_equal 'foo/bar#show', @response.body - get 'whatever/foo/bar/show/1' - assert_equal 'foo/bar#show', @response.body + get 'whatever/foo/bar/show/1' + assert_equal 'foo/bar#show', @response.body - assert_equal 'http://www.example.com/whatever/foo/bar/show', - url_for(:controller => "foo/bar", :action => "show") + assert_equal 'http://www.example.com/whatever/foo/bar/show', + url_for(:controller => "foo/bar", :action => "show") - assert_equal 'http://www.example.com/whatever/foo/bar/show/1', - url_for(:controller => "foo/bar", :action => "show", :id => '1') - end + assert_equal 'http://www.example.com/whatever/foo/bar/show/1', + url_for(:controller => "foo/bar", :action => "show", :id => '1') end def test_assert_recognizes_account_overview - with_test_routes do - assert_recognizes({:controller => "account", :action => "overview"}, "/account/overview") - end + assert_recognizes({:controller => "account", :action => "overview"}, "/account/overview") end def test_resource_new_actions - with_test_routes do - assert_equal '/replies/new/preview', preview_new_reply_path - assert_equal '/pt/projetos/novo/preview', preview_new_pt_project_path - assert_equal '/pt/administrador/novo/preview', preview_new_pt_admin_path - assert_equal '/pt/products/novo/preview', preview_new_pt_product_path - assert_equal '/profile/new/preview', preview_new_profile_path + assert_equal '/replies/new/preview', preview_new_reply_path + assert_equal '/pt/projetos/novo/preview', preview_new_pt_project_path + assert_equal '/pt/administrador/novo/preview', preview_new_pt_admin_path + assert_equal '/pt/products/novo/preview', preview_new_pt_product_path + assert_equal '/profile/new/preview', preview_new_profile_path - post '/replies/new/preview' - assert_equal 'replies#preview', @response.body + post '/replies/new/preview' + assert_equal 'replies#preview', @response.body - post '/pt/projetos/novo/preview' - assert_equal 'projects#preview', @response.body + post '/pt/projetos/novo/preview' + assert_equal 'projects#preview', @response.body - post '/pt/administrador/novo/preview' - assert_equal 'admins#preview', @response.body + post '/pt/administrador/novo/preview' + assert_equal 'admins#preview', @response.body - post '/pt/products/novo/preview' - assert_equal 'products#preview', @response.body + post '/pt/products/novo/preview' + assert_equal 'products#preview', @response.body - post '/profile/new/preview' - assert_equal 'profiles#preview', @response.body - end + post '/profile/new/preview' + assert_equal 'profiles#preview', @response.body end def test_resource_merges_options_from_scope - with_test_routes do - assert_raise(NameError) { new_account_path } + assert_raise(NameError) { new_account_path } - get '/account/new' - assert_equal 404, status - end + get '/account/new' + assert_equal 404, status end def test_resources_merges_options_from_scope - with_test_routes do - assert_raise(NoMethodError) { edit_product_path('1') } + assert_raise(NoMethodError) { edit_product_path('1') } - get '/products/1/edit' - assert_equal 404, status + get '/products/1/edit' + assert_equal 404, status - assert_raise(NoMethodError) { edit_product_image_path('1', '2') } + assert_raise(NoMethodError) { edit_product_image_path('1', '2') } - post '/products/1/images/2/edit' - assert_equal 404, status - end + post '/products/1/images/2/edit' + assert_equal 404, status end def test_shallow_nested_resources - with_test_routes do - - get '/api/teams' - assert_equal 'api/teams#index', @response.body - assert_equal '/api/teams', api_teams_path + get '/api/teams' + assert_equal 'api/teams#index', @response.body + assert_equal '/api/teams', api_teams_path - get '/api/teams/new' - assert_equal 'api/teams#new', @response.body - assert_equal '/api/teams/new', new_api_team_path + get '/api/teams/new' + assert_equal 'api/teams#new', @response.body + assert_equal '/api/teams/new', new_api_team_path - get '/api/teams/1' - assert_equal 'api/teams#show', @response.body - assert_equal '/api/teams/1', api_team_path(:id => '1') + get '/api/teams/1' + assert_equal 'api/teams#show', @response.body + assert_equal '/api/teams/1', api_team_path(:id => '1') - get '/api/teams/1/edit' - assert_equal 'api/teams#edit', @response.body - assert_equal '/api/teams/1/edit', edit_api_team_path(:id => '1') + get '/api/teams/1/edit' + assert_equal 'api/teams#edit', @response.body + assert_equal '/api/teams/1/edit', edit_api_team_path(:id => '1') - get '/api/teams/1/players' - assert_equal 'api/players#index', @response.body - assert_equal '/api/teams/1/players', api_team_players_path(:team_id => '1') + get '/api/teams/1/players' + assert_equal 'api/players#index', @response.body + assert_equal '/api/teams/1/players', api_team_players_path(:team_id => '1') - get '/api/teams/1/players/new' - assert_equal 'api/players#new', @response.body - assert_equal '/api/teams/1/players/new', new_api_team_player_path(:team_id => '1') + get '/api/teams/1/players/new' + assert_equal 'api/players#new', @response.body + assert_equal '/api/teams/1/players/new', new_api_team_player_path(:team_id => '1') - get '/api/players/2' - assert_equal 'api/players#show', @response.body - assert_equal '/api/players/2', api_player_path(:id => '2') + get '/api/players/2' + assert_equal 'api/players#show', @response.body + assert_equal '/api/players/2', api_player_path(:id => '2') - get '/api/players/2/edit' - assert_equal 'api/players#edit', @response.body - assert_equal '/api/players/2/edit', edit_api_player_path(:id => '2') + get '/api/players/2/edit' + assert_equal 'api/players#edit', @response.body + assert_equal '/api/players/2/edit', edit_api_player_path(:id => '2') - get '/api/teams/1/captain' - assert_equal 'api/captains#show', @response.body - assert_equal '/api/teams/1/captain', api_team_captain_path(:team_id => '1') + get '/api/teams/1/captain' + assert_equal 'api/captains#show', @response.body + assert_equal '/api/teams/1/captain', api_team_captain_path(:team_id => '1') - get '/api/teams/1/captain/new' - assert_equal 'api/captains#new', @response.body - assert_equal '/api/teams/1/captain/new', new_api_team_captain_path(:team_id => '1') + get '/api/teams/1/captain/new' + assert_equal 'api/captains#new', @response.body + assert_equal '/api/teams/1/captain/new', new_api_team_captain_path(:team_id => '1') - get '/api/teams/1/captain/edit' - assert_equal 'api/captains#edit', @response.body - assert_equal '/api/teams/1/captain/edit', edit_api_team_captain_path(:team_id => '1') + get '/api/teams/1/captain/edit' + assert_equal 'api/captains#edit', @response.body + assert_equal '/api/teams/1/captain/edit', edit_api_team_captain_path(:team_id => '1') - get '/threads' - assert_equal 'threads#index', @response.body - assert_equal '/threads', threads_path + get '/threads' + assert_equal 'threads#index', @response.body + assert_equal '/threads', threads_path - get '/threads/new' - assert_equal 'threads#new', @response.body - assert_equal '/threads/new', new_thread_path + get '/threads/new' + assert_equal 'threads#new', @response.body + assert_equal '/threads/new', new_thread_path - get '/threads/1' - assert_equal 'threads#show', @response.body - assert_equal '/threads/1', thread_path(:id => '1') + get '/threads/1' + assert_equal 'threads#show', @response.body + assert_equal '/threads/1', thread_path(:id => '1') - get '/threads/1/edit' - assert_equal 'threads#edit', @response.body - assert_equal '/threads/1/edit', edit_thread_path(:id => '1') + get '/threads/1/edit' + assert_equal 'threads#edit', @response.body + assert_equal '/threads/1/edit', edit_thread_path(:id => '1') - get '/threads/1/owner' - assert_equal 'owners#show', @response.body - assert_equal '/threads/1/owner', thread_owner_path(:thread_id => '1') + get '/threads/1/owner' + assert_equal 'owners#show', @response.body + assert_equal '/threads/1/owner', thread_owner_path(:thread_id => '1') - get '/threads/1/messages' - assert_equal 'messages#index', @response.body - assert_equal '/threads/1/messages', thread_messages_path(:thread_id => '1') + get '/threads/1/messages' + assert_equal 'messages#index', @response.body + assert_equal '/threads/1/messages', thread_messages_path(:thread_id => '1') - get '/threads/1/messages/new' - assert_equal 'messages#new', @response.body - assert_equal '/threads/1/messages/new', new_thread_message_path(:thread_id => '1') + get '/threads/1/messages/new' + assert_equal 'messages#new', @response.body + assert_equal '/threads/1/messages/new', new_thread_message_path(:thread_id => '1') - get '/messages/2' - assert_equal 'messages#show', @response.body - assert_equal '/messages/2', message_path(:id => '2') + get '/messages/2' + assert_equal 'messages#show', @response.body + assert_equal '/messages/2', message_path(:id => '2') - get '/messages/2/edit' - assert_equal 'messages#edit', @response.body - assert_equal '/messages/2/edit', edit_message_path(:id => '2') + get '/messages/2/edit' + assert_equal 'messages#edit', @response.body + assert_equal '/messages/2/edit', edit_message_path(:id => '2') - get '/messages/2/comments' - assert_equal 'comments#index', @response.body - assert_equal '/messages/2/comments', message_comments_path(:message_id => '2') + get '/messages/2/comments' + assert_equal 'comments#index', @response.body + assert_equal '/messages/2/comments', message_comments_path(:message_id => '2') - get '/messages/2/comments/new' - assert_equal 'comments#new', @response.body - assert_equal '/messages/2/comments/new', new_message_comment_path(:message_id => '2') + get '/messages/2/comments/new' + assert_equal 'comments#new', @response.body + assert_equal '/messages/2/comments/new', new_message_comment_path(:message_id => '2') - get '/comments/3' - assert_equal 'comments#show', @response.body - assert_equal '/comments/3', comment_path(:id => '3') + get '/comments/3' + assert_equal 'comments#show', @response.body + assert_equal '/comments/3', comment_path(:id => '3') - get '/comments/3/edit' - assert_equal 'comments#edit', @response.body - assert_equal '/comments/3/edit', edit_comment_path(:id => '3') + get '/comments/3/edit' + assert_equal 'comments#edit', @response.body + assert_equal '/comments/3/edit', edit_comment_path(:id => '3') - post '/comments/3/preview' - assert_equal 'comments#preview', @response.body - assert_equal '/comments/3/preview', preview_comment_path(:id => '3') - end + post '/comments/3/preview' + assert_equal 'comments#preview', @response.body + assert_equal '/comments/3/preview', preview_comment_path(:id => '3') end def test_shallow_nested_resources_within_scope - with_test_routes do - - get '/hello/notes/1/trackbacks' - assert_equal 'trackbacks#index', @response.body - assert_equal '/hello/notes/1/trackbacks', note_trackbacks_path(:note_id => 1) + get '/hello/notes/1/trackbacks' + assert_equal 'trackbacks#index', @response.body + assert_equal '/hello/notes/1/trackbacks', note_trackbacks_path(:note_id => 1) - get '/hello/notes/1/edit' - assert_equal 'notes#edit', @response.body - assert_equal '/hello/notes/1/edit', edit_note_path(:id => '1') + get '/hello/notes/1/edit' + assert_equal 'notes#edit', @response.body + assert_equal '/hello/notes/1/edit', edit_note_path(:id => '1') - get '/hello/notes/1/trackbacks/new' - assert_equal 'trackbacks#new', @response.body - assert_equal '/hello/notes/1/trackbacks/new', new_note_trackback_path(:note_id => 1) + get '/hello/notes/1/trackbacks/new' + assert_equal 'trackbacks#new', @response.body + assert_equal '/hello/notes/1/trackbacks/new', new_note_trackback_path(:note_id => 1) - get '/hello/trackbacks/1' - assert_equal 'trackbacks#show', @response.body - assert_equal '/hello/trackbacks/1', trackback_path(:id => '1') + get '/hello/trackbacks/1' + assert_equal 'trackbacks#show', @response.body + assert_equal '/hello/trackbacks/1', trackback_path(:id => '1') - get '/hello/trackbacks/1/edit' - assert_equal 'trackbacks#edit', @response.body - assert_equal '/hello/trackbacks/1/edit', edit_trackback_path(:id => '1') + get '/hello/trackbacks/1/edit' + assert_equal 'trackbacks#edit', @response.body + assert_equal '/hello/trackbacks/1/edit', edit_trackback_path(:id => '1') - put '/hello/trackbacks/1' - assert_equal 'trackbacks#update', @response.body + put '/hello/trackbacks/1' + assert_equal 'trackbacks#update', @response.body - post '/hello/notes/1/trackbacks' - assert_equal 'trackbacks#create', @response.body + post '/hello/notes/1/trackbacks' + assert_equal 'trackbacks#create', @response.body - delete '/hello/trackbacks/1' - assert_equal 'trackbacks#destroy', @response.body + delete '/hello/trackbacks/1' + assert_equal 'trackbacks#destroy', @response.body - get '/hello/notes' - assert_equal 'notes#index', @response.body + get '/hello/notes' + assert_equal 'notes#index', @response.body - post '/hello/notes' - assert_equal 'notes#create', @response.body + post '/hello/notes' + assert_equal 'notes#create', @response.body - get '/hello/notes/new' - assert_equal 'notes#new', @response.body - assert_equal '/hello/notes/new', new_note_path + get '/hello/notes/new' + assert_equal 'notes#new', @response.body + assert_equal '/hello/notes/new', new_note_path - get '/hello/notes/1' - assert_equal 'notes#show', @response.body - assert_equal '/hello/notes/1', note_path(:id => 1) + get '/hello/notes/1' + assert_equal 'notes#show', @response.body + assert_equal '/hello/notes/1', note_path(:id => 1) - put '/hello/notes/1' - assert_equal 'notes#update', @response.body + put '/hello/notes/1' + assert_equal 'notes#update', @response.body - delete '/hello/notes/1' - assert_equal 'notes#destroy', @response.body - end + delete '/hello/notes/1' + assert_equal 'notes#destroy', @response.body end def test_custom_resource_routes_are_scoped - with_test_routes do - assert_equal '/customers/recent', recent_customers_path - assert_equal '/customers/1/profile', profile_customer_path(:id => '1') - assert_equal '/customers/1/secret/profile', secret_profile_customer_path(:id => '1') - assert_equal '/customers/new/preview', another_preview_new_customer_path - assert_equal '/customers/1/avatar/thumbnail.jpg', thumbnail_customer_avatar_path(:customer_id => '1', :format => :jpg) - assert_equal '/customers/1/invoices/outstanding', outstanding_customer_invoices_path(:customer_id => '1') - assert_equal '/customers/1/invoices/2/print', print_customer_invoice_path(:customer_id => '1', :id => '2') - assert_equal '/customers/1/invoices/new/preview', preview_new_customer_invoice_path(:customer_id => '1') - assert_equal '/customers/1/notes/new/preview', preview_new_customer_note_path(:customer_id => '1') - assert_equal '/notes/1/print', print_note_path(:id => '1') - assert_equal '/api/customers/recent', recent_api_customers_path - assert_equal '/api/customers/1/profile', profile_api_customer_path(:id => '1') - assert_equal '/api/customers/new/preview', preview_new_api_customer_path - - get '/customers/1/invoices/overdue' - assert_equal 'invoices#overdue', @response.body - - get '/customers/1/secret/profile' - assert_equal 'customers#secret', @response.body - end + assert_equal '/customers/recent', recent_customers_path + assert_equal '/customers/1/profile', profile_customer_path(:id => '1') + assert_equal '/customers/1/secret/profile', secret_profile_customer_path(:id => '1') + assert_equal '/customers/new/preview', another_preview_new_customer_path + assert_equal '/customers/1/avatar/thumbnail.jpg', thumbnail_customer_avatar_path(:customer_id => '1', :format => :jpg) + assert_equal '/customers/1/invoices/outstanding', outstanding_customer_invoices_path(:customer_id => '1') + assert_equal '/customers/1/invoices/2/print', print_customer_invoice_path(:customer_id => '1', :id => '2') + assert_equal '/customers/1/invoices/new/preview', preview_new_customer_invoice_path(:customer_id => '1') + assert_equal '/customers/1/notes/new/preview', preview_new_customer_note_path(:customer_id => '1') + assert_equal '/notes/1/print', print_note_path(:id => '1') + assert_equal '/api/customers/recent', recent_api_customers_path + assert_equal '/api/customers/1/profile', profile_api_customer_path(:id => '1') + assert_equal '/api/customers/new/preview', preview_new_api_customer_path + + get '/customers/1/invoices/overdue' + assert_equal 'invoices#overdue', @response.body + + get '/customers/1/secret/profile' + assert_equal 'customers#secret', @response.body end def test_shallow_nested_routes_ignore_module - with_test_routes do - get '/errors/1/notices' - assert_equal 'api/notices#index', @response.body - assert_equal '/errors/1/notices', error_notices_path(:error_id => '1') - - get '/notices/1' - assert_equal 'api/notices#show', @response.body - assert_equal '/notices/1', notice_path(:id => '1') - end + get '/errors/1/notices' + assert_equal 'api/notices#index', @response.body + assert_equal '/errors/1/notices', error_notices_path(:error_id => '1') + + get '/notices/1' + assert_equal 'api/notices#show', @response.body + assert_equal '/notices/1', notice_path(:id => '1') end def test_non_greedy_regexp - with_test_routes do - get '/api/1.0/users' - assert_equal 'api/users#index', @response.body - assert_equal '/api/1.0/users', api_users_path(:version => '1.0') - - get '/api/1.0/users.json' - assert_equal 'api/users#index', @response.body - assert_equal true, @request.format.json? - assert_equal '/api/1.0/users.json', api_users_path(:version => '1.0', :format => :json) - - get '/api/1.0/users/first.last' - assert_equal 'api/users#show', @response.body - assert_equal 'first.last', @request.params[:id] - assert_equal '/api/1.0/users/first.last', api_user_path(:version => '1.0', :id => 'first.last') - - get '/api/1.0/users/first.last.xml' - assert_equal 'api/users#show', @response.body - assert_equal 'first.last', @request.params[:id] - assert_equal true, @request.format.xml? - assert_equal '/api/1.0/users/first.last.xml', api_user_path(:version => '1.0', :id => 'first.last', :format => :xml) - end + get '/api/1.0/users' + assert_equal 'api/users#index', @response.body + assert_equal '/api/1.0/users', api_users_path(:version => '1.0') + + get '/api/1.0/users.json' + assert_equal 'api/users#index', @response.body + assert_equal true, @request.format.json? + assert_equal '/api/1.0/users.json', api_users_path(:version => '1.0', :format => :json) + + get '/api/1.0/users/first.last' + assert_equal 'api/users#show', @response.body + assert_equal 'first.last', @request.params[:id] + assert_equal '/api/1.0/users/first.last', api_user_path(:version => '1.0', :id => 'first.last') + + get '/api/1.0/users/first.last.xml' + assert_equal 'api/users#show', @response.body + assert_equal 'first.last', @request.params[:id] + assert_equal true, @request.format.xml? + assert_equal '/api/1.0/users/first.last.xml', api_user_path(:version => '1.0', :id => 'first.last', :format => :xml) end def test_glob_parameter_accepts_regexp - with_test_routes do - get '/en/path/to/existing/file.html' - assert_equal 200, @response.status - end + get '/en/path/to/existing/file.html' + assert_equal 200, @response.status end def test_resources_controller_name_is_not_pluralized - with_test_routes do - get '/content' - assert_equal 'content#index', @response.body - end + get '/content' + assert_equal 'content#index', @response.body end def test_url_generator_for_optional_prefix_dynamic_segment - with_test_routes do - get '/bob/followers' - assert_equal 'followers#index', @response.body - assert_equal 'http://www.example.com/bob/followers', - url_for(:controller => "followers", :action => "index", :username => "bob") - - get '/followers' - assert_equal 'followers#index', @response.body - assert_equal 'http://www.example.com/followers', - url_for(:controller => "followers", :action => "index", :username => nil) - end + get '/bob/followers' + assert_equal 'followers#index', @response.body + assert_equal 'http://www.example.com/bob/followers', + url_for(:controller => "followers", :action => "index", :username => "bob") + + get '/followers' + assert_equal 'followers#index', @response.body + assert_equal 'http://www.example.com/followers', + url_for(:controller => "followers", :action => "index", :username => nil) end def test_url_generator_for_optional_suffix_static_and_dynamic_segment - with_test_routes do - get '/groups/user/bob' - assert_equal 'groups#index', @response.body - assert_equal 'http://www.example.com/groups/user/bob', - url_for(:controller => "groups", :action => "index", :username => "bob") - - get '/groups' - assert_equal 'groups#index', @response.body - assert_equal 'http://www.example.com/groups', - url_for(:controller => "groups", :action => "index", :username => nil) - end + get '/groups/user/bob' + assert_equal 'groups#index', @response.body + assert_equal 'http://www.example.com/groups/user/bob', + url_for(:controller => "groups", :action => "index", :username => "bob") + + get '/groups' + assert_equal 'groups#index', @response.body + assert_equal 'http://www.example.com/groups', + url_for(:controller => "groups", :action => "index", :username => nil) end def test_url_generator_for_optional_prefix_static_and_dynamic_segment - with_test_routes do - get 'user/bob/photos' - assert_equal 'photos#index', @response.body - assert_equal 'http://www.example.com/user/bob/photos', - url_for(:controller => "photos", :action => "index", :username => "bob") - - get 'photos' - assert_equal 'photos#index', @response.body - assert_equal 'http://www.example.com/photos', - url_for(:controller => "photos", :action => "index", :username => nil) - end + get 'user/bob/photos' + assert_equal 'photos#index', @response.body + assert_equal 'http://www.example.com/user/bob/photos', + url_for(:controller => "photos", :action => "index", :username => "bob") + + get 'photos' + assert_equal 'photos#index', @response.body + assert_equal 'http://www.example.com/photos', + url_for(:controller => "photos", :action => "index", :username => nil) end def test_url_recognition_for_optional_static_segments - with_test_routes do - get '/groups/discussions/messages' - assert_equal 'messages#index', @response.body + get '/groups/discussions/messages' + assert_equal 'messages#index', @response.body - get '/groups/discussions/messages/1' - assert_equal 'messages#show', @response.body + get '/groups/discussions/messages/1' + assert_equal 'messages#show', @response.body - get '/groups/messages' - assert_equal 'messages#index', @response.body + get '/groups/messages' + assert_equal 'messages#index', @response.body - get '/groups/messages/1' - assert_equal 'messages#show', @response.body + get '/groups/messages/1' + assert_equal 'messages#show', @response.body - get '/discussions/messages' - assert_equal 'messages#index', @response.body + get '/discussions/messages' + assert_equal 'messages#index', @response.body - get '/discussions/messages/1' - assert_equal 'messages#show', @response.body + get '/discussions/messages/1' + assert_equal 'messages#show', @response.body - get '/messages' - assert_equal 'messages#index', @response.body + get '/messages' + assert_equal 'messages#index', @response.body - get '/messages/1' - assert_equal 'messages#show', @response.body - end + get '/messages/1' + assert_equal 'messages#show', @response.body end def test_router_removes_invalid_conditions - with_test_routes do - get '/tickets' - assert_equal 'tickets#index', @response.body - assert_equal '/tickets', tickets_path - end + get '/tickets' + assert_equal 'tickets#index', @response.body + assert_equal '/tickets', tickets_path end def test_constraints_are_merged_from_scope - with_test_routes do - get '/movies/0001' - assert_equal 'movies#show', @response.body - assert_equal '/movies/0001', movie_path(:id => '0001') - - get '/movies/00001' - assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_path(:id => '00001') } - - get '/movies/0001/reviews' - assert_equal 'reviews#index', @response.body - assert_equal '/movies/0001/reviews', movie_reviews_path(:movie_id => '0001') - - get '/movies/00001/reviews' - assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_reviews_path(:movie_id => '00001') } - - get '/movies/0001/reviews/0001' - assert_equal 'reviews#show', @response.body - assert_equal '/movies/0001/reviews/0001', movie_review_path(:movie_id => '0001', :id => '0001') - - get '/movies/00001/reviews/0001' - assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_path(:movie_id => '00001', :id => '00001') } - - get '/movies/0001/trailer' - assert_equal 'trailers#show', @response.body - assert_equal '/movies/0001/trailer', movie_trailer_path(:movie_id => '0001') - - get '/movies/00001/trailer' - assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_trailer_path(:movie_id => '00001') } - end + get '/movies/0001' + assert_equal 'movies#show', @response.body + assert_equal '/movies/0001', movie_path(:id => '0001') + + get '/movies/00001' + assert_equal 'Not Found', @response.body + assert_raises(ActionController::RoutingError){ movie_path(:id => '00001') } + + get '/movies/0001/reviews' + assert_equal 'reviews#index', @response.body + assert_equal '/movies/0001/reviews', movie_reviews_path(:movie_id => '0001') + + get '/movies/00001/reviews' + assert_equal 'Not Found', @response.body + assert_raises(ActionController::RoutingError){ movie_reviews_path(:movie_id => '00001') } + + get '/movies/0001/reviews/0001' + assert_equal 'reviews#show', @response.body + assert_equal '/movies/0001/reviews/0001', movie_review_path(:movie_id => '0001', :id => '0001') + + get '/movies/00001/reviews/0001' + assert_equal 'Not Found', @response.body + assert_raises(ActionController::RoutingError){ movie_path(:movie_id => '00001', :id => '00001') } + + get '/movies/0001/trailer' + assert_equal 'trailers#show', @response.body + assert_equal '/movies/0001/trailer', movie_trailer_path(:movie_id => '0001') + + get '/movies/00001/trailer' + assert_equal 'Not Found', @response.body + assert_raises(ActionController::RoutingError){ movie_trailer_path(:movie_id => '00001') } end def test_only_should_be_read_from_scope - with_test_routes do - get '/only/clubs' - assert_equal 'only/clubs#index', @response.body - assert_equal '/only/clubs', only_clubs_path - - get '/only/clubs/1/edit' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { edit_only_club_path(:id => '1') } - - get '/only/clubs/1/players' - assert_equal 'only/players#index', @response.body - assert_equal '/only/clubs/1/players', only_club_players_path(:club_id => '1') - - get '/only/clubs/1/players/2/edit' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { edit_only_club_player_path(:club_id => '1', :id => '2') } - - get '/only/clubs/1/chairman' - assert_equal 'only/chairmen#show', @response.body - assert_equal '/only/clubs/1/chairman', only_club_chairman_path(:club_id => '1') - - get '/only/clubs/1/chairman/edit' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { edit_only_club_chairman_path(:club_id => '1') } - end + get '/only/clubs' + assert_equal 'only/clubs#index', @response.body + assert_equal '/only/clubs', only_clubs_path + + get '/only/clubs/1/edit' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { edit_only_club_path(:id => '1') } + + get '/only/clubs/1/players' + assert_equal 'only/players#index', @response.body + assert_equal '/only/clubs/1/players', only_club_players_path(:club_id => '1') + + get '/only/clubs/1/players/2/edit' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { edit_only_club_player_path(:club_id => '1', :id => '2') } + + get '/only/clubs/1/chairman' + assert_equal 'only/chairmen#show', @response.body + assert_equal '/only/clubs/1/chairman', only_club_chairman_path(:club_id => '1') + + get '/only/clubs/1/chairman/edit' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { edit_only_club_chairman_path(:club_id => '1') } end def test_except_should_be_read_from_scope - with_test_routes do - get '/except/clubs' - assert_equal 'except/clubs#index', @response.body - assert_equal '/except/clubs', except_clubs_path - - get '/except/clubs/1/edit' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { edit_except_club_path(:id => '1') } - - get '/except/clubs/1/players' - assert_equal 'except/players#index', @response.body - assert_equal '/except/clubs/1/players', except_club_players_path(:club_id => '1') - - get '/except/clubs/1/players/2/edit' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { edit_except_club_player_path(:club_id => '1', :id => '2') } - - get '/except/clubs/1/chairman' - assert_equal 'except/chairmen#show', @response.body - assert_equal '/except/clubs/1/chairman', except_club_chairman_path(:club_id => '1') - - get '/except/clubs/1/chairman/edit' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { edit_except_club_chairman_path(:club_id => '1') } - end + get '/except/clubs' + assert_equal 'except/clubs#index', @response.body + assert_equal '/except/clubs', except_clubs_path + + get '/except/clubs/1/edit' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { edit_except_club_path(:id => '1') } + + get '/except/clubs/1/players' + assert_equal 'except/players#index', @response.body + assert_equal '/except/clubs/1/players', except_club_players_path(:club_id => '1') + + get '/except/clubs/1/players/2/edit' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { edit_except_club_player_path(:club_id => '1', :id => '2') } + + get '/except/clubs/1/chairman' + assert_equal 'except/chairmen#show', @response.body + assert_equal '/except/clubs/1/chairman', except_club_chairman_path(:club_id => '1') + + get '/except/clubs/1/chairman/edit' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { edit_except_club_chairman_path(:club_id => '1') } end def test_only_option_should_override_scope - with_test_routes do - get '/only/sectors' - assert_equal 'only/sectors#index', @response.body - assert_equal '/only/sectors', only_sectors_path - - get '/only/sectors/1' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { only_sector_path(:id => '1') } - end + get '/only/sectors' + assert_equal 'only/sectors#index', @response.body + assert_equal '/only/sectors', only_sectors_path + + get '/only/sectors/1' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { only_sector_path(:id => '1') } end def test_only_option_should_not_inherit - with_test_routes do - get '/only/sectors/1/companies/2' - assert_equal 'only/companies#show', @response.body - assert_equal '/only/sectors/1/companies/2', only_sector_company_path(:sector_id => '1', :id => '2') - - get '/only/sectors/1/leader' - assert_equal 'only/leaders#show', @response.body - assert_equal '/only/sectors/1/leader', only_sector_leader_path(:sector_id => '1') - end + get '/only/sectors/1/companies/2' + assert_equal 'only/companies#show', @response.body + assert_equal '/only/sectors/1/companies/2', only_sector_company_path(:sector_id => '1', :id => '2') + + get '/only/sectors/1/leader' + assert_equal 'only/leaders#show', @response.body + assert_equal '/only/sectors/1/leader', only_sector_leader_path(:sector_id => '1') end def test_except_option_should_override_scope - with_test_routes do - get '/except/sectors' - assert_equal 'except/sectors#index', @response.body - assert_equal '/except/sectors', except_sectors_path - - get '/except/sectors/1' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { except_sector_path(:id => '1') } - end + get '/except/sectors' + assert_equal 'except/sectors#index', @response.body + assert_equal '/except/sectors', except_sectors_path + + get '/except/sectors/1' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { except_sector_path(:id => '1') } end def test_except_option_should_not_inherit - with_test_routes do - get '/except/sectors/1/companies/2' - assert_equal 'except/companies#show', @response.body - assert_equal '/except/sectors/1/companies/2', except_sector_company_path(:sector_id => '1', :id => '2') - - get '/except/sectors/1/leader' - assert_equal 'except/leaders#show', @response.body - assert_equal '/except/sectors/1/leader', except_sector_leader_path(:sector_id => '1') - end + get '/except/sectors/1/companies/2' + assert_equal 'except/companies#show', @response.body + assert_equal '/except/sectors/1/companies/2', except_sector_company_path(:sector_id => '1', :id => '2') + + get '/except/sectors/1/leader' + assert_equal 'except/leaders#show', @response.body + assert_equal '/except/sectors/1/leader', except_sector_leader_path(:sector_id => '1') end def test_except_option_should_override_scoped_only - with_test_routes do - get '/only/sectors/1/managers' - assert_equal 'only/managers#index', @response.body - assert_equal '/only/sectors/1/managers', only_sector_managers_path(:sector_id => '1') - - get '/only/sectors/1/managers/2' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { only_sector_manager_path(:sector_id => '1', :id => '2') } - end + get '/only/sectors/1/managers' + assert_equal 'only/managers#index', @response.body + assert_equal '/only/sectors/1/managers', only_sector_managers_path(:sector_id => '1') + + get '/only/sectors/1/managers/2' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { only_sector_manager_path(:sector_id => '1', :id => '2') } end def test_only_option_should_override_scoped_except - with_test_routes do - get '/except/sectors/1/managers' - assert_equal 'except/managers#index', @response.body - assert_equal '/except/sectors/1/managers', except_sector_managers_path(:sector_id => '1') - - get '/except/sectors/1/managers/2' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { except_sector_manager_path(:sector_id => '1', :id => '2') } - end + get '/except/sectors/1/managers' + assert_equal 'except/managers#index', @response.body + assert_equal '/except/sectors/1/managers', except_sector_managers_path(:sector_id => '1') + + get '/except/sectors/1/managers/2' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { except_sector_manager_path(:sector_id => '1', :id => '2') } end def test_only_scope_should_override_parent_scope - with_test_routes do - get '/only/sectors/1/companies/2/divisions' - assert_equal 'only/divisions#index', @response.body - assert_equal '/only/sectors/1/companies/2/divisions', only_sector_company_divisions_path(:sector_id => '1', :company_id => '2') - - get '/only/sectors/1/companies/2/divisions/3' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { only_sector_company_division_path(:sector_id => '1', :company_id => '2', :id => '3') } - end + get '/only/sectors/1/companies/2/divisions' + assert_equal 'only/divisions#index', @response.body + assert_equal '/only/sectors/1/companies/2/divisions', only_sector_company_divisions_path(:sector_id => '1', :company_id => '2') + + get '/only/sectors/1/companies/2/divisions/3' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { only_sector_company_division_path(:sector_id => '1', :company_id => '2', :id => '3') } end def test_except_scope_should_override_parent_scope - with_test_routes do - get '/except/sectors/1/companies/2/divisions' - assert_equal 'except/divisions#index', @response.body - assert_equal '/except/sectors/1/companies/2/divisions', except_sector_company_divisions_path(:sector_id => '1', :company_id => '2') - - get '/except/sectors/1/companies/2/divisions/3' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { except_sector_company_division_path(:sector_id => '1', :company_id => '2', :id => '3') } - end + get '/except/sectors/1/companies/2/divisions' + assert_equal 'except/divisions#index', @response.body + assert_equal '/except/sectors/1/companies/2/divisions', except_sector_company_divisions_path(:sector_id => '1', :company_id => '2') + + get '/except/sectors/1/companies/2/divisions/3' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { except_sector_company_division_path(:sector_id => '1', :company_id => '2', :id => '3') } end def test_except_scope_should_override_parent_only_scope - with_test_routes do - get '/only/sectors/1/companies/2/departments' - assert_equal 'only/departments#index', @response.body - assert_equal '/only/sectors/1/companies/2/departments', only_sector_company_departments_path(:sector_id => '1', :company_id => '2') - - get '/only/sectors/1/companies/2/departments/3' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { only_sector_company_department_path(:sector_id => '1', :company_id => '2', :id => '3') } - end + get '/only/sectors/1/companies/2/departments' + assert_equal 'only/departments#index', @response.body + assert_equal '/only/sectors/1/companies/2/departments', only_sector_company_departments_path(:sector_id => '1', :company_id => '2') + + get '/only/sectors/1/companies/2/departments/3' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { only_sector_company_department_path(:sector_id => '1', :company_id => '2', :id => '3') } end def test_only_scope_should_override_parent_except_scope - with_test_routes do - get '/except/sectors/1/companies/2/departments' - assert_equal 'except/departments#index', @response.body - assert_equal '/except/sectors/1/companies/2/departments', except_sector_company_departments_path(:sector_id => '1', :company_id => '2') - - get '/except/sectors/1/companies/2/departments/3' - assert_equal 'Not Found', @response.body - assert_raise(NoMethodError) { except_sector_company_department_path(:sector_id => '1', :company_id => '2', :id => '3') } - end + get '/except/sectors/1/companies/2/departments' + assert_equal 'except/departments#index', @response.body + assert_equal '/except/sectors/1/companies/2/departments', except_sector_company_departments_path(:sector_id => '1', :company_id => '2') + + get '/except/sectors/1/companies/2/departments/3' + assert_equal 'Not Found', @response.body + assert_raise(NoMethodError) { except_sector_company_department_path(:sector_id => '1', :company_id => '2', :id => '3') } end def test_resources_are_not_pluralized - with_test_routes do - get '/transport/taxis' - assert_equal 'transport/taxis#index', @response.body - assert_equal '/transport/taxis', transport_taxis_path + get '/transport/taxis' + assert_equal 'transport/taxis#index', @response.body + assert_equal '/transport/taxis', transport_taxis_path - get '/transport/taxis/new' - assert_equal 'transport/taxis#new', @response.body - assert_equal '/transport/taxis/new', new_transport_taxi_path + get '/transport/taxis/new' + assert_equal 'transport/taxis#new', @response.body + assert_equal '/transport/taxis/new', new_transport_taxi_path - post '/transport/taxis' - assert_equal 'transport/taxis#create', @response.body + post '/transport/taxis' + assert_equal 'transport/taxis#create', @response.body - get '/transport/taxis/1' - assert_equal 'transport/taxis#show', @response.body - assert_equal '/transport/taxis/1', transport_taxi_path(:id => '1') + get '/transport/taxis/1' + assert_equal 'transport/taxis#show', @response.body + assert_equal '/transport/taxis/1', transport_taxi_path(:id => '1') - get '/transport/taxis/1/edit' - assert_equal 'transport/taxis#edit', @response.body - assert_equal '/transport/taxis/1/edit', edit_transport_taxi_path(:id => '1') + get '/transport/taxis/1/edit' + assert_equal 'transport/taxis#edit', @response.body + assert_equal '/transport/taxis/1/edit', edit_transport_taxi_path(:id => '1') - put '/transport/taxis/1' - assert_equal 'transport/taxis#update', @response.body + put '/transport/taxis/1' + assert_equal 'transport/taxis#update', @response.body - delete '/transport/taxis/1' - assert_equal 'transport/taxis#destroy', @response.body - end + delete '/transport/taxis/1' + assert_equal 'transport/taxis#destroy', @response.body end def test_singleton_resources_are_not_singularized - with_test_routes do - get '/medical/taxis/new' - assert_equal 'medical/taxes#new', @response.body - assert_equal '/medical/taxis/new', new_medical_taxis_path + get '/medical/taxis/new' + assert_equal 'medical/taxis#new', @response.body + assert_equal '/medical/taxis/new', new_medical_taxis_path - post '/medical/taxis' - assert_equal 'medical/taxes#create', @response.body + post '/medical/taxis' + assert_equal 'medical/taxis#create', @response.body - get '/medical/taxis' - assert_equal 'medical/taxes#show', @response.body - assert_equal '/medical/taxis', medical_taxis_path + get '/medical/taxis' + assert_equal 'medical/taxis#show', @response.body + assert_equal '/medical/taxis', medical_taxis_path - get '/medical/taxis/edit' - assert_equal 'medical/taxes#edit', @response.body - assert_equal '/medical/taxis/edit', edit_medical_taxis_path + get '/medical/taxis/edit' + assert_equal 'medical/taxis#edit', @response.body + assert_equal '/medical/taxis/edit', edit_medical_taxis_path - put '/medical/taxis' - assert_equal 'medical/taxes#update', @response.body + put '/medical/taxis' + assert_equal 'medical/taxis#update', @response.body - delete '/medical/taxis' - assert_equal 'medical/taxes#destroy', @response.body - end + delete '/medical/taxis' + assert_equal 'medical/taxis#destroy', @response.body end def test_greedy_resource_id_regexp_doesnt_match_edit_and_custom_action - with_test_routes do - get '/sections/1/edit' - assert_equal 'sections#edit', @response.body - assert_equal '/sections/1/edit', edit_section_path(:id => '1') - - get '/sections/1/preview' - assert_equal 'sections#preview', @response.body - assert_equal '/sections/1/preview', preview_section_path(:id => '1') - end + get '/sections/1/edit' + assert_equal 'sections#edit', @response.body + assert_equal '/sections/1/edit', edit_section_path(:id => '1') + + get '/sections/1/preview' + assert_equal 'sections#preview', @response.body + assert_equal '/sections/1/preview', preview_section_path(:id => '1') end def test_resource_constraints_are_pushed_to_scope - with_test_routes do - get '/wiki/articles/Ruby_on_Rails_3.0' - assert_equal 'wiki/articles#show', @response.body - assert_equal '/wiki/articles/Ruby_on_Rails_3.0', wiki_article_path(:id => 'Ruby_on_Rails_3.0') - - get '/wiki/articles/Ruby_on_Rails_3.0/comments/new' - assert_equal 'wiki/comments#new', @response.body - assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments/new', new_wiki_article_comment_path(:article_id => 'Ruby_on_Rails_3.0') - - post '/wiki/articles/Ruby_on_Rails_3.0/comments' - assert_equal 'wiki/comments#create', @response.body - assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments', wiki_article_comments_path(:article_id => 'Ruby_on_Rails_3.0') - end + get '/wiki/articles/Ruby_on_Rails_3.0' + assert_equal 'wiki/articles#show', @response.body + assert_equal '/wiki/articles/Ruby_on_Rails_3.0', wiki_article_path(:id => 'Ruby_on_Rails_3.0') + + get '/wiki/articles/Ruby_on_Rails_3.0/comments/new' + assert_equal 'wiki/comments#new', @response.body + assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments/new', new_wiki_article_comment_path(:article_id => 'Ruby_on_Rails_3.0') + + post '/wiki/articles/Ruby_on_Rails_3.0/comments' + assert_equal 'wiki/comments#create', @response.body + assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments', wiki_article_comments_path(:article_id => 'Ruby_on_Rails_3.0') end def test_resources_path_can_be_a_symbol - with_test_routes do - get '/pages' - assert_equal 'wiki_pages#index', @response.body - assert_equal '/pages', wiki_pages_path - - get '/pages/Ruby_on_Rails' - assert_equal 'wiki_pages#show', @response.body - assert_equal '/pages/Ruby_on_Rails', wiki_page_path(:id => 'Ruby_on_Rails') - - get '/my_account' - assert_equal 'wiki_accounts#show', @response.body - assert_equal '/my_account', wiki_account_path - end + get '/pages' + assert_equal 'wiki_pages#index', @response.body + assert_equal '/pages', wiki_pages_path + + get '/pages/Ruby_on_Rails' + assert_equal 'wiki_pages#show', @response.body + assert_equal '/pages/Ruby_on_Rails', wiki_page_path(:id => 'Ruby_on_Rails') + + get '/my_account' + assert_equal 'wiki_accounts#show', @response.body + assert_equal '/my_account', wiki_account_path end def test_redirect_https - with_test_routes do - with_https do - get '/secure' - verify_redirect 'https://www.example.com/secure/login' - end + with_https do + get '/secure' + verify_redirect 'https://www.example.com/secure/login' end end @@ -2229,6 +2082,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest verify_redirect 'http://www.example.com/countries/all/cities' end + def test_constraints_block_not_carried_to_following_routes + get '/italians/writers' + assert_equal 'Not Found', @response.body + + get '/italians/sculptors' + assert_equal 'italians#sculptors', @response.body + + get '/italians/painters/botticelli' + assert_equal 'Not Found', @response.body + + get '/italians/painters/michelangelo' + assert_equal 'italians#painters', @response.body + end + def test_custom_resource_actions_defined_using_string get '/customers/inactive' assert_equal 'customers#inactive', @response.body @@ -2275,7 +2142,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_named_routes_collision_is_avoided_unless_explicitly_given_as assert_equal "/c/1", routes_collision_path(1) - assert_equal "/forced_collision", routes_forced_collision_path + assert_equal "/fc/1", routes_forced_collision_path(1) + end + + def test_redirect_argument_error + routes = Class.new { include ActionDispatch::Routing::Redirection }.new + assert_raises(ArgumentError) { routes.redirect Object.new } end def test_explicitly_avoiding_the_named_route @@ -2358,11 +2230,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal "/posts/1/admin", post_admin_root_path(:post_id => '1') end -private - def with_test_routes - yield + def test_custom_param + get '/profiles/bob' + assert_equal 'profiles#show', @response.body + assert_equal 'bob', @request.params[:username] + + get '/profiles/bob/details' + assert_equal 'bob', @request.params[:username] + + get '/profiles/bob/messages/34' + assert_equal 'bob', @request.params[:profile_username] + assert_equal '34', @request.params[:id] end +private def with_https old_https = https? https! @@ -2387,16 +2268,17 @@ class TestAppendingRoutes < ActionDispatch::IntegrationTest lambda { |e| [ 200, { 'Content-Type' => 'text/plain' }, [resp] ] } end - setup do + def setup + super s = self @app = ActionDispatch::Routing::RouteSet.new @app.append do - match '/hello' => s.simple_app('fail') - match '/goodbye' => s.simple_app('goodbye') + get '/hello' => s.simple_app('fail') + get '/goodbye' => s.simple_app('goodbye') end @app.draw do - match '/hello' => s.simple_app('hello') + get '/hello' => s.simple_app('hello') end end @@ -2416,6 +2298,81 @@ class TestAppendingRoutes < ActionDispatch::IntegrationTest end end +class TestNamespaceWithControllerOption < ActionDispatch::IntegrationTest + module ::Admin + class StorageFilesController < ActionController::Base + def index + render :text => "admin/storage_files#index" + end + end + end + + DefaultScopeRoutes = ActionDispatch::Routing::RouteSet.new + DefaultScopeRoutes.draw do + namespace :admin do + resources :storage_files, :controller => "StorageFiles" + end + end + + def app + DefaultScopeRoutes + end + + def test_controller_options + get '/admin/storage_files' + assert_equal "admin/storage_files#index", @response.body + end +end + +class TestDrawExternalFile < ActionDispatch::IntegrationTest + class ExternalController < ActionController::Base + def index + render :text => "external#index" + end + end + + DRAW_PATH = Pathname.new(File.expand_path('../../fixtures/routes', __FILE__)) + + DefaultScopeRoutes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw_paths << DRAW_PATH + end + + def app + DefaultScopeRoutes + end + + def test_draw_external_file + DefaultScopeRoutes.draw do + scope :module => 'test_draw_external_file' do + draw :external + end + end + + get '/external' + assert_equal "external#index", @response.body + end + + def test_draw_nonexistent_file + exception = assert_raise ArgumentError do + DefaultScopeRoutes.draw do + draw :nonexistent + end + end + assert_match 'Your router tried to #draw the external file nonexistent.rb', exception.message + assert_match DRAW_PATH.to_s, exception.message + end + + def test_draw_bogus_file + exception = assert_raise NoMethodError do + DefaultScopeRoutes.draw do + draw :bogus + end + end + assert_match "undefined method `wrong'", exception.message + assert_match 'test/fixtures/routes/bogus.rb:1', exception.backtrace.first + end +end + class TestDefaultScope < ActionDispatch::IntegrationTest module ::Blog class PostsController < ActionController::Base @@ -2474,3 +2431,300 @@ class TestHttpMethods < ActionDispatch::IntegrationTest end end end + +class TestUriPathEscaping < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + get '/:segment' => lambda { |env| + path_params = env['action_dispatch.request.path_parameters'] + [200, { 'Content-Type' => 'text/plain' }, [path_params[:segment]]] + }, :as => :segment + + get '/*splat' => lambda { |env| + path_params = env['action_dispatch.request.path_parameters'] + [200, { 'Content-Type' => 'text/plain' }, [path_params[:splat]]] + }, :as => :splat + end + end + + include Routes.url_helpers + def app; Routes end + + test 'escapes generated path segment' do + assert_equal '/a%20b/c+d', segment_path(:segment => 'a b/c+d') + end + + test 'unescapes recognized path segment' do + get '/a%20b%2Fc+d' + assert_equal 'a b/c+d', @response.body + end + + test 'escapes generated path splat' do + assert_equal '/a%20b/c+d', splat_path(:splat => 'a b/c+d') + end + + test 'unescapes recognized path splat' do + get '/a%20b/c+d' + assert_equal 'a b/c+d', @response.body + end +end + +class TestUnicodePaths < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + get "/#{Rack::Utils.escape("ほげ")}" => lambda { |env| + [200, { 'Content-Type' => 'text/plain' }, []] + }, :as => :unicode_path + end + end + + include Routes.url_helpers + def app; Routes end + + test 'recognizes unicode path' do + get "/#{Rack::Utils.escape("ほげ")}" + assert_equal "200", @response.code + end +end + +class TestMultipleNestedController < ActionDispatch::IntegrationTest + module ::Foo + module Bar + class BazController < ActionController::Base + def index + render :inline => "<%= url_for :controller => '/pooh', :action => 'index' %>" + end + end + end + end + + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + namespace :foo do + namespace :bar do + get "baz" => "baz#index" + end + end + get "pooh" => "pooh#index" + end + end + + include Routes.url_helpers + def app; Routes end + + test "controller option which starts with '/' from multiple nested controller" do + get "/foo/bar/baz" + assert_equal "/pooh", @response.body + end +end + +class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get "/~user" => ok + get "/young-and-fine" => ok + end + end + + include Routes.url_helpers + def app; Routes end + + test 'recognizes tilde path' do + get "/~user" + assert_equal "200", @response.code + end + + test 'recognizes minus path' do + get "/young-and-fine" + assert_equal "200", @response.code + end + +end + +class TestRedirectInterpolation < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get "/foo/:id" => redirect("/foo/bar/%{id}") + get "/bar/:id" => redirect(:path => "/foo/bar/%{id}") + get "/foo/bar/:id" => ok + end + end + + def app; Routes end + + test "redirect escapes interpolated parameters with redirect proc" do + get "/foo/1%3E" + verify_redirect "http://www.example.com/foo/bar/1%3E" + end + + test "redirect escapes interpolated parameters with option proc" do + get "/bar/1%3E" + verify_redirect "http://www.example.com/foo/bar/1%3E" + end + +private + def verify_redirect(url, status=301) + assert_equal status, @response.status + assert_equal url, @response.headers['Location'] + assert_equal expected_redirect_body(url), @response.body + end + + def expected_redirect_body(url) + %(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>) + end +end + +class TestConstraintsAccessingParameters < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get "/:foo" => ok, :constraints => lambda { |r| r.params[:foo] == 'foo' } + get "/:bar" => ok + end + end + + def app; Routes end + + test "parameters are reset between constraint checks" do + get "/bar" + assert_equal nil, @request.params[:foo] + assert_equal "bar", @request.params[:bar] + end +end + +class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + get '/foo' => ok, as: :foo + end + end + + include Routes.url_helpers + def app; Routes end + + test 'enabled when not mounted and default_url_options is empty' do + assert Routes.url_helpers.optimize_routes_generation? + end + + test 'named route called as singleton method' do + assert_equal '/foo', Routes.url_helpers.foo_path + end + + test 'named route called on included module' do + assert_equal '/foo', foo_path + end +end + +class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest + class CategoriesController < ActionController::Base + def show + render :text => "categories#show" + end + end + + class ProductsController < ActionController::Base + def show + render :text => "products#show" + end + end + + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + scope :module => "test_named_route_url_helpers" do + get "/categories/:id" => 'categories#show', :as => :category + get "/products/:id" => 'products#show', :as => :product + end + end + end + + def app; Routes end + + include Routes.url_helpers + + test "url helpers do not ignore nil parameters when using non-optimized routes" do + Routes.stubs(:optimize_routes_generation?).returns(false) + + get "/categories/1" + assert_response :success + assert_raises(ActionController::RoutingError) { product_path(nil) } + end +end + +class TestUrlConstraints < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + constraints :subdomain => 'admin' do + get '/' => ok, :as => :admin_root + end + + scope :constraints => { :protocol => 'https://' } do + get '/' => ok, :as => :secure_root + end + + get '/' => ok, :as => :alternate_root, :constraints => { :port => 8080 } + end + end + + include Routes.url_helpers + def app; Routes end + + test "constraints are copied to defaults when using constraints method" do + assert_equal 'http://admin.example.com/', admin_root_url + + get 'http://admin.example.com/' + assert_response :success + end + + test "constraints are copied to defaults when using scope constraints hash" do + assert_equal 'https://www.example.com/', secure_root_url + + get 'https://www.example.com/' + assert_response :success + end + + test "constraints are copied to defaults when using route constraints hash" do + assert_equal 'http://www.example.com:8080/', alternate_root_url + + get 'http://www.example.com:8080/' + assert_response :success + end +end + +class TestInvalidUrls < ActionDispatch::IntegrationTest + class FooController < ActionController::Base + def show + render :text => "foo#show" + end + end + + test "invalid UTF-8 encoding returns a 400 Bad Request" do + with_routing do |set| + set.draw do + get "/bar/:id", :to => redirect("/foo/show/%{id}") + get "/foo/show(/:id)", :to => "test_invalid_urls/foo#show" + get "/foo(/:action(/:id))", :to => "test_invalid_urls/foo" + get "/:controller(/:action(/:id))" + end + + get "/%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/foo/%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/foo/show/%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/bar/%E2%EF%BF%BD%A6" + assert_response :bad_request + end + end +end
\ No newline at end of file diff --git a/actionpack/test/dispatch/session/abstract_store_test.rb b/actionpack/test/dispatch/session/abstract_store_test.rb new file mode 100644 index 0000000000..8daf3d3f5e --- /dev/null +++ b/actionpack/test/dispatch/session/abstract_store_test.rb @@ -0,0 +1,56 @@ +require 'abstract_unit' +require 'action_dispatch/middleware/session/abstract_store' + +module ActionDispatch + module Session + class AbstractStoreTest < ActiveSupport::TestCase + class MemoryStore < AbstractStore + def initialize(app) + @sessions = {} + super + end + + def get_session(env, sid) + sid ||= 1 + session = @sessions[sid] ||= {} + [sid, session] + end + + def set_session(env, sid, session, options) + @sessions[sid] = session + end + end + + def test_session_is_set + env = {} + as = MemoryStore.new app + as.call(env) + + assert @env + assert Request::Session.find @env + end + + def test_new_session_object_is_merged_with_old + env = {} + as = MemoryStore.new app + as.call(env) + + assert @env + session = Request::Session.find @env + session['foo'] = 'bar' + + as.call(@env) + session1 = Request::Session.find @env + + refute_equal session, session1 + assert_equal session.to_hash, session1.to_hash + end + + private + def app(&block) + @env = nil + lambda { |env| @env = env } + end + end + end +end diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb new file mode 100644 index 0000000000..a74e165826 --- /dev/null +++ b/actionpack/test/dispatch/session/cache_store_test.rb @@ -0,0 +1,179 @@ +require 'abstract_unit' + +class CacheStoreTest < ActionDispatch::IntegrationTest + class TestController < ActionController::Base + def no_session_access + head :ok + end + + def set_session_value + session[:foo] = "bar" + head :ok + end + + def set_serialized_session_value + session[:foo] = SessionAutoloadTest::Foo.new + head :ok + end + + def get_session_value + render :text => "foo: #{session[:foo].inspect}" + end + + def get_session_id + render :text => "#{request.session_options[:id]}" + end + + def call_reset_session + session[:bar] + reset_session + session[:bar] = "baz" + head :ok + end + end + + def test_setting_and_getting_session_value + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + + get '/get_session_value' + assert_response :success + assert_equal 'foo: "bar"', response.body + end + end + + def test_getting_nil_session_value + with_test_route_set do + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body + end + end + + def test_getting_session_value_after_session_reset + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + session_cookie = cookies.send(:hash_for)['_session_id'] + + get '/call_reset_session' + assert_response :success + assert_not_equal [], headers['Set-Cookie'] + + cookies << session_cookie # replace our new session_id with our old, pre-reset session_id + + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body, "data for this session should have been obliterated from cache" + end + end + + def test_getting_from_nonexistent_session + with_test_route_set do + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body + assert_nil cookies['_session_id'], "should only create session on write, not read" + end + end + + def test_setting_session_value_after_session_reset + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + session_id = cookies['_session_id'] + + get '/call_reset_session' + assert_response :success + assert_not_equal [], headers['Set-Cookie'] + + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body + + get '/get_session_id' + assert_response :success + assert_not_equal session_id, response.body + end + end + + def test_getting_session_id + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + session_id = cookies['_session_id'] + + get '/get_session_id' + assert_response :success + assert_equal session_id, response.body, "should be able to read session id without accessing the session hash" + end + end + + def test_deserializes_unloaded_class + with_test_route_set do + with_autoload_path "session_autoload_test" do + get '/set_serialized_session_value' + assert_response :success + assert cookies['_session_id'] + end + with_autoload_path "session_autoload_test" do + get '/get_session_id' + assert_response :success + end + with_autoload_path "session_autoload_test" do + get '/get_session_value' + assert_response :success + assert_equal 'foo: #<SessionAutoloadTest::Foo bar:"baz">', response.body, "should auto-load unloaded class" + end + end + end + + def test_doesnt_write_session_cookie_if_session_id_is_already_exists + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + + get '/get_session_value' + assert_response :success + assert_equal nil, headers['Set-Cookie'], "should not resend the cookie again if session_id cookie is already exists" + end + end + + def test_prevents_session_fixation + with_test_route_set do + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body + session_id = cookies['_session_id'] + + reset! + + get '/set_session_value', :_session_id => session_id + assert_response :success + assert_not_equal session_id, cookies['_session_id'] + end + end + + private + def with_test_route_set + with_routing do |set| + set.draw do + get ':action', :to => ::CacheStoreTest::TestController + end + + @app = self.class.build_app(set) do |middleware| + cache = ActiveSupport::Cache::MemoryStore.new + middleware.use ActionDispatch::Session::CacheStore, :key => '_session_id', :cache => cache + middleware.delete "ActionDispatch::ShowExceptions" + end + + yield + end + end +end diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index b0efbcef4a..631974d6c4 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -5,8 +5,8 @@ class CookieStoreTest < ActionDispatch::IntegrationTest SessionKey = '_myapp_session' SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33' - Verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1') - SignedBar = Verifier.generate(:foo => "bar", :session_id => ActiveSupport::SecureRandom.hex(16)) + Verifier = ActiveSupport::MessageVerifier.new(SessionSecret, :digest => 'SHA1') + SignedBar = Verifier.generate(:foo => "bar", :session_id => SecureRandom.hex(16)) class TestController < ActionController::Base def no_session_access @@ -54,8 +54,6 @@ class CookieStoreTest < ActionDispatch::IntegrationTest request.session_options[:renew] = true head :ok end - - def rescue_action(e) raise end end def test_setting_session_value @@ -319,7 +317,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest def with_test_route_set(options = {}) with_routing do |set| set.draw do - match ':action', :to => ::CookieStoreTest::TestController + get ':action', :to => ::CookieStoreTest::TestController end options = { :key => SessionKey }.merge!(options) diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index 8502bc547b..03234612ab 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -31,8 +31,6 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest session[:bar] = "baz" head :ok end - - def rescue_action(e) raise end end begin @@ -175,7 +173,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match ':action', :to => ::MemCacheStoreTest::TestController + get ':action', :to => ::MemCacheStoreTest::TestController end @app = self.class.build_app(set) do |middleware| diff --git a/actionpack/test/dispatch/session/test_session_test.rb b/actionpack/test/dispatch/session/test_session_test.rb index 31ce97a25b..904398f563 100644 --- a/actionpack/test/dispatch/session/test_session_test.rb +++ b/actionpack/test/dispatch/session/test_session_test.rb @@ -29,7 +29,6 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase end def test_clear_emptys_session - params = {:one => 'one', :two => 'two'} session = ActionController::TestSession.new({:one => 'one', :two => 'two'}) session.clear assert_nil(session[:one]) diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index 42f6c7f79f..45f8fc11b3 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -2,32 +2,33 @@ require 'abstract_unit' class ShowExceptionsTest < ActionDispatch::IntegrationTest - Boomer = lambda do |env| - req = ActionDispatch::Request.new(env) - case req.path - when "/not_found" - raise ActionController::UnknownAction - when "/runtime_error" - raise RuntimeError - when "/method_not_allowed" - raise ActionController::MethodNotAllowed - when "/not_implemented" - raise ActionController::NotImplemented - when "/unprocessable_entity" - raise ActionController::InvalidAuthenticityToken - when "/not_found_original_exception" - raise ActionView::Template::Error.new('template', {}, AbstractController::ActionNotFound.new) - else - raise "puke!" + class Boomer + def call(env) + req = ActionDispatch::Request.new(env) + case req.path + when "/not_found" + raise AbstractController::ActionNotFound + when "/method_not_allowed" + raise ActionController::MethodNotAllowed + when "/not_found_original_exception" + raise ActionView::Template::Error.new('template', AbstractController::ActionNotFound.new) + else + raise "puke!" + end end end - ProductionApp = ActionDispatch::ShowExceptions.new(Boomer, false) - DevelopmentApp = ActionDispatch::ShowExceptions.new(Boomer, true) + ProductionApp = ActionDispatch::ShowExceptions.new(Boomer.new, ActionDispatch::PublicExceptions.new("#{FIXTURE_LOAD_PATH}/public")) - test "rescue in public from a remote ip" do + test "skip exceptions app if not showing exceptions" do + @app = ProductionApp + assert_raise RuntimeError do + get "/", {}, {'action_dispatch.show_exceptions' => false} + end + end + + test "rescue with error page" do @app = ProductionApp - self.remote_addr = '208.77.188.166' get "/", {}, {'action_dispatch.show_exceptions' => true} assert_response 500 @@ -42,32 +43,11 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest assert_equal "", body end - test "rescue locally from a local request" do - @app = ProductionApp - ['127.0.0.1', '127.0.0.127', '::1', '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1%0'].each do |ip_address| - self.remote_addr = ip_address - - get "/", {}, {'action_dispatch.show_exceptions' => true} - assert_response 500 - assert_match(/puke/, body) - - get "/not_found", {}, {'action_dispatch.show_exceptions' => true} - assert_response 404 - assert_match(/#{ActionController::UnknownAction.name}/, body) - - get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true} - assert_response 405 - assert_match(/ActionController::MethodNotAllowed/, body) - end - end - - test "localize public rescue message" do - # Change locale + test "localize rescue error page" do old_locale, I18n.locale = I18n.locale, :da begin @app = ProductionApp - self.remote_addr = '208.77.188.166' get "/", {}, {'action_dispatch.show_exceptions' => true} assert_response 500 @@ -81,67 +61,42 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest end end - test "always rescue locally in development mode" do - @app = DevelopmentApp - self.remote_addr = '208.77.188.166' + test "sets the HTTP charset parameter" do + @app = ProductionApp get "/", {}, {'action_dispatch.show_exceptions' => true} - assert_response 500 - assert_match(/puke/, body) - - get "/not_found", {}, {'action_dispatch.show_exceptions' => true} - assert_response 404 - assert_match(/#{ActionController::UnknownAction.name}/, body) - - get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true} - assert_response 405 - assert_match(/ActionController::MethodNotAllowed/, body) - end - - test "does not show filtered parameters" do - @app = DevelopmentApp - - get "/", {"foo"=>"bar"}, {'action_dispatch.show_exceptions' => true, - 'action_dispatch.parameter_filter' => [:foo]} - assert_response 500 - assert_match(""foo"=>"[FILTERED]"", body) + assert_equal "text/html; charset=utf-8", response.headers["Content-Type"] end - test "show registered original exception for wrapped exceptions when consider_all_requests_local is false" do + test "show registered original exception for wrapped exceptions" do @app = ProductionApp - self.remote_addr = '208.77.188.166' get "/not_found_original_exception", {}, {'action_dispatch.show_exceptions' => true} assert_response 404 assert_match(/404 error/, body) end - test "show registered original exception for wrapped exceptions when consider_all_requests_local is true" do - @app = DevelopmentApp + test "calls custom exceptions app" do + exceptions_app = lambda do |env| + assert_kind_of AbstractController::ActionNotFound, env["action_dispatch.exception"] + assert_equal "/404", env["PATH_INFO"] + [404, { "Content-Type" => "text/plain" }, ["YOU FAILED BRO"]] + end + @app = ActionDispatch::ShowExceptions.new(Boomer.new, exceptions_app) get "/not_found_original_exception", {}, {'action_dispatch.show_exceptions' => true} assert_response 404 - assert_match(/AbstractController::ActionNotFound/, body) - end - - test "show the controller name in the diagnostics template when controller name is present" do - @app = ProductionApp - get("/runtime_error", {}, { - 'action_dispatch.show_exceptions' => true, - 'action_dispatch.request.parameters' => { - 'action' => 'show', - 'id' => 'unknown', - 'controller' => 'featured_tile' - } - }) - assert_response 500 - assert_match(/RuntimeError\n in FeaturedTileController/, body) + assert_equal "YOU FAILED BRO", body end - test "sets the HTTP charset parameter" do - @app = DevelopmentApp + test "returns an empty response if custom exceptions app returns X-Cascade pass" do + exceptions_app = lambda do |env| + [404, { "X-Cascade" => "pass" }, []] + end - get "/", {}, {'action_dispatch.show_exceptions' => true} - assert_equal "text/html; charset=utf-8", response.headers["Content-Type"] + @app = ActionDispatch::ShowExceptions.new(Boomer.new, exceptions_app) + get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true} + assert_response 405 + assert_equal "", body end end diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb new file mode 100644 index 0000000000..6f075a9074 --- /dev/null +++ b/actionpack/test/dispatch/ssl_test.rb @@ -0,0 +1,157 @@ +require 'abstract_unit' + +class SSLTest < ActionDispatch::IntegrationTest + def default_app + lambda { |env| + headers = {'Content-Type' => "text/html"} + headers['Set-Cookie'] = "id=1; path=/\ntoken=abc; path=/; secure; HttpOnly" + [200, headers, ["OK"]] + } + end + + def app + @app ||= ActionDispatch::SSL.new(default_app) + end + attr_writer :app + + def test_allows_https_url + get "https://example.org/path?key=value" + assert_response :success + end + + def test_allows_https_proxy_header_url + get "http://example.org/", {}, 'HTTP_X_FORWARDED_PROTO' => "https" + assert_response :success + end + + def test_redirects_http_to_https + get "http://example.org/path?key=value" + assert_response :redirect + assert_equal "https://example.org/path?key=value", + response.headers['Location'] + end + + def test_hsts_header_by_default + get "https://example.org/" + assert_equal "max-age=31536000", + response.headers['Strict-Transport-Security'] + end + + def test_hsts_header + self.app = ActionDispatch::SSL.new(default_app, :hsts => true) + get "https://example.org/" + assert_equal "max-age=31536000", + response.headers['Strict-Transport-Security'] + end + + def test_disable_hsts_header + self.app = ActionDispatch::SSL.new(default_app, :hsts => false) + get "https://example.org/" + refute response.headers['Strict-Transport-Security'] + end + + def test_hsts_expires + self.app = ActionDispatch::SSL.new(default_app, :hsts => { :expires => 500 }) + get "https://example.org/" + assert_equal "max-age=500", + response.headers['Strict-Transport-Security'] + end + + def test_hsts_include_subdomains + self.app = ActionDispatch::SSL.new(default_app, :hsts => { :subdomains => true }) + get "https://example.org/" + assert_equal "max-age=31536000; includeSubDomains", + response.headers['Strict-Transport-Security'] + end + + def test_flag_cookies_as_secure + get "https://example.org/" + assert_equal ["id=1; path=/; secure", "token=abc; path=/; secure; HttpOnly" ], + response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure_at_end_of_line + self.app = ActionDispatch::SSL.new(lambda { |env| + headers = { + 'Content-Type' => "text/html", + 'Set-Cookie' => "problem=def; path=/; HttpOnly; secure" + } + [200, headers, ["OK"]] + }) + + get "https://example.org/" + assert_equal ["problem=def; path=/; HttpOnly; secure"], + response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure_with_more_spaces_before + self.app = ActionDispatch::SSL.new(lambda { |env| + headers = { + 'Content-Type' => "text/html", + 'Set-Cookie' => "problem=def; path=/; HttpOnly; secure" + } + [200, headers, ["OK"]] + }) + + get "https://example.org/" + assert_equal ["problem=def; path=/; HttpOnly; secure"], + response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure_with_more_spaces_after + self.app = ActionDispatch::SSL.new(lambda { |env| + headers = { + 'Content-Type' => "text/html", + 'Set-Cookie' => "problem=def; path=/; secure; HttpOnly" + } + [200, headers, ["OK"]] + }) + + get "https://example.org/" + assert_equal ["problem=def; path=/; secure; HttpOnly"], + response.headers['Set-Cookie'].split("\n") + end + + def test_no_cookies + self.app = ActionDispatch::SSL.new(lambda { |env| + [200, {'Content-Type' => "text/html"}, ["OK"]] + }) + get "https://example.org/" + assert !response.headers['Set-Cookie'] + end + + def test_redirect_to_host + self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org") + get "http://example.org/path?key=value" + assert_equal "https://ssl.example.org/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_port + self.app = ActionDispatch::SSL.new(default_app, :port => 8443) + get "http://example.org/path?key=value" + assert_equal "https://example.org:8443/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_host_and_port + self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org", :port => 8443) + get "http://example.org/path?key=value" + assert_equal "https://ssl.example.org:8443/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_secure_host_when_on_subdomain + self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org") + get "http://ssl.example.org/path?key=value" + assert_equal "https://ssl.example.org/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_secure_subdomain_when_on_deep_subdomain + self.app = ActionDispatch::SSL.new(default_app, :host => "example.co.uk") + get "http://double.rainbow.what.does.it.mean.example.co.uk/path?key=value" + assert_equal "https://example.co.uk/path?key=value", + response.headers['Location'] + end +end diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index 9f3cbd19ef..112f470786 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -1,10 +1,16 @@ +# encoding: utf-8 require 'abstract_unit' +require 'rbconfig' module StaticTests def test_serves_dynamic_content assert_equal "Hello, World!", get("/nofile").body end + def test_handles_urls_with_bad_encoding + assert_equal "Hello, World!", get("/doorkeeper%E3E4").body + end + def test_sets_cache_control response = get("/index.html") assert_html "/index.html", response @@ -30,6 +36,91 @@ module StaticTests assert_html "/foo/index.html", get("/foo") end + def test_served_static_file_with_non_english_filename + assert_html "means hello in Japanese\n", get("/foo/#{Rack::Utils.escape("こんにちは.html")}") + end + + + def test_serves_static_file_with_exclamation_mark_in_filename + with_static_file "/foo/foo!bar.html" do |file| + assert_html file, get("/foo/foo%21bar.html") + assert_html file, get("/foo/foo!bar.html") + end + end + + def test_serves_static_file_with_dollar_sign_in_filename + with_static_file "/foo/foo$bar.html" do |file| + assert_html file, get("/foo/foo%24bar.html") + assert_html file, get("/foo/foo$bar.html") + end + end + + def test_serves_static_file_with_ampersand_in_filename + with_static_file "/foo/foo&bar.html" do |file| + assert_html file, get("/foo/foo%26bar.html") + assert_html file, get("/foo/foo&bar.html") + end + end + + def test_serves_static_file_with_apostrophe_in_filename + with_static_file "/foo/foo'bar.html" do |file| + assert_html file, get("/foo/foo%27bar.html") + assert_html file, get("/foo/foo'bar.html") + end + end + + def test_serves_static_file_with_parentheses_in_filename + with_static_file "/foo/foo(bar).html" do |file| + assert_html file, get("/foo/foo%28bar%29.html") + assert_html file, get("/foo/foo(bar).html") + end + end + + def test_serves_static_file_with_plus_sign_in_filename + with_static_file "/foo/foo+bar.html" do |file| + assert_html file, get("/foo/foo%2Bbar.html") + assert_html file, get("/foo/foo+bar.html") + end + end + + def test_serves_static_file_with_comma_in_filename + with_static_file "/foo/foo,bar.html" do |file| + assert_html file, get("/foo/foo%2Cbar.html") + assert_html file, get("/foo/foo,bar.html") + end + end + + def test_serves_static_file_with_semi_colon_in_filename + with_static_file "/foo/foo;bar.html" do |file| + assert_html file, get("/foo/foo%3Bbar.html") + assert_html file, get("/foo/foo;bar.html") + end + end + + def test_serves_static_file_with_at_symbol_in_filename + with_static_file "/foo/foo@bar.html" do |file| + assert_html file, get("/foo/foo%40bar.html") + assert_html file, get("/foo/foo@bar.html") + end + end + + # Windows doesn't allow \ / : * ? " < > | in filenames + unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ + def test_serves_static_file_with_colon + with_static_file "/foo/foo:bar.html" do |file| + assert_html file, get("/foo/foo%3Abar.html") + assert_html file, get("/foo/foo:bar.html") + end + end + + def test_serves_static_file_with_asterisk + with_static_file "/foo/foo*bar.html" do |file| + assert_html file, get("/foo/foo%2Abar.html") + assert_html file, get("/foo/foo*bar.html") + end + end + end + private def assert_html(body, response) @@ -40,6 +131,14 @@ module StaticTests def get(path) Rack::MockRequest.new(@app).request("GET", path) end + + def with_static_file(file) + path = "#{FIXTURE_LOAD_PATH}/public" + file + File.open(path, "wb+") { |f| f.write(file) } + yield file + ensure + File.delete(path) + end end class StaticTest < ActiveSupport::TestCase @@ -53,4 +152,4 @@ class StaticTest < ActiveSupport::TestCase end include StaticTests -end
\ No newline at end of file +end diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb index 81a8c24525..4ee1d61146 100644 --- a/actionpack/test/dispatch/test_request_test.rb +++ b/actionpack/test/dispatch/test_request_test.rb @@ -34,12 +34,29 @@ class TestRequestTest < ActiveSupport::TestCase assert_equal({}, req.cookies) assert_equal nil, req.env["HTTP_COOKIE"] - req.cookies["user_name"] = "david" - assert_equal({"user_name" => "david"}, req.cookies) - assert_equal "user_name=david", req.env["HTTP_COOKIE"] + req.cookie_jar["user_name"] = "david" + assert_cookies({"user_name" => "david"}, req.cookie_jar) - req.cookies["login"] = "XJ-122" - assert_equal({"user_name" => "david", "login" => "XJ-122"}, req.cookies) - assert_equal %w(login=XJ-122 user_name=david), req.env["HTTP_COOKIE"].split(/; /).sort + req.cookie_jar["login"] = "XJ-122" + assert_cookies({"user_name" => "david", "login" => "XJ-122"}, req.cookie_jar) + + assert_nothing_raised do + req.cookie_jar["login"] = nil + assert_cookies({"user_name" => "david", "login" => nil}, req.cookie_jar) + end + + req.cookie_jar.delete(:login) + assert_cookies({"user_name" => "david"}, req.cookie_jar) + + req.cookie_jar.clear + assert_cookies({}, req.cookie_jar) + + req.cookie_jar.update(:user_name => "david") + assert_cookies({"user_name" => "david"}, req.cookie_jar) end + + private + def assert_cookies(expected, cookie_jar) + assert_equal(expected, cookie_jar.instance_variable_get("@cookies")) + end end diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index e2a7f1bad7..e69c1fbed4 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -13,6 +13,11 @@ module ActionDispatch assert_equal 'foo', uf.original_filename end + def test_filename_should_be_in_utf_8 + uf = Http::UploadedFile.new(:filename => 'foo', :tempfile => Object.new) + assert_equal "UTF-8", uf.original_filename.encoding.to_s + end + def test_content_type uf = Http::UploadedFile.new(:type => 'foo', :tempfile => Object.new) assert_equal 'foo', uf.content_type @@ -60,6 +65,12 @@ module ActionDispatch end end + def test_delegate_eof_to_tempfile + tf = Class.new { def eof?; true end; } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert uf.eof? + end + def test_respond_to? tf = Class.new { def read; yield end } uf = Http::UploadedFile.new(:tempfile => tf.new) diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index 2b54bc62b0..e56e8ddc57 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module TestUrlGeneration class WithMountPoint < ActionDispatch::IntegrationTest Routes = ActionDispatch::Routing::RouteSet.new - Routes.draw { match "/foo", :to => "my_route_generating#index", :as => :foo } + include Routes.url_helpers class ::MyRouteGeneratingController < ActionController::Base include Routes.url_helpers @@ -12,7 +12,11 @@ module TestUrlGeneration end end - include Routes.url_helpers + Routes.draw do + get "/foo", :to => "my_route_generating#index", :as => :foo + + mount MyRouteGeneratingController.action(:index), at: '/bar' + end def _routes Routes @@ -30,11 +34,16 @@ module TestUrlGeneration assert_equal "/bar/foo", foo_path(:script_name => "/bar") end - test "the request's SCRIPT_NAME takes precedence over the routes'" do + test "the request's SCRIPT_NAME takes precedence over the route" do get "/foo", {}, 'SCRIPT_NAME' => "/new", 'action_dispatch.routes' => Routes assert_equal "/new/foo", response.body end + test "the request's SCRIPT_NAME wraps the mounted app's" do + get '/new/bar/foo', {}, 'SCRIPT_NAME' => '/new', 'PATH_INFO' => '/bar/foo', 'action_dispatch.routes' => Routes + assert_equal "/new/bar/foo", response.body + end + test "handling http protocol with https set" do https! assert_equal "http://www.example.com/foo", foo_url(:protocol => "http") diff --git a/actionpack/test/fixtures/addresses/list.erb b/actionpack/test/fixtures/addresses/list.erb deleted file mode 100644 index c75e01eece..0000000000 --- a/actionpack/test/fixtures/addresses/list.erb +++ /dev/null @@ -1 +0,0 @@ -We only need to get this far! diff --git a/actionpack/test/fixtures/comments/empty.de.html.erb b/actionpack/test/fixtures/comments/empty.de.html.erb new file mode 100644 index 0000000000..cffd90dd26 --- /dev/null +++ b/actionpack/test/fixtures/comments/empty.de.html.erb @@ -0,0 +1 @@ +<h1>Kein Kommentar</h1>
\ No newline at end of file diff --git a/actionpack/test/fixtures/comments/empty.html.builder b/actionpack/test/fixtures/comments/empty.html.builder new file mode 100644 index 0000000000..2b0c7207a3 --- /dev/null +++ b/actionpack/test/fixtures/comments/empty.html.builder @@ -0,0 +1 @@ +xml.h1 'No Comment'
\ No newline at end of file diff --git a/actionpack/test/fixtures/comments/empty.html.erb b/actionpack/test/fixtures/comments/empty.html.erb new file mode 100644 index 0000000000..827f3861de --- /dev/null +++ b/actionpack/test/fixtures/comments/empty.html.erb @@ -0,0 +1 @@ +<h1>No Comment</h1>
\ No newline at end of file diff --git a/actionpack/test/fixtures/comments/empty.xml.erb b/actionpack/test/fixtures/comments/empty.xml.erb new file mode 100644 index 0000000000..db1027cd7d --- /dev/null +++ b/actionpack/test/fixtures/comments/empty.xml.erb @@ -0,0 +1 @@ +<error>No Comment</error>
\ No newline at end of file diff --git a/actionpack/test/fixtures/company.rb b/actionpack/test/fixtures/company.rb index cd39ea7898..e29978801e 100644 --- a/actionpack/test/fixtures/company.rb +++ b/actionpack/test/fixtures/company.rb @@ -1,10 +1,10 @@ class Company < ActiveRecord::Base has_one :mascot attr_protected :rating - set_sequence_name :companies_nonstd_seq + self.sequence_name = :companies_nonstd_seq validates_presence_of :name def validate errors.add('rating', 'rating should not be 2') if rating == 2 end -end
\ No newline at end of file +end diff --git a/actionpack/test/fixtures/developer.rb b/actionpack/test/fixtures/developer.rb index c70eda34c6..dd14548fac 100644 --- a/actionpack/test/fixtures/developer.rb +++ b/actionpack/test/fixtures/developer.rb @@ -5,5 +5,5 @@ class Developer < ActiveRecord::Base end class DeVeLoPeR < ActiveRecord::Base - set_table_name "developers" + self.table_name = "developers" end diff --git a/actionpack/test/fixtures/developers.yml b/actionpack/test/fixtures/developers.yml index 308bf75de2..3656564f63 100644 --- a/actionpack/test/fixtures/developers.yml +++ b/actionpack/test/fixtures/developers.yml @@ -8,7 +8,7 @@ jamis: name: Jamis salary: 150000 -<% for digit in 3..10 %> +<% (3..10).each do |digit| %> dev_<%= digit %>: id: <%= digit %> name: fixture_<%= digit %> diff --git a/actionpack/test/fixtures/fun/games/_game.erb b/actionpack/test/fixtures/fun/games/_game.erb index d51b7b3ebc..f0f542ff92 100644 --- a/actionpack/test/fixtures/fun/games/_game.erb +++ b/actionpack/test/fixtures/fun/games/_game.erb @@ -1 +1 @@ -<%= game.name %>
\ No newline at end of file +Fun <%= game.name %> diff --git a/actionpack/test/fixtures/fun/serious/games/_game.erb b/actionpack/test/fixtures/fun/serious/games/_game.erb index d51b7b3ebc..523bc55bd7 100644 --- a/actionpack/test/fixtures/fun/serious/games/_game.erb +++ b/actionpack/test/fixtures/fun/serious/games/_game.erb @@ -1 +1 @@ -<%= game.name %>
\ No newline at end of file +Serious <%= game.name %> diff --git a/actionpack/test/fixtures/functional_caching/fragment_cached.html.erb b/actionpack/test/fixtures/functional_caching/fragment_cached.html.erb index c479adb897..fa5e6bd318 100644 --- a/actionpack/test/fixtures/functional_caching/fragment_cached.html.erb +++ b/actionpack/test/fixtures/functional_caching/fragment_cached.html.erb @@ -1,2 +1,3 @@ Hello <%= cache do %>This bit's fragment cached<% end %> +<%= 'Ciao' %> diff --git a/actionpack/test/fixtures/games/_game.erb b/actionpack/test/fixtures/games/_game.erb new file mode 100644 index 0000000000..1aeb81fcba --- /dev/null +++ b/actionpack/test/fixtures/games/_game.erb @@ -0,0 +1 @@ +Just <%= game.name %> diff --git a/actionpack/test/fixtures/layouts/with_html_partial.html.erb b/actionpack/test/fixtures/layouts/with_html_partial.html.erb new file mode 100644 index 0000000000..fd2896aeaa --- /dev/null +++ b/actionpack/test/fixtures/layouts/with_html_partial.html.erb @@ -0,0 +1 @@ +<%= render :partial => "partial_only_html" %><%= yield %> diff --git a/actionpack/test/fixtures/plain_text.raw b/actionpack/test/fixtures/plain_text.raw new file mode 100644 index 0000000000..b13985337f --- /dev/null +++ b/actionpack/test/fixtures/plain_text.raw @@ -0,0 +1 @@ +<%= hello_world %> diff --git a/actionpack/test/fixtures/plain_text_with_characters.raw b/actionpack/test/fixtures/plain_text_with_characters.raw new file mode 100644 index 0000000000..1e86e44fb4 --- /dev/null +++ b/actionpack/test/fixtures/plain_text_with_characters.raw @@ -0,0 +1 @@ +Here are some characters: !@#$%^&*()-="'}{` diff --git a/actionpack/test/fixtures/public/foo/こんにちは.html b/actionpack/test/fixtures/public/foo/こんにちは.html new file mode 100644 index 0000000000..1df9166522 --- /dev/null +++ b/actionpack/test/fixtures/public/foo/こんにちは.html @@ -0,0 +1 @@ +means hello in Japanese diff --git a/actionpack/test/fixtures/reply.rb b/actionpack/test/fixtures/reply.rb index 19cba93673..0d3b0a7c98 100644 --- a/actionpack/test/fixtures/reply.rb +++ b/actionpack/test/fixtures/reply.rb @@ -1,5 +1,5 @@ class Reply < ActiveRecord::Base - scope :base + scope :base, -> { scoped } belongs_to :topic, :include => [:replies] belongs_to :developer diff --git a/actionpack/test/fixtures/respond_with/using_resource.js.erb b/actionpack/test/fixtures/respond_with/using_resource.js.erb new file mode 100644 index 0000000000..4417680bce --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_resource.js.erb @@ -0,0 +1 @@ +alert("Hi");
\ No newline at end of file diff --git a/actionpack/test/fixtures/routes/bogus.rb b/actionpack/test/fixtures/routes/bogus.rb new file mode 100644 index 0000000000..41fbf0cd64 --- /dev/null +++ b/actionpack/test/fixtures/routes/bogus.rb @@ -0,0 +1 @@ +wrong :route diff --git a/actionpack/test/fixtures/routes/external.rb b/actionpack/test/fixtures/routes/external.rb new file mode 100644 index 0000000000..d103c39f53 --- /dev/null +++ b/actionpack/test/fixtures/routes/external.rb @@ -0,0 +1 @@ +get '/external' => 'external#index' diff --git a/actionpack/test/fixtures/sprockets/app/images/logo.png b/actionpack/test/fixtures/sprockets/app/images/logo.png Binary files differdeleted file mode 100644 index d5edc04e65..0000000000 --- a/actionpack/test/fixtures/sprockets/app/images/logo.png +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/application.js b/actionpack/test/fixtures/sprockets/app/javascripts/application.js deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/javascripts/application.js +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/dir/xmlhr.js b/actionpack/test/fixtures/sprockets/app/javascripts/dir/xmlhr.js deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/javascripts/dir/xmlhr.js +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/xmlhr.js b/actionpack/test/fixtures/sprockets/app/javascripts/xmlhr.js deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/javascripts/xmlhr.js +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/application.css b/actionpack/test/fixtures/sprockets/app/stylesheets/application.css deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/application.css +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css b/actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/style.css b/actionpack/test/fixtures/sprockets/app/stylesheets/style.css deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/style.css +++ /dev/null diff --git a/actionpack/test/fixtures/test/_200.html.erb b/actionpack/test/fixtures/test/_200.html.erb new file mode 100644 index 0000000000..c9f45675dc --- /dev/null +++ b/actionpack/test/fixtures/test/_200.html.erb @@ -0,0 +1 @@ +<h1>Invalid partial</h1> diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial.html.erb new file mode 100644 index 0000000000..e918ba8f83 --- /dev/null +++ b/actionpack/test/fixtures/test/_b_layout_for_partial.html.erb @@ -0,0 +1 @@ +<b><%= yield %></b>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb new file mode 100644 index 0000000000..bdd53014cd --- /dev/null +++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb @@ -0,0 +1 @@ +<b class="<%= customer.name.downcase %>"><%= yield %></b>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb new file mode 100644 index 0000000000..44d6121297 --- /dev/null +++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb @@ -0,0 +1 @@ +<b data-counter="<%= customer_counter %>"><%= yield %></b>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_content_tag_nested_in_content_tag.erb b/actionpack/test/fixtures/test/_content_tag_nested_in_content_tag.erb new file mode 100644 index 0000000000..2f21a75dd9 --- /dev/null +++ b/actionpack/test/fixtures/test/_content_tag_nested_in_content_tag.erb @@ -0,0 +1,3 @@ +<%= content_tag 'p' do %> + <%= content_tag 'b', 'Hello' %> +<% end %> diff --git a/actionpack/test/fixtures/test/_label_with_block.erb b/actionpack/test/fixtures/test/_label_with_block.erb new file mode 100644 index 0000000000..40117e594e --- /dev/null +++ b/actionpack/test/fixtures/test/_label_with_block.erb @@ -0,0 +1,4 @@ +<%= label 'post', 'message' do %> + Message + <%= text_field 'post', 'message' %> +<% end %> diff --git a/actionpack/test/fixtures/test/_layout_with_partial_and_yield.html.erb b/actionpack/test/fixtures/test/_layout_with_partial_and_yield.html.erb index 5db0822f07..820e7db789 100644 --- a/actionpack/test/fixtures/test/_layout_with_partial_and_yield.html.erb +++ b/actionpack/test/fixtures/test/_layout_with_partial_and_yield.html.erb @@ -1,4 +1,4 @@ Before -<%= render :partial => "test/partial.html.erb" %> +<%= render :partial => "test/partial" %> <%= yield %> After diff --git a/actionpack/test/fixtures/test/_partial_html_erb.html.erb b/actionpack/test/fixtures/test/_partial_html_erb.html.erb new file mode 100644 index 0000000000..4b54875782 --- /dev/null +++ b/actionpack/test/fixtures/test/_partial_html_erb.html.erb @@ -0,0 +1 @@ +<%= "partial.html.erb" %> diff --git a/actionpack/test/fixtures/test/_partial_only_html.html b/actionpack/test/fixtures/test/_partial_only_html.html new file mode 100644 index 0000000000..d2d630bd40 --- /dev/null +++ b/actionpack/test/fixtures/test/_partial_only_html.html @@ -0,0 +1 @@ +only html partial
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/deprecated_nested_layout.erb b/actionpack/test/fixtures/test/deprecated_nested_layout.erb deleted file mode 100644 index 7b6dcbb6c7..0000000000 --- a/actionpack/test/fixtures/test/deprecated_nested_layout.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% content_for :title, "title" -%> -<% content_for :column do -%>column<% end -%> -<% render :layout => 'layouts/column' do -%>content<% end -%>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hello,world.erb b/actionpack/test/fixtures/test/hello,world.erb new file mode 100644 index 0000000000..bc8fa5e0ca --- /dev/null +++ b/actionpack/test/fixtures/test/hello,world.erb @@ -0,0 +1 @@ +Hello w*rld!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hello_world_with_partial.html.erb b/actionpack/test/fixtures/test/hello_world_with_partial.html.erb new file mode 100644 index 0000000000..ec31545356 --- /dev/null +++ b/actionpack/test/fixtures/test/hello_world_with_partial.html.erb @@ -0,0 +1,2 @@ +Hello world! +<%= render '/test/partial' %> diff --git a/actionpack/test/fixtures/test/one.html.erb b/actionpack/test/fixtures/test/one.html.erb new file mode 100644 index 0000000000..0151874809 --- /dev/null +++ b/actionpack/test/fixtures/test/one.html.erb @@ -0,0 +1 @@ +<%= render :partial => "test/two" %> world
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/with_html_partial.html.erb b/actionpack/test/fixtures/test/with_html_partial.html.erb new file mode 100644 index 0000000000..d84d909d64 --- /dev/null +++ b/actionpack/test/fixtures/test/with_html_partial.html.erb @@ -0,0 +1 @@ +<strong><%= render :partial => "partial_only_html" %></strong> diff --git a/actionpack/test/fixtures/test/with_partial.html.erb b/actionpack/test/fixtures/test/with_partial.html.erb new file mode 100644 index 0000000000..7502364cf5 --- /dev/null +++ b/actionpack/test/fixtures/test/with_partial.html.erb @@ -0,0 +1 @@ +<strong><%= render :partial => "partial_only" %></strong> diff --git a/actionpack/test/fixtures/test/with_partial.text.erb b/actionpack/test/fixtures/test/with_partial.text.erb new file mode 100644 index 0000000000..5f068ebf27 --- /dev/null +++ b/actionpack/test/fixtures/test/with_partial.text.erb @@ -0,0 +1 @@ +**<%= render :partial => "partial_only" %>** diff --git a/actionpack/test/fixtures/test/with_xml_template.html.erb b/actionpack/test/fixtures/test/with_xml_template.html.erb new file mode 100644 index 0000000000..e54a7cd001 --- /dev/null +++ b/actionpack/test/fixtures/test/with_xml_template.html.erb @@ -0,0 +1 @@ +<%= render :template => "test/greeting", :formats => :xml %> diff --git a/actionpack/test/fixtures/translations/templates/default.erb b/actionpack/test/fixtures/translations/templates/default.erb new file mode 100644 index 0000000000..8b70031071 --- /dev/null +++ b/actionpack/test/fixtures/translations/templates/default.erb @@ -0,0 +1 @@ +<%= t('.missing', :default => :'.foo') %> diff --git a/actionpack/test/fixtures/with_format.json.erb b/actionpack/test/fixtures/with_format.json.erb new file mode 100644 index 0000000000..a7f480ab1d --- /dev/null +++ b/actionpack/test/fixtures/with_format.json.erb @@ -0,0 +1 @@ +<%= render :partial => 'missing', :formats => [:json] %> diff --git a/actionpack/test/lib/controller/fake_controllers.rb b/actionpack/test/lib/controller/fake_controllers.rb index 09692f77b5..1a2863b689 100644 --- a/actionpack/test/lib/controller/fake_controllers.rb +++ b/actionpack/test/lib/controller/fake_controllers.rb @@ -1,11 +1,7 @@ -class << Object; alias_method :const_available?, :const_defined?; end - class ContentController < ActionController::Base; end module Admin - class << self; alias_method :const_available?, :const_defined?; end class AccountsController < ActionController::Base; end - class NewsFeedController < ActionController::Base; end class PostsController < ActionController::Base; end class StuffController < ActionController::Base; end class UserController < ActionController::Base; end @@ -17,46 +13,23 @@ module Api class ProductsController < ActionController::Base; end end -# TODO: Reduce the number of test controllers we use class AccountController < ActionController::Base; end -class AddressesController < ActionController::Base; end class ArchiveController < ActionController::Base; end class ArticlesController < ActionController::Base; end class BarController < ActionController::Base; end class BlogController < ActionController::Base; end class BooksController < ActionController::Base; end -class BraveController < ActionController::Base; end class CarsController < ActionController::Base; end class CcController < ActionController::Base; end class CController < ActionController::Base; end -class ElsewhereController < ActionController::Base; end class FooController < ActionController::Base; end class GeocodeController < ActionController::Base; end -class HiController < ActionController::Base; end -class ImageController < ActionController::Base; end class NewsController < ActionController::Base; end class NotesController < ActionController::Base; end +class PagesController < ActionController::Base; end class PeopleController < ActionController::Base; end class PostsController < ActionController::Base; end -class SessionsController < ActionController::Base; end -class StuffController < ActionController::Base; end class SubpathBooksController < ActionController::Base; end class SymbolsController < ActionController::Base; end class UserController < ActionController::Base; end -class WeblogController < ActionController::Base; end - -# For speed test -class SpeedController < ActionController::Base; end -class SearchController < SpeedController; end -class VideosController < SpeedController; end -class VideoFileController < SpeedController; end -class VideoSharesController < SpeedController; end -class VideoAbusesController < SpeedController; end -class VideoUploadsController < SpeedController; end -class VideoVisitsController < SpeedController; end -class UsersController < SpeedController; end -class SettingsController < SpeedController; end -class ChannelsController < SpeedController; end -class ChannelVideosController < SpeedController; end -class LostPasswordsController < SpeedController; end -class PagesController < SpeedController; end +class UsersController < ActionController::Base; end diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index 67baf369e2..bbb4cc5ef3 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -34,6 +34,16 @@ end class GoodCustomer < Customer end +class ValidatedCustomer < Customer + def errors + if name =~ /Sikachu/i + [] + else + [{:name => "is invalid"}] + end + end +end + module Quiz class Question < Struct.new(:name, :id) extend ActiveModel::Naming @@ -48,26 +58,19 @@ module Quiz end end -class Post < Struct.new(:title, :author_name, :body, :secret, :written_on, :cost) +class Post < Struct.new(:title, :author_name, :body, :secret, :persisted, :written_on, :cost) extend ActiveModel::Naming include ActiveModel::Conversion extend ActiveModel::Translation alias_method :secret?, :secret + alias_method :persisted?, :persisted def initialize(*args) super @persisted = false end - def persisted=(boolean) - @persisted = boolean - end - - def persisted? - @persisted - end - attr_accessor :author def author_attributes=(attributes); end @@ -170,9 +173,20 @@ class Author < Comment def post_attributes=(attributes); end end +class HashBackedAuthor < Hash + extend ActiveModel::Naming + include ActiveModel::Conversion + + def persisted?; false; end + + def name + "hash backed author" + end +end + module Blog - def self._railtie - self + def self.use_relative_model_naming? + true end class Post < Struct.new(:title, :id) diff --git a/actionpack/test/lib/testing_sandbox.rb b/actionpack/test/lib/testing_sandbox.rb deleted file mode 100644 index c36585104f..0000000000 --- a/actionpack/test/lib/testing_sandbox.rb +++ /dev/null @@ -1,15 +0,0 @@ -module TestingSandbox - # Temporarily replaces KCODE for the block - def with_kcode(kcode) - if RUBY_VERSION < '1.9' - old_kcode, $KCODE = $KCODE, kcode - begin - yield - ensure - $KCODE = old_kcode - end - else - yield - end - end -end diff --git a/actionpack/test/routing/helper_test.rb b/actionpack/test/routing/helper_test.rb new file mode 100644 index 0000000000..a5588d95fa --- /dev/null +++ b/actionpack/test/routing/helper_test.rb @@ -0,0 +1,31 @@ +require 'abstract_unit' + +module ActionDispatch + module Routing + class HelperTest < ActiveSupport::TestCase + class Duck + def to_param + nil + end + end + + def test_exception + rs = ::ActionDispatch::Routing::RouteSet.new + rs.draw do + resources :ducks do + member do + get :pond + end + end + end + + x = Class.new { + include rs.url_helpers + } + assert_raises ActionController::RoutingError do + x.new.pond_duck_path Duck.new + end + end + end + end +end diff --git a/actionpack/test/template/active_model_helper_test.rb b/actionpack/test/template/active_model_helper_test.rb index 8530a72a82..24511df444 100644 --- a/actionpack/test/template/active_model_helper_test.rb +++ b/actionpack/test/template/active_model_helper_test.rb @@ -4,7 +4,7 @@ class ActiveModelHelperTest < ActionView::TestCase tests ActionView::Helpers::ActiveModelHelper silence_warnings do - class Post < Struct.new(:author_name, :body) + class Post < Struct.new(:author_name, :body, :updated_at) include ActiveModel::Conversion include ActiveModel::Validations @@ -20,25 +20,48 @@ class ActiveModelHelperTest < ActionView::TestCase @post = Post.new @post.errors[:author_name] << "can't be empty" @post.errors[:body] << "foo" + @post.errors[:updated_at] << "bar" @post.author_name = "" @post.body = "Back to the hill and over it again!" + @post.updated_at = Date.new(2004, 6, 15) end def test_text_area_with_errors assert_dom_equal( - %(<div class="field_with_errors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div>), + %(<div class="field_with_errors"><textarea id="post_body" name="post[body]">\nBack to the hill and over it again!</textarea></div>), text_area("post", "body") ) end def test_text_field_with_errors assert_dom_equal( - %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>), + %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" type="text" value="" /></div>), text_field("post", "author_name") ) end + def test_date_select_with_errors + assert_dom_equal( + %(<div class="field_with_errors"><select id="post_updated_at_1i" name="post[updated_at(1i)]">\n<option selected="selected" value="2004">2004</option>\n<option value="2005">2005</option>\n</select>\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="1" />\n</div>), + date_select("post", "updated_at", :discard_month => true, :discard_day => true, :start_year => 2004, :end_year => 2005) + ) + end + + def test_datetime_select_with_errors + assert_dom_equal( + %(<div class="field_with_errors"><input id="post_updated_at_1i" name="post[updated_at(1i)]" type="hidden" value="2004" />\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="1" />\n<select id="post_updated_at_4i" name="post[updated_at(4i)]">\n<option selected="selected" value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n</select>\n : <select id="post_updated_at_5i" name="post[updated_at(5i)]">\n<option selected="selected" value="00">00</option>\n</select>\n</div>), + datetime_select("post", "updated_at", :discard_year => true, :discard_month => true, :discard_day => true, :minute_step => 60) + ) + end + + def test_time_select_with_errors + assert_dom_equal( + %(<div class="field_with_errors"><input id="post_updated_at_1i" name="post[updated_at(1i)]" type="hidden" value="2004" />\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="15" />\n<select id="post_updated_at_4i" name="post[updated_at(4i)]">\n<option selected="selected" value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n</select>\n : <select id="post_updated_at_5i" name="post[updated_at(5i)]">\n<option selected="selected" value="00">00</option>\n</select>\n</div>), + time_select("post", "updated_at", :minute_step => 60) + ) + end + def test_hidden_field_does_not_render_errors assert_dom_equal( %(<input id="post_author_name" name="post[author_name]" type="hidden" value="" />), @@ -53,7 +76,7 @@ class ActiveModelHelperTest < ActionView::TestCase end assert_dom_equal( - %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /> <span class="error">can't be empty</span></div>), + %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" type="text" value="" /> <span class="error">can't be empty</span></div>), text_field("post", "author_name") ) ensure diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 2abc806e97..7cc567c72d 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -1,3 +1,4 @@ +require 'zlib' require 'abstract_unit' require 'active_support/ordered_options' @@ -37,6 +38,7 @@ class AssetTagHelperTest < ActionView::TestCase @controller = BasicController.new @request = Class.new do + attr_accessor :script_name def protocol() 'http://' end def ssl?() false end def host_with_port() 'localhost' end @@ -87,21 +89,33 @@ class AssetTagHelperTest < ActionView::TestCase %(path_to_javascript("/super/xmlhr.js")) => %(/super/xmlhr.js) } + JavascriptUrlToTag = { + %(javascript_url("xmlhr")) => %(http://www.example.com/javascripts/xmlhr.js), + %(javascript_url("super/xmlhr")) => %(http://www.example.com/javascripts/super/xmlhr.js), + %(javascript_url("/super/xmlhr.js")) => %(http://www.example.com/super/xmlhr.js) + } + + UrlToJavascriptToTag = { + %(url_to_javascript("xmlhr")) => %(http://www.example.com/javascripts/xmlhr.js), + %(url_to_javascript("super/xmlhr")) => %(http://www.example.com/javascripts/super/xmlhr.js), + %(url_to_javascript("/super/xmlhr.js")) => %(http://www.example.com/super/xmlhr.js) + } + JavascriptIncludeToTag = { - %(javascript_include_tag("bank")) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>), - %(javascript_include_tag("bank.js")) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>), - %(javascript_include_tag("bank", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/bank.js" type="text/javascript"></script>), - %(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" type="text/javascript"></script>\n<script src="/elsewhere/cools.js" type="text/javascript"></script>), - %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:all)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:all, :recursive => true)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/subdir/subdir.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:defaults, "bank")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:defaults, "application")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag("bank", :defaults)) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - - %(javascript_include_tag("http://example.com/all")) => %(<script src="http://example.com/all" type="text/javascript"></script>), - %(javascript_include_tag("http://example.com/all.js")) => %(<script src="http://example.com/all.js" type="text/javascript"></script>), - %(javascript_include_tag("//example.com/all.js")) => %(<script src="//example.com/all.js" type="text/javascript"></script>), + %(javascript_include_tag("bank")) => %(<script src="/javascripts/bank.js" ></script>), + %(javascript_include_tag("bank.js")) => %(<script src="/javascripts/bank.js" ></script>), + %(javascript_include_tag("bank", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/bank.js" ></script>), + %(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" ></script>\n<script src="/elsewhere/cools.js" ></script>), + %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" ></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:all)) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:all, :recursive => true)) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/subdir/subdir.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:defaults, "bank")) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:defaults, "application")) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag("bank", :defaults)) => %(<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), + + %(javascript_include_tag("http://example.com/all")) => %(<script src="http://example.com/all"></script>), + %(javascript_include_tag("http://example.com/all.js")) => %(<script src="http://example.com/all.js"></script>), + %(javascript_include_tag("//example.com/all.js")) => %(<script src="//example.com/all.js"></script>), } StylePathToTag = { @@ -118,20 +132,34 @@ class AssetTagHelperTest < ActionView::TestCase %(path_to_stylesheet('/dir/file.rcss')) => %(/dir/file.rcss) } + StyleUrlToTag = { + %(stylesheet_url("bank")) => %(http://www.example.com/stylesheets/bank.css), + %(stylesheet_url("bank.css")) => %(http://www.example.com/stylesheets/bank.css), + %(stylesheet_url('subdir/subdir')) => %(http://www.example.com/stylesheets/subdir/subdir.css), + %(stylesheet_url('/subdir/subdir.css')) => %(http://www.example.com/subdir/subdir.css) + } + + UrlToStyleToTag = { + %(url_to_stylesheet("style")) => %(http://www.example.com/stylesheets/style.css), + %(url_to_stylesheet("style.css")) => %(http://www.example.com/stylesheets/style.css), + %(url_to_stylesheet('dir/file')) => %(http://www.example.com/stylesheets/dir/file.css), + %(url_to_stylesheet('/dir/file.rcss')) => %(http://www.example.com/dir/file.rcss) + } + StyleLinkToTag = { - %(stylesheet_link_tag("bank")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("bank.css")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("/elsewhere/file")) => %(<link href="/elsewhere/file.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("subdir/subdir")) => %(<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("bank", :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all, :recursive => true)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all, :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="all" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("random.styles", "/elsewhere/file")) => %(<link href="/stylesheets/random.styles" media="screen" rel="stylesheet" type="text/css" />\n<link href="/elsewhere/file.css" media="screen" rel="stylesheet" type="text/css" />), - - %(stylesheet_link_tag("http://www.example.com/styles/style")) => %(<link href="http://www.example.com/styles/style" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("http://www.example.com/styles/style.css")) => %(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("//www.example.com/styles/style.css")) => %(<link href="//www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />), + %(stylesheet_link_tag("bank")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("bank.css")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("/elsewhere/file")) => %(<link href="/elsewhere/file.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("subdir/subdir")) => %(<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("bank", :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" />), + %(stylesheet_link_tag(:all)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag(:all, :recursive => true)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag(:all, :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="all" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="all" rel="stylesheet" />), + %(stylesheet_link_tag("random.styles", "/elsewhere/file")) => %(<link href="/stylesheets/random.styles" media="screen" rel="stylesheet" />\n<link href="/elsewhere/file.css" media="screen" rel="stylesheet" />), + + %(stylesheet_link_tag("http://www.example.com/styles/style")) => %(<link href="http://www.example.com/styles/style" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("http://www.example.com/styles/style.css")) => %(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("//www.example.com/styles/style.css")) => %(<link href="//www.example.com/styles/style.css" media="screen" rel="stylesheet" />), } ImagePathToTag = { @@ -148,6 +176,20 @@ class AssetTagHelperTest < ActionView::TestCase %(path_to_image("/dir/xml.png")) => %(/dir/xml.png) } + ImageUrlToTag = { + %(image_url("xml")) => %(http://www.example.com/images/xml), + %(image_url("xml.png")) => %(http://www.example.com/images/xml.png), + %(image_url("dir/xml.png")) => %(http://www.example.com/images/dir/xml.png), + %(image_url("/dir/xml.png")) => %(http://www.example.com/dir/xml.png) + } + + UrlToImageToTag = { + %(url_to_image("xml")) => %(http://www.example.com/images/xml), + %(url_to_image("xml.png")) => %(http://www.example.com/images/xml.png), + %(url_to_image("dir/xml.png")) => %(http://www.example.com/images/dir/xml.png), + %(url_to_image("/dir/xml.png")) => %(http://www.example.com/dir/xml.png) + } + ImageLinkToTag = { %(image_tag("xml.png")) => %(<img alt="Xml" src="/images/xml.png" />), %(image_tag("rss.gif", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/images/rss.gif" />), @@ -161,13 +203,13 @@ class AssetTagHelperTest < ActionView::TestCase %(image_tag(".pdf.png")) => %(<img alt=".pdf" src="/images/.pdf.png" />), %(image_tag("http://www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="http://www.rubyonrails.com/images/rails.png" />), %(image_tag("//www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="//www.rubyonrails.com/images/rails.png" />), - %(image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) => %(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />), - %(image_tag("mouse.png", :mouseover => image_path("mouse_over.png"))) => %(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />), - %(image_tag("mouse.png", :alt => nil)) => %(<img src="/images/mouse.png" />) + %(image_tag("mouse.png", :alt => nil)) => %(<img src="/images/mouse.png" />), + %(image_tag("data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==", :alt => nil)) => %(<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />), + %(image_tag("")) => %(<img src="" />) } FaviconLinkToTag = { - %(favicon_link_tag) => %(<link href="/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />), + %(favicon_link_tag) => %(<link href="/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />), %(favicon_link_tag 'favicon.ico') => %(<link href="/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />), %(favicon_link_tag 'favicon.ico', :rel => 'foo') => %(<link href="/images/favicon.ico" rel="foo" type="image/vnd.microsoft.icon" />), %(favicon_link_tag 'favicon.ico', :rel => 'foo', :type => 'bar') => %(<link href="/images/favicon.ico" rel="foo" type="bar" />), @@ -188,23 +230,38 @@ class AssetTagHelperTest < ActionView::TestCase %(path_to_video("/dir/xml.ogg")) => %(/dir/xml.ogg) } + VideoUrlToTag = { + %(video_url("xml")) => %(http://www.example.com/videos/xml), + %(video_url("xml.ogg")) => %(http://www.example.com/videos/xml.ogg), + %(video_url("dir/xml.ogg")) => %(http://www.example.com/videos/dir/xml.ogg), + %(video_url("/dir/xml.ogg")) => %(http://www.example.com/dir/xml.ogg) + } + + UrlToVideoToTag = { + %(url_to_video("xml")) => %(http://www.example.com/videos/xml), + %(url_to_video("xml.ogg")) => %(http://www.example.com/videos/xml.ogg), + %(url_to_video("dir/xml.ogg")) => %(http://www.example.com/videos/dir/xml.ogg), + %(url_to_video("/dir/xml.ogg")) => %(http://www.example.com/dir/xml.ogg) + } + VideoLinkToTag = { - %(video_tag("xml.ogg")) => %(<video src="/videos/xml.ogg" />), - %(video_tag("rss.m4v", :autoplay => true, :controls => true)) => %(<video autoplay="autoplay" controls="controls" src="/videos/rss.m4v" />), - %(video_tag("rss.m4v", :autobuffer => true)) => %(<video autobuffer="autobuffer" src="/videos/rss.m4v" />), - %(video_tag("gold.m4v", :size => "160x120")) => %(<video height="120" src="/videos/gold.m4v" width="160" />), - %(video_tag("gold.m4v", "size" => "320x240")) => %(<video height="240" src="/videos/gold.m4v" width="320" />), - %(video_tag("trailer.ogg", :poster => "screenshot.png")) => %(<video poster="/images/screenshot.png" src="/videos/trailer.ogg" />), - %(video_tag("error.avi", "size" => "100")) => %(<video src="/videos/error.avi" />), - %(video_tag("error.avi", "size" => "100 x 100")) => %(<video src="/videos/error.avi" />), - %(video_tag("error.avi", "size" => "x")) => %(<video src="/videos/error.avi" />), - %(video_tag("http://media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="http://media.rubyonrails.org/video/rails_blog_2.mov" />), - %(video_tag("//media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="//media.rubyonrails.org/video/rails_blog_2.mov" />), - %(video_tag(["multiple.ogg", "multiple.avi"])) => %(<video><source src="multiple.ogg" /><source src="multiple.avi" /></video>), - %(video_tag(["multiple.ogg", "multiple.avi"], :size => "160x120", :controls => true)) => %(<video controls="controls" height="120" width="160"><source src="multiple.ogg" /><source src="multiple.avi" /></video>) + %(video_tag("xml.ogg")) => %(<video src="/videos/xml.ogg"></video>), + %(video_tag("rss.m4v", :autoplay => true, :controls => true)) => %(<video autoplay="autoplay" controls="controls" src="/videos/rss.m4v"></video>), + %(video_tag("rss.m4v", :autobuffer => true)) => %(<video autobuffer="autobuffer" src="/videos/rss.m4v"></video>), + %(video_tag("gold.m4v", :size => "160x120")) => %(<video height="120" src="/videos/gold.m4v" width="160"></video>), + %(video_tag("gold.m4v", "size" => "320x240")) => %(<video height="240" src="/videos/gold.m4v" width="320"></video>), + %(video_tag("trailer.ogg", :poster => "screenshot.png")) => %(<video poster="/images/screenshot.png" src="/videos/trailer.ogg"></video>), + %(video_tag("error.avi", "size" => "100")) => %(<video src="/videos/error.avi"></video>), + %(video_tag("error.avi", "size" => "100 x 100")) => %(<video src="/videos/error.avi"></video>), + %(video_tag("error.avi", "size" => "x")) => %(<video src="/videos/error.avi"></video>), + %(video_tag("http://media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="http://media.rubyonrails.org/video/rails_blog_2.mov"></video>), + %(video_tag("//media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="//media.rubyonrails.org/video/rails_blog_2.mov"></video>), + %(video_tag("multiple.ogg", "multiple.avi")) => %(<video><source src="/videos/multiple.ogg" /><source src="/videos/multiple.avi" /></video>), + %(video_tag(["multiple.ogg", "multiple.avi"])) => %(<video><source src="/videos/multiple.ogg" /><source src="/videos/multiple.avi" /></video>), + %(video_tag(["multiple.ogg", "multiple.avi"], :size => "160x120", :controls => true)) => %(<video controls="controls" height="120" width="160"><source src="/videos/multiple.ogg" /><source src="/videos/multiple.avi" /></video>) } - AudioPathToTag = { + AudioPathToTag = { %(audio_path("xml")) => %(/audios/xml), %(audio_path("xml.wav")) => %(/audios/xml.wav), %(audio_path("dir/xml.wav")) => %(/audios/dir/xml.wav), @@ -218,11 +275,28 @@ class AssetTagHelperTest < ActionView::TestCase %(path_to_audio("/dir/xml.wav")) => %(/dir/xml.wav) } + AudioUrlToTag = { + %(audio_url("xml")) => %(http://www.example.com/audios/xml), + %(audio_url("xml.wav")) => %(http://www.example.com/audios/xml.wav), + %(audio_url("dir/xml.wav")) => %(http://www.example.com/audios/dir/xml.wav), + %(audio_url("/dir/xml.wav")) => %(http://www.example.com/dir/xml.wav) + } + + UrlToAudioToTag = { + %(url_to_audio("xml")) => %(http://www.example.com/audios/xml), + %(url_to_audio("xml.wav")) => %(http://www.example.com/audios/xml.wav), + %(url_to_audio("dir/xml.wav")) => %(http://www.example.com/audios/dir/xml.wav), + %(url_to_audio("/dir/xml.wav")) => %(http://www.example.com/dir/xml.wav) + } + AudioLinkToTag = { - %(audio_tag("xml.wav")) => %(<audio src="/audios/xml.wav" />), - %(audio_tag("rss.wav", :autoplay => true, :controls => true)) => %(<audio autoplay="autoplay" controls="controls" src="/audios/rss.wav" />), - %(audio_tag("http://media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="http://media.rubyonrails.org/audio/rails_blog_2.mov" />), - %(audio_tag("//media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="//media.rubyonrails.org/audio/rails_blog_2.mov" />), + %(audio_tag("xml.wav")) => %(<audio src="/audios/xml.wav"></audio>), + %(audio_tag("rss.wav", :autoplay => true, :controls => true)) => %(<audio autoplay="autoplay" controls="controls" src="/audios/rss.wav"></audio>), + %(audio_tag("http://media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="http://media.rubyonrails.org/audio/rails_blog_2.mov"></audio>), + %(audio_tag("//media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="//media.rubyonrails.org/audio/rails_blog_2.mov"></audio>), + %(audio_tag("audio.mp3", "audio.ogg")) => %(<audio><source src="/audios/audio.mp3" /><source src="/audios/audio.ogg" /></audio>), + %(audio_tag(["audio.mp3", "audio.ogg"])) => %(<audio><source src="/audios/audio.mp3" /><source src="/audios/audio.ogg" /></audio>), + %(audio_tag(["audio.mp3", "audio.ogg"], :autobuffer => true, :controls => true)) => %(<audio autobuffer="autobuffer" controls="controls"><source src="/audios/audio.mp3" /><source src="/audios/audio.ogg" /></audio>) } def test_auto_discovery_link_tag @@ -237,6 +311,14 @@ class AssetTagHelperTest < ActionView::TestCase PathToJavascriptToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_javascript_url + JavascriptUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_url_to_javascript_alias_for_javascript_url + UrlToJavascriptToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + def test_javascript_include_tag_with_blank_asset_id ENV["RAILS_ASSET_ID"] = "" JavascriptIncludeToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } @@ -258,7 +340,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_javascript_include_tag_with_given_asset_id ENV["RAILS_ASSET_ID"] = "1" - assert_dom_equal(%(<script src="/javascripts/prototype.js?1" type="text/javascript"></script>\n<script src="/javascripts/effects.js?1" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js?1" type="text/javascript"></script>\n<script src="/javascripts/controls.js?1" type="text/javascript"></script>\n<script src="/javascripts/rails.js?1" type="text/javascript"></script>\n<script src="/javascripts/application.js?1" type="text/javascript"></script>), javascript_include_tag(:defaults)) + assert_dom_equal(%(<script src="/javascripts/prototype.js?1"></script>\n<script src="/javascripts/effects.js?1"></script>\n<script src="/javascripts/dragdrop.js?1"></script>\n<script src="/javascripts/controls.js?1"></script>\n<script src="/javascripts/rails.js?1"></script>\n<script src="/javascripts/application.js?1"></script>), javascript_include_tag(:defaults)) end def test_javascript_include_tag_is_html_safe @@ -269,35 +351,35 @@ class AssetTagHelperTest < ActionView::TestCase def test_custom_javascript_expansions ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"] - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>), javascript_include_tag('controls', :robbery, 'effects') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/effects.js"></script>), javascript_include_tag('controls', :robbery, 'effects') end def test_custom_javascript_expansions_return_unique_set ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :defaults => %w(prototype effects dragdrop controls rails application) - assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag(:defaults) + assert_dom_equal %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:defaults) end def test_custom_javascript_expansions_and_defaults_puts_application_js_at_the_end ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"] - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls',:defaults, :robbery, 'effects') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('controls',:defaults, :robbery, 'effects') end def test_javascript_include_tag_should_not_output_the_same_asset_twice ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('prototype', 'effects', :defaults) + assert_dom_equal %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('prototype', 'effects', :defaults) end def test_javascript_include_tag_should_not_output_the_same_expansion_twice ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag(:defaults, :defaults) + assert_dom_equal %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:defaults, :defaults) end def test_single_javascript_asset_keys_should_take_precedence_over_expansions ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls', :defaults, 'effects') - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls', 'effects', :defaults) + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('controls', :defaults, 'effects') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('controls', 'effects', :defaults) end def test_registering_javascript_expansions_merges_with_existing_expansions @@ -305,7 +387,7 @@ class AssetTagHelperTest < ActionView::TestCase ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['bank'] ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['robber'] ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['bank'] - assert_dom_equal %(<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>), javascript_include_tag(:can_merge) + assert_dom_equal %(<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>), javascript_include_tag(:can_merge) end def test_custom_javascript_expansions_with_undefined_symbol @@ -314,20 +396,20 @@ class AssetTagHelperTest < ActionView::TestCase def test_custom_javascript_expansions_with_nil_value ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => nil - assert_dom_equal %(<script src="/javascripts/first.js" type="text/javascript"></script>\n<script src="/javascripts/last.js" type="text/javascript"></script>), javascript_include_tag('first', :monkey, 'last') + assert_dom_equal %(<script src="/javascripts/first.js"></script>\n<script src="/javascripts/last.js"></script>), javascript_include_tag('first', :monkey, 'last') end def test_custom_javascript_expansions_with_empty_array_value ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => [] - assert_dom_equal %(<script src="/javascripts/first.js" type="text/javascript"></script>\n<script src="/javascripts/last.js" type="text/javascript"></script>), javascript_include_tag('first', :monkey, 'last') + assert_dom_equal %(<script src="/javascripts/first.js"></script>\n<script src="/javascripts/last.js"></script>), javascript_include_tag('first', :monkey, 'last') end def test_custom_javascript_and_stylesheet_expansion_with_same_name ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"] ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :robbery => ["money", "security"] - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>), javascript_include_tag('controls', :robbery, 'effects') - assert_dom_equal %(<link href="/stylesheets/style.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/money.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/security.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/print.css" rel="stylesheet" type="text/css" media="screen" />), stylesheet_link_tag('style', :robbery, 'print') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/effects.js"></script>), javascript_include_tag('controls', :robbery, 'effects') + assert_dom_equal %(<link href="/stylesheets/style.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/money.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/security.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/print.css" rel="stylesheet" media="screen" />), stylesheet_link_tag('style', :robbery, 'print') end def test_reset_javascript_expansions @@ -344,6 +426,15 @@ class AssetTagHelperTest < ActionView::TestCase PathToStyleToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_stylesheet_url + ENV["RAILS_ASSET_ID"] = "" + StyleUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_url_to_stylesheet_alias_for_stylesheet_url + UrlToStyleToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + def test_stylesheet_link_tag ENV["RAILS_ASSET_ID"] = "" StyleLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } @@ -365,33 +456,37 @@ class AssetTagHelperTest < ActionView::TestCase assert stylesheet_link_tag('dir/other/file', 'dir/file2').html_safe? end + def test_stylesheet_link_tag_escapes_options + assert_dom_equal %(<link href="/file.css" media="<script>" rel="stylesheet" />), stylesheet_link_tag('/file', :media => '<script>') + end + def test_custom_stylesheet_expansions ENV["RAILS_ASSET_ID"] = '' ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :robbery => ["bank", "robber"] - assert_dom_equal %(<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('version.1.0', :robbery, 'subdir/subdir') + assert_dom_equal %(<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('version.1.0', :robbery, 'subdir/subdir') end def test_custom_stylesheet_expansions_return_unique_set ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :cities => %w(wellington amsterdam london) - assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:cities) + assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:cities) end def test_stylesheet_link_tag_should_not_output_the_same_asset_twice ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('wellington', 'wellington', 'amsterdam') + assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('wellington', 'wellington', 'amsterdam') end def test_stylesheet_link_tag_should_not_output_the_same_expansion_twice ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :cities => %w(wellington amsterdam london) - assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:cities, :cities) + assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:cities, :cities) end def test_single_stylesheet_asset_keys_should_take_precedence_over_expansions ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :cities => %w(wellington amsterdam london) - assert_dom_equal %(<link href="/stylesheets/london.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('london', :cities) + assert_dom_equal %(<link href="/stylesheets/london.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('london', :cities) end def test_custom_stylesheet_expansions_with_unknown_symbol @@ -400,12 +495,12 @@ class AssetTagHelperTest < ActionView::TestCase def test_custom_stylesheet_expansions_with_nil_value ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :monkey => nil - assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" type="text/css" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') + assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') end def test_custom_stylesheet_expansions_with_empty_array_value ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :monkey => [] - assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" type="text/css" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') + assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') end def test_registering_stylesheet_expansions_merges_with_existing_expansions @@ -413,7 +508,7 @@ class AssetTagHelperTest < ActionView::TestCase ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['bank'] ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['robber'] ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['bank'] - assert_dom_equal %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:can_merge) + assert_dom_equal %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:can_merge) end def test_image_path @@ -424,17 +519,39 @@ class AssetTagHelperTest < ActionView::TestCase PathToImageToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_image_url + ImageUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_url_to_image_alias_for_image_url + UrlToImageToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_image_alt + [nil, '/', '/foo/bar/', 'foo/bar/'].each do |prefix| + assert_equal 'Rails', image_alt("#{prefix}rails.png") + assert_equal 'Rails', image_alt("#{prefix}rails-9c0a079bdd7701d7e729bd956823d153.png") + assert_equal 'Avatar-0000', image_alt("#{prefix}avatar-0000.png") + end + end + def test_image_tag ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_image_tag_does_not_modify_options + options = {:size => '16x10'} + image_tag('icon', options) + assert_equal({:size => '16x10'}, options) + end + def test_favicon_link_tag FaviconLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end def test_image_tag_windows_behaviour old_asset_id, ENV["RAILS_ASSET_ID"] = ENV["RAILS_ASSET_ID"], "1" - # This simulates the behaviour of File#exist? on windows when testing a file ending in "." + # This simulates the behavior of File#exist? on windows when testing a file ending in "." # If the file "rails.png" exists, windows will return true when asked if "rails.png." exists (notice trailing ".") # OS X, linux etc will return false in this case. File.stubs(:exist?).with('template/../fixtures/public/images/rails.png.').returns(true) @@ -455,6 +572,14 @@ class AssetTagHelperTest < ActionView::TestCase PathToVideoToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_video_url + VideoUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_url_to_video_alias_for_video_url + UrlToVideoToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + def test_video_tag VideoLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end @@ -467,12 +592,28 @@ class AssetTagHelperTest < ActionView::TestCase PathToAudioToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_audio_url + AudioUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_url_to_audio_alias_for_audio_url + UrlToAudioToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + def test_audio_tag AudioLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_video_audio_tag_does_not_modify_options + options = {:autoplay => true} + video_tag('video', options) + assert_equal({:autoplay => true}, options) + audio_tag('audio', options) + assert_equal({:autoplay => true}, options) + end + def test_timebased_asset_id - expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s + expected_time = File.mtime(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).to_i.to_s assert_equal %(<img alt="Rails" src="/images/rails.png?#{expected_time}" />), image_tag("rails.png") end @@ -503,10 +644,17 @@ class AssetTagHelperTest < ActionView::TestCase def test_timebased_asset_id_with_relative_url_root @controller.config.relative_url_root = "/collaboration/hieraki" - expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s + expected_time = File.mtime(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).to_i.to_s assert_equal %(<img alt="Rails" src="#{@controller.config.relative_url_root}/images/rails.png?#{expected_time}" />), image_tag("rails.png") end + # Same as above, but with script_name + def test_timebased_asset_id_with_script_name + @request.script_name = "/collaboration/hieraki" + expected_time = File.mtime(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).to_i.to_s + assert_equal %(<img alt="Rails" src="#{@request.script_name}/images/rails.png?#{expected_time}" />), image_tag("rails.png") + end + def test_should_skip_asset_id_on_complete_url assert_equal %(<img alt="Rails" src="http://www.example.com/rails.png" />), image_tag("http://www.example.com/rails.png") end @@ -542,7 +690,6 @@ class AssetTagHelperTest < ActionView::TestCase end end - @controller.request.stubs(:ssl?).returns(false) assert_equal "http://assets15.example.com/images/xml.png", image_path("xml.png") @@ -556,21 +703,21 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/all.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/all.js"></script>), javascript_include_tag(:all, :cache => true) ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/money.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/money.js"></script>), javascript_include_tag(:all, :cache => "money") ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) assert_dom_equal( - %(<script src="http://a0.example.com/absolute/test.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/absolute/test.js"></script>), javascript_include_tag(:all, :cache => "/absolute/test") ) @@ -589,7 +736,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/scripts.js'.length, 23 assert_dom_equal( - %(<script src="http://a23.example.com/javascripts/scripts.js" type="text/javascript"></script>), + %(<script src="http://a23.example.com/javascripts/scripts.js"></script>), javascript_include_tag(:all, :cache => 'scripts') ) @@ -612,7 +759,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/vanilla.js'.length, 23 assert_dom_equal( - %(<script src="http://assets23.example.com/javascripts/vanilla.js" type="text/javascript"></script>), + %(<script src="http://assets23.example.com/javascripts/vanilla.js"></script>), javascript_include_tag(:all, :cache => 'vanilla') ) @@ -625,7 +772,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/secure.js'.length, 22 assert_dom_equal( - %(<script src="https://localhost/javascripts/secure.js" type="text/javascript"></script>), + %(<script src="https://localhost/javascripts/secure.js"></script>), javascript_include_tag(:all, :cache => 'secure') ) @@ -652,7 +799,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/vanilla.js'.length, 23 assert_dom_equal( - %(<script src="http://assets23.example.com/javascripts/vanilla.js" type="text/javascript"></script>), + %(<script src="http://assets23.example.com/javascripts/vanilla.js"></script>), javascript_include_tag(:all, :cache => 'vanilla') ) @@ -665,7 +812,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/secure.js'.length, 22 assert_dom_equal( - %(<script src="https://localhost/javascripts/secure.js" type="text/javascript"></script>), + %(<script src="https://localhost/javascripts/secure.js"></script>), javascript_include_tag(:all, :cache => 'secure') ) @@ -681,9 +828,9 @@ class AssetTagHelperTest < ActionView::TestCase @controller.config.asset_host = 'http://a%d.example.com' config.perform_caching = true - hash = '/javascripts/cache/money.js'.hash % 4 + number = Zlib.crc32('/javascripts/cache/money.js') % 4 assert_dom_equal( - %(<script src="http://a#{hash}.example.com/javascripts/cache/money.js" type="text/javascript"></script>), + %(<script src="http://a#{number}.example.com/javascripts/cache/money.js"></script>), javascript_include_tag(:all, :cache => "cache/money") ) @@ -698,7 +845,7 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/combined.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/combined.js"></script>), javascript_include_tag(:all, :cache => "combined", :recursive => true) ) @@ -719,7 +866,7 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/combined.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/combined.js"></script>), javascript_include_tag(:all, :cache => "combined") ) @@ -740,14 +887,39 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/all.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/all.js"></script>), javascript_include_tag(:all, :cache => true) ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/money.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/money.js"></script>), + javascript_include_tag(:all, :cache => "money") + ) + + assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + + ensure + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + end + + # Same as above, but with script_name + def test_caching_javascript_include_tag_with_script_name + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = true + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/all.js"></script>), + javascript_include_tag(:all, :cache => true) + ) + + assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/money.js"></script>), javascript_include_tag(:all, :cache => "money") ) @@ -764,14 +936,35 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/robber.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), + javascript_include_tag('robber', :cache => true) + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), + javascript_include_tag('robber', :cache => "money", :recursive => true) + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + end + + # Same as above, but with script_name + def test_caching_javascript_include_tag_with_named_paths_and_script_name_when_caching_off + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = false + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), javascript_include_tag('robber', :cache => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/robber.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), javascript_include_tag('robber', :cache => "money", :recursive => true) ) @@ -783,24 +976,24 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => true) ) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/subdir/subdir.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/subdir/subdir.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => true, :recursive => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => "money") ) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/subdir/subdir.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/subdir/subdir.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => "money", :recursive => true) ) @@ -854,11 +1047,11 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_on ENV["RAILS_ASSET_ID"] = "" - @controller.config.asset_host = 'http://a0.example.com' + @controller.config.asset_host = 'a0.example.com' config.perform_caching = true assert_dom_equal( - %(<link href="http://a0.example.com/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a0.example.com/stylesheets/all.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true) ) @@ -872,14 +1065,14 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal expected_size, File.size(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="http://a0.example.com/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a0.example.com/stylesheets/money.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money") ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) assert_dom_equal( - %(<link href="http://a0.example.com/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a0.example.com/absolute/test.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "/absolute/test") ) @@ -894,7 +1087,7 @@ class AssetTagHelperTest < ActionView::TestCase ENV["RAILS_ASSET_ID"] = "" assert_dom_equal( - %(<link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/all.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :concat => true) ) @@ -902,14 +1095,14 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal expected, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/money.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :concat => "money") ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) assert_dom_equal( - %(<link href="/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/absolute/test.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :concat => "/absolute/test") ) @@ -964,12 +1157,12 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host ENV["RAILS_ASSET_ID"] = "" - @controller.config.asset_host = Proc.new { |source| "http://a#{source.length}.example.com" } + @controller.config.asset_host = Proc.new { |source| "a#{source.length}.example.com" } config.perform_caching = true assert_equal '/stylesheets/styles.css'.length, 23 assert_dom_equal( - %(<link href="http://a23.example.com/stylesheets/styles.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a23.example.com/stylesheets/styles.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => 'styles') ) @@ -985,7 +1178,34 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag(:all, :cache => true) + ) + + files_to_be_joined = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/[^all]*.css"] + + expected_mtime = files_to_be_joined.map { |p| File.mtime(p) }.max + assert_equal expected_mtime, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/money.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag(:all, :cache => "money") + ) + + assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + ensure + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + end + + # Same as above, but with script_name + def test_caching_stylesheet_link_tag_with_script_name + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = true + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true) ) @@ -995,7 +1215,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal expected_mtime, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/money.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money") ) @@ -1012,14 +1232,35 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag('robber', :cache => true) + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag('robber', :cache => "money") + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + end + + # Same as above, but with script_name + def test_caching_stylesheet_link_tag_with_named_paths_and_script_name_when_caching_off + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = false + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('robber', :cache => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('robber', :cache => "money") ) @@ -1034,24 +1275,24 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true) ) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true, :recursive => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money") ) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money", :recursive => true) ) @@ -1082,8 +1323,6 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase assert_dom_equal(%(/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) assert_dom_equal(%(/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) assert_dom_equal(%(/collaboration/hieraki/images/xml.png), image_path("xml.png")) - assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='/collaboration/hieraki/images/mouse.png'" src="/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) - assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='/collaboration/hieraki/images/mouse2.png'" src="/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) end def test_should_ignore_relative_root_path_on_complete_url @@ -1091,38 +1330,63 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase end def test_should_compute_proper_path_with_asset_host - @controller.config.asset_host = "http://assets.example.com" + @controller.config.asset_host = "assets.example.com" + assert_dom_equal(%(<link href="http://www.example.com/collaboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), auto_discovery_link_tag) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) + end + + def test_should_compute_proper_path_with_asset_host_and_default_protocol + @controller.config.asset_host = "assets.example.com" + @controller.config.default_asset_host_protocol = :request + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) + end + + def test_should_compute_proper_url_with_asset_host + @controller.config.asset_host = "assets.example.com" assert_dom_equal(%(<link href="http://www.example.com/collaboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), auto_discovery_link_tag) - assert_dom_equal(%(http://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) - assert_dom_equal(%(http://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) - assert_dom_equal(%(http://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) - assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='http://assets.example.com/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='http://assets.example.com/collaboration/hieraki/images/mouse.png'" src="http://assets.example.com/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) - assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='http://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='http://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="http://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_url("xmlhr")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_url("style")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_url("xml.png")) + end + + def test_should_compute_proper_url_with_asset_host_and_default_protocol + @controller.config.asset_host = "assets.example.com" + @controller.config.default_asset_host_protocol = :request + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_url("xmlhr")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_url("style")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_url("xml.png")) end def test_should_ignore_asset_host_on_complete_url @controller.config.asset_host = "http://assets.example.com" - assert_dom_equal(%(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("http://bar.example.com/stylesheets/style.css")) + assert_dom_equal(%(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" />), stylesheet_link_tag("http://bar.example.com/stylesheets/style.css")) end def test_should_ignore_asset_host_on_scheme_relative_url @controller.config.asset_host = "http://assets.example.com" - assert_dom_equal(%(<link href="//bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("//bar.example.com/stylesheets/style.css")) + assert_dom_equal(%(<link href="//bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" />), stylesheet_link_tag("//bar.example.com/stylesheets/style.css")) end def test_should_wildcard_asset_host_between_zero_and_four @controller.config.asset_host = 'http://a%d.example.com' assert_match(%r(http://a[0123].example.com/collaboration/hieraki/images/xml.png), image_path('xml.png')) + assert_match(%r(http://a[0123].example.com/collaboration/hieraki/images/xml.png), image_url('xml.png')) end - def test_asset_host_without_protocol_should_use_request_protocol + def test_asset_host_without_protocol_should_be_protocol_relative @controller.config.asset_host = 'a.example.com' assert_equal 'gopher://a.example.com/collaboration/hieraki/images/xml.png', image_path('xml.png') + assert_equal 'gopher://a.example.com/collaboration/hieraki/images/xml.png', image_url('xml.png') end - def test_asset_host_without_protocol_should_use_request_protocol_even_if_path_present + def test_asset_host_without_protocol_should_be_protocol_relative_even_if_path_present @controller.config.asset_host = 'a.example.com/files/go/here' assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_path('xml.png') + assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_url('xml.png') end def test_assert_css_and_js_of_the_same_name_return_correct_extension diff --git a/actionpack/test/template/atom_feed_helper_test.rb b/actionpack/test/template/atom_feed_helper_test.rb index 81d7444cf8..89aae4ac56 100644 --- a/actionpack/test/template/atom_feed_helper_test.rb +++ b/actionpack/test/template/atom_feed_helper_test.rb @@ -16,7 +16,7 @@ class ScrollsController < ActionController::Base feed.title("My great blog!") feed.updated((@scrolls.first.created_at)) - @scrolls.each do |scroll| + @scrolls.each do |scroll| feed.entry(scroll) do |entry| entry.title(scroll.title) entry.content(scroll.body, :type => 'html') @@ -45,6 +45,23 @@ class ScrollsController < ActionController::Base end end EOT + FEEDS["entry_type_options"] = <<-EOT + atom_feed(:schema_date => '2008') do |feed| + feed.title("My great blog!") + feed.updated((@scrolls.first.created_at)) + + @scrolls.each do |scroll| + feed.entry(scroll, :type => 'text/xml') do |entry| + entry.title(scroll.title) + entry.content(scroll.body, :type => 'html') + + entry.author do |author| + author.name("DHH") + end + end + end + end + EOT FEEDS["xml_block"] = <<-EOT atom_feed do |feed| feed.title("My great blog!") @@ -185,11 +202,6 @@ class ScrollsController < ActionController::Base render :inline => FEEDS[params[:id]], :type => :builder end - - protected - def rescue_action(e) - raise(e) - end end class AtomFeedTest < ActionController::TestCase @@ -311,6 +323,20 @@ class AtomFeedTest < ActionController::TestCase end end + def test_feed_entry_type_option_default_to_text_html + with_restful_routing(:scrolls) do + get :index, :id => 'defaults' + assert_select "entry link[rel=alternate][type=text/html]" + end + end + + def test_feed_entry_type_option_specified + with_restful_routing(:scrolls) do + get :index, :id => 'entry_type_options' + assert_select "entry link[rel=alternate][type=text/xml]" + end + end + private def with_restful_routing(resources) with_routing do |set| diff --git a/actionpack/test/template/benchmark_helper_test.rb b/actionpack/test/template/benchmark_helper_test.rb new file mode 100644 index 0000000000..8c198d2562 --- /dev/null +++ b/actionpack/test/template/benchmark_helper_test.rb @@ -0,0 +1,24 @@ +require 'abstract_unit' +require 'stringio' + +class BenchmarkHelperTest < ActionView::TestCase + include RenderERBUtils + tests ActionView::Helpers::BenchmarkHelper + + def test_output_in_erb + output = render_erb("Hello <%= benchmark do %>world<% end %>") + expected = 'Hello world' + assert_equal expected, output + end + + def test_returns_value_from_block + assert_equal 'test', benchmark { 'test' } + end + + def test_default_message + log = StringIO.new + self.stubs(:logger).returns(Logger.new(log)) + benchmark {} + assert_match(/Benchmarking \(\d+.\d+ms\)/, log.rewind && log.read) + end +end diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index a9157e711c..17469f8c3e 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -46,6 +46,97 @@ class CaptureHelperTest < ActionView::TestCase assert_equal "bar", content_for(:bar) end + def test_content_for_with_multiple_calls + assert ! content_for?(:title) + content_for :title, 'foo' + content_for :title, 'bar' + assert_equal 'foobar', content_for(:title) + end + + def test_content_for_with_multiple_calls_and_flush + assert ! content_for?(:title) + content_for :title, 'foo' + content_for :title, 'bar', true + assert_equal 'bar', content_for(:title) + end + + def test_content_for_with_block + assert ! content_for?(:title) + content_for :title do + output_buffer << 'foo' + output_buffer << 'bar' + nil + end + assert_equal 'foobar', content_for(:title) + end + + def test_content_for_with_block_and_multiple_calls_with_flush + assert ! content_for?(:title) + content_for :title do + 'foo' + end + content_for :title, true do + 'bar' + end + assert_equal 'bar', content_for(:title) + end + + def test_content_for_with_block_and_multiple_calls_with_flush_nil_content + assert ! content_for?(:title) + content_for :title do + 'foo' + end + content_for :title, nil, true do + 'bar' + end + assert_equal 'bar', content_for(:title) + end + + def test_content_for_with_block_and_multiple_calls_without_flush + assert ! content_for?(:title) + content_for :title do + 'foo' + end + content_for :title, false do + 'bar' + end + assert_equal 'foobar', content_for(:title) + end + + def test_content_for_with_whitespace_block + assert ! content_for?(:title) + content_for :title, 'foo' + content_for :title do + output_buffer << " \n " + nil + end + content_for :title, 'bar' + assert_equal 'foobar', content_for(:title) + end + + def test_content_for_with_whitespace_block_and_flush + assert ! content_for?(:title) + content_for :title, 'foo' + content_for :title, true do + output_buffer << " \n " + nil + end + content_for :title, 'bar', true + assert_equal 'bar', content_for(:title) + end + + def test_content_for_returns_nil_when_writing + assert ! content_for?(:title) + assert_equal nil, content_for(:title, 'foo') + assert_equal nil, content_for(:title) { output_buffer << 'bar'; nil } + assert_equal nil, content_for(:title) { output_buffer << " \n "; nil } + assert_equal 'foobar', content_for(:title) + assert_equal nil, content_for(:title, 'foo', true) + assert_equal nil, content_for(:title, true) { output_buffer << 'bar'; nil } + assert_equal nil, content_for(:title, true) { output_buffer << " \n "; nil } + assert_equal 'bar', content_for(:title) + end + def test_content_for_question_mark assert ! content_for?(:title) content_for :title, 'title' @@ -95,17 +186,15 @@ class CaptureHelperTest < ActionView::TestCase assert buffer.equal?(@av.output_buffer) end - unless RUBY_VERSION < '1.9' - def test_with_output_buffer_sets_proper_encoding - @av.output_buffer = ActionView::OutputBuffer.new + def test_with_output_buffer_sets_proper_encoding + @av.output_buffer = ActionView::OutputBuffer.new - # Ensure we set the output buffer to an encoding different than the default one. - alt_encoding = alt_encoding(@av.output_buffer) - @av.output_buffer.force_encoding(alt_encoding) + # Ensure we set the output buffer to an encoding different than the default one. + alt_encoding = alt_encoding(@av.output_buffer) + @av.output_buffer.force_encoding(alt_encoding) - @av.with_output_buffer do - assert_equal alt_encoding, @av.output_buffer.encoding - end + @av.with_output_buffer do + assert_equal alt_encoding, @av.output_buffer.encoding end end @@ -129,14 +218,12 @@ class CaptureHelperTest < ActionView::TestCase assert_equal '', view.output_buffer end - unless RUBY_VERSION < '1.9' - def test_flush_output_buffer_preserves_the_encoding_of_the_output_buffer - view = view_with_controller - alt_encoding = alt_encoding(view.output_buffer) - view.output_buffer.force_encoding(alt_encoding) - flush_output_buffer - assert_equal alt_encoding, view.output_buffer.encoding - end + def test_flush_output_buffer_preserves_the_encoding_of_the_output_buffer + view = view_with_controller + alt_encoding = alt_encoding(view.output_buffer) + view.output_buffer.force_encoding(alt_encoding) + flush_output_buffer + assert_equal alt_encoding, view.output_buffer.encoding end def alt_encoding(output_buffer) diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb index 3f31edd5ce..f5dc2fbb33 100644 --- a/actionpack/test/template/compiled_templates_test.rb +++ b/actionpack/test/template/compiled_templates_test.rb @@ -1,8 +1,12 @@ require 'abstract_unit' require 'controller/fake_models' -class CompiledTemplatesTest < Test::Unit::TestCase +class CompiledTemplatesTest < ActiveSupport::TestCase def setup + # Clean up any details key cached to expose failures + # that otherwise would appear just on isolated tests + ActionView::LookupContext::DetailsKey.clear + @compiled_templates = ActionView::CompiledTemplates @compiled_templates.instance_methods.each do |m| @compiled_templates.send(:remove_method, m) if m =~ /^_render_template_/ @@ -10,24 +14,24 @@ class CompiledTemplatesTest < Test::Unit::TestCase end def test_template_gets_recompiled_when_using_different_keys_in_local_assigns - assert_equal "one", render(:file => "test/render_file_with_locals_and_default.erb") - assert_equal "two", render(:file => "test/render_file_with_locals_and_default.erb", :locals => { :secret => "two" }) + assert_equal "one", render(:file => "test/render_file_with_locals_and_default") + assert_equal "two", render(:file => "test/render_file_with_locals_and_default", :locals => { :secret => "two" }) end def test_template_changes_are_not_reflected_with_cached_templates - assert_equal "Hello world!", render(:file => "test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world") modify_template "test/hello_world.erb", "Goodbye world!" do - assert_equal "Hello world!", render(:file => "test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world") end - assert_equal "Hello world!", render(:file => "test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world") end def test_template_changes_are_reflected_with_uncached_templates - assert_equal "Hello world!", render_without_cache(:file => "test/hello_world.erb") + assert_equal "Hello world!", render_without_cache(:file => "test/hello_world") modify_template "test/hello_world.erb", "Goodbye world!" do - assert_equal "Goodbye world!", render_without_cache(:file => "test/hello_world.erb") + assert_equal "Goodbye world!", render_without_cache(:file => "test/hello_world") end - assert_equal "Hello world!", render_without_cache(:file => "test/hello_world.erb") + assert_equal "Hello world!", render_without_cache(:file => "test/hello_world") end private @@ -42,7 +46,7 @@ class CompiledTemplatesTest < Test::Unit::TestCase def render_without_cache(*args) path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) - view_paths = ActionView::Base.process_view_paths(path) + view_paths = ActionView::PathSet.new([path]) ActionView::Base.new(view_paths, {}).render(*args) end diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb index d45215acfd..63066d40cd 100644 --- a/actionpack/test/template/date_helper_i18n_test.rb +++ b/actionpack/test/template/date_helper_i18n_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase +class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase include ActionView::Helpers::DateHelper attr_reader :request @@ -12,24 +12,24 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase def test_distance_of_time_in_words_calls_i18n { # with include_seconds - [2.seconds, true] => [:'less_than_x_seconds', 5], - [9.seconds, true] => [:'less_than_x_seconds', 10], - [19.seconds, true] => [:'less_than_x_seconds', 20], - [30.seconds, true] => [:'half_a_minute', nil], - [59.seconds, true] => [:'less_than_x_minutes', 1], - [60.seconds, true] => [:'x_minutes', 1], + [2.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 5], + [9.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 10], + [19.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 20], + [30.seconds, { :include_seconds => true }] => [:'half_a_minute', nil], + [59.seconds, { :include_seconds => true }] => [:'less_than_x_minutes', 1], + [60.seconds, { :include_seconds => true }] => [:'x_minutes', 1], # without include_seconds - [29.seconds, false] => [:'less_than_x_minutes', 1], - [60.seconds, false] => [:'x_minutes', 1], - [44.minutes, false] => [:'x_minutes', 44], - [61.minutes, false] => [:'about_x_hours', 1], - [24.hours, false] => [:'x_days', 1], - [30.days, false] => [:'about_x_months', 1], - [60.days, false] => [:'x_months', 2], - [1.year, false] => [:'about_x_years', 1], - [3.years + 6.months, false] => [:'over_x_years', 3], - [3.years + 10.months, false] => [:'almost_x_years', 4] + [29.seconds, { :include_seconds => false }] => [:'less_than_x_minutes', 1], + [60.seconds, { :include_seconds => false }] => [:'x_minutes', 1], + [44.minutes, { :include_seconds => false }] => [:'x_minutes', 44], + [61.minutes, { :include_seconds => false }] => [:'about_x_hours', 1], + [24.hours, { :include_seconds => false }] => [:'x_days', 1], + [30.days, { :include_seconds => false }] => [:'about_x_months', 1], + [60.days, { :include_seconds => false }] => [:'x_months', 2], + [1.year, { :include_seconds => false }] => [:'about_x_years', 1], + [3.years + 6.months, { :include_seconds => false }] => [:'over_x_years', 3], + [3.years + 10.months, { :include_seconds => false }] => [:'almost_x_years', 4] }.each do |passed, expected| assert_distance_of_time_in_words_translates_key passed, expected @@ -37,7 +37,7 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase end def assert_distance_of_time_in_words_translates_key(passed, expected) - diff, include_seconds = *passed + diff, passed_options = *passed key, count = *expected to = @from + diff @@ -45,7 +45,12 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase options[:count] = count if count I18n.expects(:t).with(key, options) - distance_of_time_in_words(@from, to, include_seconds, :locale => 'en') + distance_of_time_in_words(@from, to, passed_options.merge(:locale => 'en')) + end + + def test_time_ago_in_words_passes_locale + I18n.expects(:t).with(:less_than_x_minutes, :scope => :'datetime.distance_in_words', :count => 1, :locale => 'ru') + time_ago_in_words(15.seconds.ago, :locale => 'ru') end def test_distance_of_time_pluralizations @@ -71,7 +76,7 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase end end -class DateHelperSelectTagsI18nTests < Test::Unit::TestCase +class DateHelperSelectTagsI18nTests < ActiveSupport::TestCase include ActionView::Helpers::DateHelper attr_reader :request @@ -103,7 +108,7 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase I18n.expects(:translate).with(('datetime.prompts.' + key.to_s).to_sym, :locale => 'en').returns prompt end - I18n.expects(:translate).with(:'date.order', :locale => 'en').returns [:year, :month, :day] + I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:year, :month, :day] datetime_select('post', 'updated_at', :locale => 'en', :include_seconds => true, :prompt => true) end @@ -115,7 +120,15 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase end def test_date_or_time_select_given_no_order_options_translates_order - I18n.expects(:translate).with(:'date.order', :locale => 'en').returns [:year, :month, :day] + I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:year, :month, :day] datetime_select('post', 'updated_at', :locale => 'en') end + + def test_date_or_time_select_given_invalid_order + I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:invalid, :month, :day] + + assert_raise StandardError do + datetime_select('post', 'updated_at', :locale => 'en') + end + end end diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index 09c53a36f0..ff85a675a2 100644 --- a/actionpack/test/template/date_helper_test.rb +++ b/actionpack/test/template/date_helper_test.rb @@ -21,56 +21,80 @@ class DateHelperTest < ActionView::TestCase def assert_distance_of_time_in_words(from, to=nil) to ||= from - # 0..1 with include_seconds - assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 0.seconds, true) - assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 4.seconds, true) - assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 5.seconds, true) - assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 9.seconds, true) - assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 10.seconds, true) - assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 19.seconds, true) - assert_equal "half a minute", distance_of_time_in_words(from, to + 20.seconds, true) - assert_equal "half a minute", distance_of_time_in_words(from, to + 39.seconds, true) - assert_equal "less than a minute", distance_of_time_in_words(from, to + 40.seconds, true) - assert_equal "less than a minute", distance_of_time_in_words(from, to + 59.seconds, true) - assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, true) - assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, true) - - # First case 0..1 + # 0..1 minute with :include_seconds => true + assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 0.seconds, :include_seconds => true) + assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 4.seconds, :include_seconds => true) + assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 5.seconds, :include_seconds => true) + assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 9.seconds, :include_seconds => true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 10.seconds, :include_seconds => true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 19.seconds, :include_seconds => true) + assert_equal "half a minute", distance_of_time_in_words(from, to + 20.seconds, :include_seconds => true) + assert_equal "half a minute", distance_of_time_in_words(from, to + 39.seconds, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 40.seconds, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 59.seconds, :include_seconds => true) + assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, :include_seconds => true) + assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, :include_seconds => true) + + # 0..1 minute with :include_seconds => false + assert_equal "less than a minute", distance_of_time_in_words(from, to + 0.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 4.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 5.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 9.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 10.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 19.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 20.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 39.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 40.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 59.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, :include_seconds => false) + + # Note that we are including a 30-second boundary around the interval we + # want to test. For instance, "1 minute" is actually 30s to 1m29s. The + # reason for doing this is simple -- in `distance_of_time_to_words`, when we + # take the distance between our two Time objects in seconds and convert it + # to minutes, we round the number. So 29s gets rounded down to 0m, 30s gets + # rounded up to 1m, and 1m29s gets rounded down to 1m. A similar thing + # happens with the other cases. + + # First case 0..1 minute assert_equal "less than a minute", distance_of_time_in_words(from, to + 0.seconds) assert_equal "less than a minute", distance_of_time_in_words(from, to + 29.seconds) assert_equal "1 minute", distance_of_time_in_words(from, to + 30.seconds) assert_equal "1 minute", distance_of_time_in_words(from, to + 1.minutes + 29.seconds) - # 2..44 + # 2 minutes up to 45 minutes assert_equal "2 minutes", distance_of_time_in_words(from, to + 1.minutes + 30.seconds) assert_equal "44 minutes", distance_of_time_in_words(from, to + 44.minutes + 29.seconds) - # 45..89 + # 45 minutes up to 90 minutes assert_equal "about 1 hour", distance_of_time_in_words(from, to + 44.minutes + 30.seconds) assert_equal "about 1 hour", distance_of_time_in_words(from, to + 89.minutes + 29.seconds) - # 90..1439 + # 90 minutes up to 24 hours assert_equal "about 2 hours", distance_of_time_in_words(from, to + 89.minutes + 30.seconds) assert_equal "about 24 hours", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 29.seconds) - # 1440..2519 + # 24 hours up to 42 hours assert_equal "1 day", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 30.seconds) assert_equal "1 day", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 29.seconds) - # 2520..43199 + # 42 hours up to 30 days assert_equal "2 days", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 30.seconds) assert_equal "3 days", distance_of_time_in_words(from, to + 2.days + 12.hours) assert_equal "30 days", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 29.seconds) - # 43200..86399 + # 30 days up to 60 days assert_equal "about 1 month", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 30.seconds) - assert_equal "about 1 month", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 29.seconds) + assert_equal "about 1 month", distance_of_time_in_words(from, to + 44.days + 23.hours + 59.minutes + 29.seconds) + assert_equal "about 2 months", distance_of_time_in_words(from, to + 44.days + 23.hours + 59.minutes + 30.seconds) + assert_equal "about 2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 29.seconds) - # 86400..525599 + # 60 days up to 365 days assert_equal "2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 30.seconds) assert_equal "12 months", distance_of_time_in_words(from, to + 1.years - 31.seconds) - # > 525599 + # >= 365 days assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years - 30.seconds) assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years + 3.months - 1.day) assert_equal "over 1 year", distance_of_time_in_words(from, to + 1.years + 6.months) @@ -95,7 +119,8 @@ class DateHelperTest < ActionView::TestCase # test to < from assert_equal "about 4 hours", distance_of_time_in_words(from + 4.hours, to) - assert_equal "less than 20 seconds", distance_of_time_in_words(from + 19.seconds, to, true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from + 19.seconds, to, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(from + 19.seconds, to, :include_seconds => false) end def test_distance_in_words @@ -103,6 +128,11 @@ class DateHelperTest < ActionView::TestCase assert_distance_of_time_in_words(from) end + def test_time_ago_in_words_passes_include_seconds + assert_equal "less than 20 seconds", time_ago_in_words(15.seconds.ago, :include_seconds => true) + assert_equal "less than a minute", time_ago_in_words(15.seconds.ago, :include_seconds => false) + end + def test_distance_in_words_with_time_zones from = Time.mktime(2004, 6, 6, 21, 45, 0) assert_distance_of_time_in_words(from.in_time_zone('Alaska')) @@ -125,13 +155,33 @@ class DateHelperTest < ActionView::TestCase start_date = Date.new 1982, 12, 3 end_date = Date.new 2010, 11, 30 assert_equal("almost 28 years", distance_of_time_in_words(start_date, end_date)) + assert_equal("almost 28 years", distance_of_time_in_words(end_date, start_date)) end def test_distance_in_words_with_integers - assert_equal "less than a minute", distance_of_time_in_words(59) + assert_equal "1 minute", distance_of_time_in_words(59) assert_equal "about 1 hour", distance_of_time_in_words(60*60) - assert_equal "less than a minute", distance_of_time_in_words(0, 59) + assert_equal "1 minute", distance_of_time_in_words(0, 59) assert_equal "about 1 hour", distance_of_time_in_words(60*60, 0) + assert_equal "about 3 years", distance_of_time_in_words(10**8) + assert_equal "about 3 years", distance_of_time_in_words(0, 10**8) + end + + def test_distance_in_words_with_times + assert_equal "1 minute", distance_of_time_in_words(30.seconds) + assert_equal "1 minute", distance_of_time_in_words(59.seconds) + assert_equal "2 minutes", distance_of_time_in_words(119.seconds) + assert_equal "2 minutes", distance_of_time_in_words(1.minute + 59.seconds) + assert_equal "3 minutes", distance_of_time_in_words(2.minute + 30.seconds) + assert_equal "44 minutes", distance_of_time_in_words(44.minutes + 29.seconds) + assert_equal "about 1 hour", distance_of_time_in_words(44.minutes + 30.seconds) + assert_equal "about 1 hour", distance_of_time_in_words(60.minutes) + + # include seconds + assert_equal "half a minute", distance_of_time_in_words(39.seconds, 0, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(40.seconds, 0, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(59.seconds, 0, :include_seconds => true) + assert_equal "1 minute", distance_of_time_in_words(60.seconds, 0, :include_seconds => true) end def test_time_ago_in_words @@ -164,6 +214,15 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_day(nil, :include_blank => true) end + def test_select_day_with_two_digit_numbers + expected = %(<select id="date_day" name="date[day]">\n) + expected << %(<option value="1">01</option>\n<option selected="selected" value="2">02</option>\n<option value="3">03</option>\n<option value="4">04</option>\n<option value="5">05</option>\n<option value="6">06</option>\n<option value="7">07</option>\n<option value="8">08</option>\n<option value="9">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_dom_equal expected, select_day(Time.mktime(2011, 8, 2), :use_two_digit_numbers => true) + assert_dom_equal expected, select_day(2, :use_two_digit_numbers => true) + end + def test_select_day_with_html_options expected = %(<select id="date_day" name="date[day]" class="selector">\n) expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) @@ -198,6 +257,15 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_month(8) end + def test_select_month_with_two_digit_numbers + expected = %(<select id="date_month" name="date[month]">\n) + expected << %(<option value="1">01</option>\n<option value="2">02</option>\n<option value="3">03</option>\n<option value="4">04</option>\n<option value="5">05</option>\n<option value="6">06</option>\n<option value="7">07</option>\n<option value="8" selected="selected">08</option>\n<option value="9">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n) + expected << "</select>\n" + + assert_dom_equal expected, select_month(Time.mktime(2011, 8, 16), :use_two_digit_numbers => true) + assert_dom_equal expected, select_month(8, :use_two_digit_numbers => true) + end + def test_select_month_with_disabled expected = %(<select id="date_month" name="date[month]" disabled="disabled">\n) expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) @@ -549,7 +617,7 @@ class DateHelperTest < ActionView::TestCase end def test_select_minute_with_html_options - expected = expected = %(<select id="date_minute" name="date[minute]" class="selector" accesskey="M">\n) + expected = %(<select id="date_minute" name="date[minute]" class="selector" accesskey="M">\n) expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) expected << "</select>\n" @@ -664,6 +732,15 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005, :prefix => "date[first]") end + def test_select_date_with_too_big_range_between_start_year_and_end_year + assert_raise(ArgumentError) { select_date(Time.mktime(2003, 8, 16), :start_year => 2000, :end_year => 20000, :prefix => "date[first]", :order => [:month, :day, :year]) } + assert_raise(ArgumentError) { select_date(Time.mktime(2003, 8, 16), :start_year => Date.today.year - 100.years, :end_year => 2000, :prefix => "date[first]", :order => [:month, :day, :year]) } + end + + def test_select_date_can_have_more_then_1000_years_interval_if_forced_via_parameter + assert_nothing_raised { select_date(Time.mktime(2003, 8, 16), :start_year => 2000, :end_year => 3100, :max_years_allowed => 2000) } + end + def test_select_date_with_order expected = %(<select id="date_first_month" name="date[first][month]">\n) expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) @@ -684,7 +761,7 @@ class DateHelperTest < ActionView::TestCase # Since the order is incomplete nothing will be shown expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n) expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) - expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="1" />\n) assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :order => [:day]) end @@ -916,11 +993,20 @@ class DateHelperTest < ActionView::TestCase expected << "</select>\n" expected << %(<input type="hidden" id="date_first_month" name="date[first][month]" value="8" />\n) - expected << %(<input type="hidden" id="date_first_day" name="date[first][day]" value="16" />\n) + expected << %(<input type="hidden" id="date_first_day" name="date[first][day]" value="1" />\n) assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :discard_month => true, :discard_day => true, :start_year => 2003, :end_year => 2005, :prefix => "date[first]"}) end + def test_select_date_with_hidden + expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003"/>\n) + expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + + assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :prefix => "date[first]", :use_hidden => true }) + assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :prefix => "date[first]", :use_hidden => true }) + end + def test_select_datetime expected = %(<select id="date_first_year" name="date[first][year]">\n) expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) @@ -977,7 +1063,6 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :ampm => true) end - def test_select_datetime_with_separators expected = %(<select id="date_first_year" name="date[first][year]">\n) expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) @@ -1158,6 +1243,18 @@ class DateHelperTest < ActionView::TestCase :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year', :hour => 'Choose hour', :minute => 'Choose minute'}) end + def test_select_datetime_with_hidden + expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n) + expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + expected << %(<input id="date_first_hour" name="date[first][hour]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_minute" name="date[first][minute]" type="hidden" value="4" />\n) + + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :prefix => "date[first]", :use_hidden => true) + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :datetime_separator => "—", :date_separator => "/", + :time_separator => ":", :prefix => "date[first]", :use_hidden => true) + end + def test_select_time expected = %(<input name="date[year]" id="date_year" value="2003" type="hidden" />\n) expected << %(<input name="date[month]" id="date_month" value="8" type="hidden" />\n) @@ -1333,6 +1430,17 @@ class DateHelperTest < ActionView::TestCase :prompt => {:hour => 'Choose hour', :minute => 'Choose minute', :second => 'Choose seconds'}) end + def test_select_time_with_hidden + expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n) + expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + expected << %(<input id="date_first_hour" name="date[first][hour]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_minute" name="date[first][minute]" type="hidden" value="4" />\n) + + assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :prefix => "date[first]", :use_hidden => true) + assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :time_separator => ":", :prefix => "date[first]", :use_hidden => true) + end + def test_date_select @post = Post.new @post.written_on = Date.new(2004, 6, 15) @@ -1370,6 +1478,39 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, date_select("post", "written_on", :order => [ :month, :year ]) end + def test_date_select_without_day_and_month + @post = Post.new + @post.written_on = Date.new(2004, 2, 29) + + expected = "<input type=\"hidden\" id=\"post_written_on_2i\" name=\"post[written_on(2i)]\" value=\"2\" />\n" + expected << "<input type=\"hidden\" id=\"post_written_on_3i\" name=\"post[written_on(3i)]\" value=\"1\" />\n" + + expected << %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n} + expected << %{<option value="1999">1999</option>\n<option value="2000">2000</option>\n<option value="2001">2001</option>\n<option value="2002">2002</option>\n<option value="2003">2003</option>\n<option value="2004" selected="selected">2004</option>\n<option value="2005">2005</option>\n<option value="2006">2006</option>\n<option value="2007">2007</option>\n<option value="2008">2008</option>\n<option value="2009">2009</option>\n} + expected << "</select>\n" + + assert_dom_equal expected, date_select("post", "written_on", :order => [ :year ]) + end + + def test_date_select_without_day_with_separator + @post = Post.new + @post.written_on = Date.new(2004, 6, 15) + + expected = "<input type=\"hidden\" id=\"post_written_on_3i\" name=\"post[written_on(3i)]\" value=\"1\" />\n" + + expected << %{<select id="post_written_on_2i" name="post[written_on(2i)]">\n} + expected << %{<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6" selected="selected">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n} + expected << "</select>\n" + + expected << "/" + + expected << %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n} + expected << %{<option value="1999">1999</option>\n<option value="2000">2000</option>\n<option value="2001">2001</option>\n<option value="2002">2002</option>\n<option value="2003">2003</option>\n<option value="2004" selected="selected">2004</option>\n<option value="2005">2005</option>\n<option value="2006">2006</option>\n<option value="2007">2007</option>\n<option value="2008">2008</option>\n<option value="2009">2009</option>\n} + expected << "</select>\n" + + assert_dom_equal expected, date_select("post", "written_on", :date_separator => '/', :order => [ :month, :year ]) + end + def test_date_select_without_day_and_with_disabled_html_option @post = Post.new @post.written_on = Date.new(2004, 6, 15) @@ -1542,7 +1683,7 @@ class DateHelperTest < ActionView::TestCase start_year = Time.now.year-5 end_year = Time.now.year+5 - expected = '<input name="post[written_on(3i)]" type="hidden" id="post_written_on_3i"/>' + "\n" + expected = '<input name="post[written_on(3i)]" type="hidden" id="post_written_on_3i" value="1"/>' + "\n" expected << %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n} expected << "<option value=\"\"></option>\n" start_year.upto(end_year) { |i| expected << %(<option value="#{i}">#{i}</option>\n) } @@ -1556,6 +1697,40 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, date_select("post", "written_on", :order=>[:year, :month], :include_blank=>true) end + def test_date_select_with_nil_and_blank_and_discard_month + @post = Post.new + + start_year = Time.now.year-5 + end_year = Time.now.year+5 + + expected = %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n} + expected << "<option value=\"\"></option>\n" + start_year.upto(end_year) { |i| expected << %(<option value="#{i}">#{i}</option>\n) } + expected << "</select>\n" + expected << '<input name="post[written_on(2i)]" type="hidden" id="post_written_on_2i" value="1"/>' + "\n" + expected << '<input name="post[written_on(3i)]" type="hidden" id="post_written_on_3i" value="1"/>' + "\n" + + assert_dom_equal expected, date_select("post", "written_on", :discard_month => true, :include_blank=>true) + end + + def test_date_select_with_nil_and_blank_and_discard_year + @post = Post.new + + expected = '<input id="post_written_on_1i" name="post[written_on(1i)]" type="hidden" value="1" />' + "\n" + + expected << %{<select id="post_written_on_2i" name="post[written_on(2i)]">\n} + expected << "<option value=\"\"></option>\n" + 1.upto(12) { |i| expected << %(<option value="#{i}">#{Date::MONTHNAMES[i]}</option>\n) } + expected << "</select>\n" + + expected << %{<select id="post_written_on_3i" name="post[written_on(3i)]">\n} + expected << "<option value=\"\"></option>\n" + 1.upto(31) { |i| expected << %(<option value="#{i}">#{i}</option>\n) } + expected << "</select>\n" + + assert_dom_equal expected, date_select("post", "written_on", :discard_year => true, :include_blank=>true) + end + def test_date_select_cant_override_discard_hour @post = Post.new @post.written_on = Date.new(2004, 6, 15) @@ -2039,6 +2214,18 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, datetime_select("post", "updated_at", { :date_separator => " / ", :datetime_separator => " , ", :time_separator => " - ", :include_seconds => true }) end + def test_datetime_select_with_integer + @post = Post.new + @post.updated_at = 3 + datetime_select("post", "updated_at") + end + + def test_datetime_select_with_infinity # Float + @post = Post.new + @post.updated_at = (-1.0/0) + datetime_select("post", "updated_at") + end + def test_datetime_select_with_default_prompt @post = Post.new @post.updated_at = nil @@ -2348,7 +2535,7 @@ class DateHelperTest < ActionView::TestCase 1999.upto(2009) { |i| expected << %(<option value="#{i}"#{' selected="selected"' if i == 2004}>#{i}</option>\n) } expected << "</select>\n" expected << %{<input type="hidden" id="post_updated_at_2i" name="post[updated_at(2i)]" value="6" />\n} - expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="15" />\n} + expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="1" />\n} expected << " — " @@ -2369,7 +2556,7 @@ class DateHelperTest < ActionView::TestCase expected = %{<input type="hidden" id="post_updated_at_1i" name="post[updated_at(1i)]" value="2004" />\n} expected << %{<input type="hidden" id="post_updated_at_2i" name="post[updated_at(2i)]" value="6" />\n} - expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="15" />\n} + expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="1" />\n} expected << %{<select id="post_updated_at_4i" name="post[updated_at(4i)]">\n} 0.upto(23) { |i| expected << %(<option value="#{sprintf("%02d", i)}"#{' selected="selected"' if i == 15}>#{sprintf("%02d", i)}</option>\n) } @@ -2388,7 +2575,7 @@ class DateHelperTest < ActionView::TestCase expected = %{<input type="hidden" id="post_updated_at_1i" disabled="disabled" name="post[updated_at(1i)]" value="2004" />\n} expected << %{<input type="hidden" id="post_updated_at_2i" disabled="disabled" name="post[updated_at(2i)]" value="6" />\n} - expected << %{<input type="hidden" id="post_updated_at_3i" disabled="disabled" name="post[updated_at(3i)]" value="15" />\n} + expected << %{<input type="hidden" id="post_updated_at_3i" disabled="disabled" name="post[updated_at(3i)]" value="1" />\n} expected << %{<select id="post_updated_at_4i" disabled="disabled" name="post[updated_at(4i)]">\n} 0.upto(23) { |i| expected << %(<option value="#{sprintf("%02d", i)}"#{' selected="selected"' if i == 15}>#{sprintf("%02d", i)}</option>\n) } @@ -2786,6 +2973,10 @@ class DateHelperTest < ActionView::TestCase assert_match(/<time.*>Right now<\/time>/, time_tag(Time.now, 'Right now')) end + def test_time_tag_with_given_block + assert_match(/<time.*><span>Right now<\/span><\/time>/, time_tag(Time.now){ '<span>Right now</span>'.html_safe }) + end + def test_time_tag_with_different_format time = Time.now expected = "<time datetime=\"#{time.xmlschema}\">#{I18n.l(time, :format => :short)}</time>" diff --git a/actionpack/test/template/erb/tag_helper_test.rb b/actionpack/test/template/erb/tag_helper_test.rb index a384e94766..1724d6432d 100644 --- a/actionpack/test/template/erb/tag_helper_test.rb +++ b/actionpack/test/template/erb/tag_helper_test.rb @@ -11,12 +11,12 @@ module ERBTest end test "percent equals works for javascript_tag" do - expected_output = "<script type=\"text/javascript\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" + expected_output = "<script>\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" assert_equal expected_output, render_content("javascript_tag", "alert('Hello')") end test "percent equals works for javascript_tag with options" do - expected_output = "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" + expected_output = "<script id=\"the_js_tag\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" assert_equal expected_output, render_content("javascript_tag(:id => 'the_js_tag')", "alert('Hello')") end @@ -30,4 +30,4 @@ module ERBTest assert_equal expected_output, render_content("field_set_tag('foo')", "<%= 'hello' %>") end end -end
\ No newline at end of file +end diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb index 30f6d1a213..ca2710e9b3 100644 --- a/actionpack/test/template/erb_util_test.rb +++ b/actionpack/test/template/erb_util_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/inclusion' -class ErbUtilTest < Test::Unit::TestCase +class ErbUtilTest < ActiveSupport::TestCase include ERB::Util ERB::Util::HTML_ESCAPE.each do |given, expected| @@ -16,6 +16,16 @@ class ErbUtilTest < Test::Unit::TestCase end end + def test_json_escape_returns_unsafe_strings_when_passed_unsafe_strings + value = json_escape("asdf") + assert !value.html_safe? + end + + def test_json_escape_returns_safe_strings_when_passed_safe_strings + value = json_escape("asdf".html_safe) + assert value.html_safe? + end + def test_html_escape_is_html_safe escaped = h("<p>") assert_equal "<p>", escaped @@ -34,4 +44,18 @@ class ErbUtilTest < Test::Unit::TestCase assert_equal chr, html_escape(chr) end end + + def test_html_escape_once + assert_equal '1 < 2 & 3', html_escape_once('1 < 2 & 3') + end + + def test_html_escape_once_returns_unsafe_strings_when_passed_unsafe_strings + value = html_escape_once('1 < 2 & 3') + assert !value.html_safe? + end + + def test_html_escape_once_returns_safe_strings_when_passed_safe_strings + value = html_escape_once('1 < 2 & 3'.html_safe) + assert value.html_safe? + end end diff --git a/actionpack/test/template/form_collections_helper_test.rb b/actionpack/test/template/form_collections_helper_test.rb new file mode 100644 index 0000000000..c73e80ed88 --- /dev/null +++ b/actionpack/test/template/form_collections_helper_test.rb @@ -0,0 +1,336 @@ +require 'abstract_unit' + +class Category < Struct.new(:id, :name) +end + +class FormCollectionsHelperTest < ActionView::TestCase + def assert_no_select(selector, value = nil) + assert_select(selector, :text => value, :count => 0) + end + + def with_collection_radio_buttons(*args, &block) + @output_buffer = collection_radio_buttons(*args, &block) + end + + def with_collection_check_boxes(*args, &block) + @output_buffer = collection_check_boxes(*args, &block) + end + + # COLLECTION RADIO BUTTONS + test 'collection radio accepts a collection and generate inputs from value method' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s + + assert_select 'input[type=radio][value=true]#user_active_true' + assert_select 'input[type=radio][value=false]#user_active_false' + end + + test 'collection radio accepts a collection and generate inputs from label method' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s + + assert_select 'label[for=user_active_true]', 'true' + assert_select 'label[for=user_active_false]', 'false' + end + + test 'collection radio handles camelized collection values for labels correctly' do + with_collection_radio_buttons :user, :active, ['Yes', 'No'], :to_s, :to_s + + assert_select 'label[for=user_active_yes]', 'Yes' + assert_select 'label[for=user_active_no]', 'No' + end + + test 'colection radio should sanitize collection values for labels correctly' do + with_collection_radio_buttons :user, :name, ['$0.99', '$1.99'], :to_s, :to_s + assert_select 'label[for=user_name_099]', '$0.99' + assert_select 'label[for=user_name_199]', '$1.99' + end + + test 'collection radio accepts checked item' do + with_collection_radio_buttons :user, :active, [[1, true], [0, false]], :last, :first, :checked => true + + assert_select 'input[type=radio][value=true][checked=checked]' + assert_no_select 'input[type=radio][value=false][checked=checked]' + end + + test 'collection radio accepts multiple disabled items' do + collection = [[1, true], [0, false], [2, 'other']] + with_collection_radio_buttons :user, :active, collection, :last, :first, :disabled => [true, false] + + assert_select 'input[type=radio][value=true][disabled=disabled]' + assert_select 'input[type=radio][value=false][disabled=disabled]' + assert_no_select 'input[type=radio][value=other][disabled=disabled]' + end + + test 'collection radio accepts single disable item' do + collection = [[1, true], [0, false]] + with_collection_radio_buttons :user, :active, collection, :last, :first, :disabled => true + + assert_select 'input[type=radio][value=true][disabled=disabled]' + assert_no_select 'input[type=radio][value=false][disabled=disabled]' + end + + test 'collection radio accepts html options as input' do + collection = [[1, true], [0, false]] + with_collection_radio_buttons :user, :active, collection, :last, :first, {}, :class => 'special-radio' + + assert_select 'input[type=radio][value=true].special-radio#user_active_true' + assert_select 'input[type=radio][value=false].special-radio#user_active_false' + end + + test 'collection radio does not wrap input inside the label' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s + + assert_select 'input[type=radio] + label' + assert_no_select 'label input' + end + + test 'collection radio accepts a block to render the label as radio button wrapper' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b| + b.label { b.radio_button } + end + + assert_select 'label[for=user_active_true] > input#user_active_true[type=radio]' + assert_select 'label[for=user_active_false] > input#user_active_false[type=radio]' + end + + test 'collection radio accepts a block to change the order of label and radio button' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b| + b.label + b.radio_button + end + + assert_select 'label[for=user_active_true] + input#user_active_true[type=radio]' + assert_select 'label[for=user_active_false] + input#user_active_false[type=radio]' + end + + test 'collection radio with block helpers accept extra html options' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b| + b.label(:class => "radio_button") + b.radio_button(:class => "radio_button") + end + + assert_select 'label.radio_button[for=user_active_true] + input#user_active_true.radio_button[type=radio]' + assert_select 'label.radio_button[for=user_active_false] + input#user_active_false.radio_button[type=radio]' + end + + test 'collection radio with block helpers allows access to current text and value' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b| + b.label(:"data-value" => b.value) { b.radio_button + b.text } + end + + assert_select 'label[for=user_active_true][data-value=true]', 'true' do + assert_select 'input#user_active_true[type=radio]' + end + assert_select 'label[for=user_active_false][data-value=false]', 'false' do + assert_select 'input#user_active_false[type=radio]' + end + end + + test 'collection radio with block helpers allows access to the current object item in the collection to access extra properties' do + with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b| + b.label(:class => b.object) { b.radio_button + b.text } + end + + assert_select 'label.true[for=user_active_true]', 'true' do + assert_select 'input#user_active_true[type=radio]' + end + assert_select 'label.false[for=user_active_false]', 'false' do + assert_select 'input#user_active_false[type=radio]' + end + end + + test 'collection radio buttons with fields for' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + @output_buffer = fields_for(:post) do |p| + p.collection_radio_buttons :category_id, collection, :id, :name + end + + assert_select 'input#post_category_id_1[type=radio][value=1]' + assert_select 'input#post_category_id_2[type=radio][value=2]' + + assert_select 'label[for=post_category_id_1]', 'Category 1' + assert_select 'label[for=post_category_id_2]', 'Category 2' + end + + # COLLECTION CHECK BOXES + test 'collection check boxes accepts a collection and generate a serie of checkboxes for value method' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_check_boxes :user, :category_ids, collection, :id, :name + + assert_select 'input#user_category_ids_1[type=checkbox][value=1]' + assert_select 'input#user_category_ids_2[type=checkbox][value=2]' + end + + test 'collection check boxes generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_check_boxes :user, :category_ids, collection, :id, :name + + assert_select "input[type=hidden][name='user[category_ids][]'][value=]", :count => 1 + end + + test 'collection check boxes accepts a collection and generate a serie of checkboxes with labels for label method' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_check_boxes :user, :category_ids, collection, :id, :name + + assert_select 'label[for=user_category_ids_1]', 'Category 1' + assert_select 'label[for=user_category_ids_2]', 'Category 2' + end + + test 'collection check boxes handles camelized collection values for labels correctly' do + with_collection_check_boxes :user, :active, ['Yes', 'No'], :to_s, :to_s + + assert_select 'label[for=user_active_yes]', 'Yes' + assert_select 'label[for=user_active_no]', 'No' + end + + test 'colection check box should sanitize collection values for labels correctly' do + with_collection_check_boxes :user, :name, ['$0.99', '$1.99'], :to_s, :to_s + assert_select 'label[for=user_name_099]', '$0.99' + assert_select 'label[for=user_name_199]', '$1.99' + end + + test 'collection check boxes accepts selected values as :checked option' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :checked => [1, 3] + + assert_select 'input[type=checkbox][value=1][checked=checked]' + assert_select 'input[type=checkbox][value=3][checked=checked]' + assert_no_select 'input[type=checkbox][value=2][checked=checked]' + end + + test 'collection check boxes accepts selected string values as :checked option' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :checked => ['1', '3'] + + assert_select 'input[type=checkbox][value=1][checked=checked]' + assert_select 'input[type=checkbox][value=3][checked=checked]' + assert_no_select 'input[type=checkbox][value=2][checked=checked]' + end + + test 'collection check boxes accepts a single checked value' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :checked => 3 + + assert_select 'input[type=checkbox][value=3][checked=checked]' + assert_no_select 'input[type=checkbox][value=1][checked=checked]' + assert_no_select 'input[type=checkbox][value=2][checked=checked]' + end + + test 'collection check boxes accepts selected values as :checked option and override the model values' do + user = Struct.new(:category_ids).new(2) + collection = (1..3).map{|i| [i, "Category #{i}"] } + + @output_buffer = fields_for(:user, user) do |p| + p.collection_check_boxes :category_ids, collection, :first, :last, :checked => [1, 3] + end + + assert_select 'input[type=checkbox][value=1][checked=checked]' + assert_select 'input[type=checkbox][value=3][checked=checked]' + assert_no_select 'input[type=checkbox][value=2][checked=checked]' + end + + test 'collection check boxes accepts multiple disabled items' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :disabled => [1, 3] + + assert_select 'input[type=checkbox][value=1][disabled=disabled]' + assert_select 'input[type=checkbox][value=3][disabled=disabled]' + assert_no_select 'input[type=checkbox][value=2][disabled=disabled]' + end + + test 'collection check boxes accepts single disable item' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :disabled => 1 + + assert_select 'input[type=checkbox][value=1][disabled=disabled]' + assert_no_select 'input[type=checkbox][value=3][disabled=disabled]' + assert_no_select 'input[type=checkbox][value=2][disabled=disabled]' + end + + test 'collection check boxes accepts a proc to disabled items' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :disabled => proc { |i| i.first == 1 } + + assert_select 'input[type=checkbox][value=1][disabled=disabled]' + assert_no_select 'input[type=checkbox][value=3][disabled=disabled]' + assert_no_select 'input[type=checkbox][value=2][disabled=disabled]' + end + + test 'collection check boxes accepts html options' do + collection = [[1, 'Category 1'], [2, 'Category 2']] + with_collection_check_boxes :user, :category_ids, collection, :first, :last, {}, :class => 'check' + + assert_select 'input.check[type=checkbox][value=1]' + assert_select 'input.check[type=checkbox][value=2]' + end + + test 'collection check boxes with fields for' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + @output_buffer = fields_for(:post) do |p| + p.collection_check_boxes :category_ids, collection, :id, :name + end + + assert_select 'input#post_category_ids_1[type=checkbox][value=1]' + assert_select 'input#post_category_ids_2[type=checkbox][value=2]' + + assert_select 'label[for=post_category_ids_1]', 'Category 1' + assert_select 'label[for=post_category_ids_2]', 'Category 2' + end + + test 'collection check boxes does not wrap input inside the label' do + with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s + + assert_select 'input[type=checkbox] + label' + assert_no_select 'label input' + end + + test 'collection check boxes accepts a block to render the label as check box wrapper' do + with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b| + b.label { b.check_box } + end + + assert_select 'label[for=user_active_true] > input#user_active_true[type=checkbox]' + assert_select 'label[for=user_active_false] > input#user_active_false[type=checkbox]' + end + + test 'collection check boxes accepts a block to change the order of label and check box' do + with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b| + b.label + b.check_box + end + + assert_select 'label[for=user_active_true] + input#user_active_true[type=checkbox]' + assert_select 'label[for=user_active_false] + input#user_active_false[type=checkbox]' + end + + test 'collection check boxes with block helpers accept extra html options' do + with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b| + b.label(:class => "check_box") + b.check_box(:class => "check_box") + end + + assert_select 'label.check_box[for=user_active_true] + input#user_active_true.check_box[type=checkbox]' + assert_select 'label.check_box[for=user_active_false] + input#user_active_false.check_box[type=checkbox]' + end + + test 'collection check boxes with block helpers allows access to current text and value' do + with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b| + b.label(:"data-value" => b.value) { b.check_box + b.text } + end + + assert_select 'label[for=user_active_true][data-value=true]', 'true' do + assert_select 'input#user_active_true[type=checkbox]' + end + assert_select 'label[for=user_active_false][data-value=false]', 'false' do + assert_select 'input#user_active_false[type=checkbox]' + end + end + + test 'collection check boxes with block helpers allows access to the current object item in the collection to access extra properties' do + with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b| + b.label(:class => b.object) { b.check_box + b.text } + end + + assert_select 'label.true[for=user_active_true]', 'true' do + assert_select 'input#user_active_true[type=checkbox]' + end + assert_select 'label.false[for=user_active_false]', 'false' do + assert_select 'input#user_active_false[type=checkbox]' + end + end +end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 286bfb4d04..27cc3ad48a 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -3,6 +3,8 @@ require 'controller/fake_models' require 'active_support/core_ext/object/inclusion' class FormHelperTest < ActionView::TestCase + include RenderERBUtils + tests ActionView::Helpers::FormHelper def form_for(*) @@ -27,7 +29,13 @@ class FormHelperTest < ActionView::TestCase :body => "Write entire text here", :color => { :red => "Rojo" + }, + :comments => { + :body => "Write body here" } + }, + :tag => { + :value => "Tag" } } } @@ -57,7 +65,7 @@ class FormHelperTest < ActionView::TestCase def full_messages() [ "Author name can't be empty" ] end }.new end - def @post.id; 123; end + def @post.to_key; [123]; end def @post.id_before_type_cast; 123; end def @post.to_param; '123'; end @@ -68,6 +76,12 @@ class FormHelperTest < ActionView::TestCase @post.secret = 1 @post.written_on = Date.new(2004, 6, 15) + @post.comments = [] + @post.comments << @comment + + @post.tags = [] + @post.tags << Tag.new + @blog_post = Blog::Post.new("And his name will be forty and four.", 44) end @@ -83,7 +97,7 @@ class FormHelperTest < ActionView::TestCase end end - match "/foo", :to => "controller#action" + get "/foo", :to => "controller#action" root :to => "main#index" end @@ -101,6 +115,14 @@ class FormHelperTest < ActionView::TestCase super end + class FooTag < ActionView::Helpers::Tags::Base + def initialize; end + end + + def test_tags_base_child_without_render_method + assert_raise(NotImplementedError) { FooTag.new.render } + end + def test_label assert_dom_equal('<label for="post_title">Title</label>', label("post", "title")) assert_dom_equal('<label for="post_title">The title goes here</label>', label("post", "title", "The title goes here")) @@ -151,6 +173,40 @@ class FormHelperTest < ActionView::TestCase I18n.locale = old_locale end + def test_label_with_locales_and_nested_attributes + old_locale, I18n.locale = I18n.locale, :label + form_for(@post, :html => { :id => 'create-post' }) do |f| + f.fields_for(:comments) do |cf| + concat cf.label(:body) + end + end + + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch') do + "<label for=\"post_comments_attributes_0_body\">Write body here</label>" + end + + assert_dom_equal expected, output_buffer + ensure + I18n.locale = old_locale + end + + def test_label_with_locales_fallback_and_nested_attributes + old_locale, I18n.locale = I18n.locale, :label + form_for(@post, :html => { :id => 'create-post' }) do |f| + f.fields_for(:tags) do |cf| + concat cf.label(:value) + end + end + + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch') do + "<label for=\"post_tags_attributes_0_value\">Tag</label>" + end + + assert_dom_equal expected, output_buffer + ensure + I18n.locale = old_locale + end + def test_label_with_for_attribute_as_symbol assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, :for => "my_for")) end @@ -159,6 +215,10 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, "for" => "my_for")) end + def test_label_does_not_generate_for_attribute_when_given_nil + assert_dom_equal('<label>Title</label>', label(:post, :title, :for => nil)) + end + def test_label_with_id_attribute_as_symbol assert_dom_equal('<label for="post_title" id="my_id">Title</label>', label(:post, :title, nil, :id => "my_id")) end @@ -184,32 +244,40 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal('<label for="post_title">The title, please:</label>', label(:post, :title) { "The title, please:" }) end + def test_label_with_block_and_options + assert_dom_equal('<label for="my_for">The title, please:</label>', label(:post, :title, "for" => "my_for") { "The title, please:" }) + end + + def test_label_with_block_in_erb + assert_equal "<label for=\"post_message\">\n Message\n <input id=\"post_message\" name=\"post[message]\" type=\"text\" />\n</label>", view.render("test/label_with_block") + end + def test_text_field assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title") + '<input id="post_title" name="post[title]" type="text" value="Hello World" />', text_field("post", "title") ) assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="password" />', password_field("post", "title") + '<input id="post_title" name="post[title]" type="password" />', password_field("post", "title") ) assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="password" value="Hello World" />', password_field("post", "title", :value => @post.title) + '<input id="post_title" name="post[title]" type="password" value="Hello World" />', password_field("post", "title", :value => @post.title) ) assert_dom_equal( - '<input id="person_name" name="person[name]" size="30" type="password" />', password_field("person", "name") + '<input id="person_name" name="person[name]" type="password" />', password_field("person", "name") ) end def test_text_field_with_escapes @post.title = "<b>Hello World</b>" assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="text" value="<b>Hello World</b>" />', text_field("post", "title") + '<input id="post_title" name="post[title]" type="text" value="<b>Hello World</b>" />', text_field("post", "title") ) end def test_text_field_with_html_entities @post.title = "The HTML Entity for & is &" assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="text" value="The HTML Entity for & is &amp;" />', + '<input id="post_title" name="post[title]" type="text" value="The HTML Entity for & is &amp;" />', text_field("post", "title") ) end @@ -233,13 +301,18 @@ class FormHelperTest < ActionView::TestCase end def test_text_field_with_nil_value - expected = '<input id="post_title" name="post[title]" size="30" type="text" />' + expected = '<input id="post_title" name="post[title]" type="text" />' assert_dom_equal expected, text_field("post", "title", :value => nil) end + def test_text_field_with_nil_name + expected = '<input id="post_title" type="text" value="Hello World" />' + assert_dom_equal expected, text_field("post", "title", :name => nil) + end + def test_text_field_doesnt_change_param_values object_name = 'post[]' - expected = '<input id="post_123_title" name="post[123][title]" size="30" type="text" value="Hello World" />' + expected = '<input id="post_123_title" name="post[123][title]" type="text" value="Hello World" />' assert_equal expected, text_field(object_name, "title") assert_equal object_name, "post[]" end @@ -273,39 +346,56 @@ class FormHelperTest < ActionView::TestCase end def test_text_field_with_custom_type - assert_dom_equal '<input id="user_email" size="30" name="user[email]" type="email" />', + assert_dom_equal '<input id="user_email" name="user[email]" type="email" />', text_field("user", "email", :type => "email") end - def test_check_box + def test_check_box_is_html_safe + assert check_box("post", "secret").html_safe? + end + + def test_check_box_checked_if_object_value_is_same_that_check_value assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + end + + def test_check_box_not_checked_if_object_value_is_same_that_unchecked_value @post.secret = 0 assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + end + + def test_check_box_checked_if_option_checked_is_present assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret" ,{"checked"=>"checked"}) ) + end + + def test_check_box_checked_if_object_value_is_true @post.secret = true assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret?") ) + end + def test_check_box_checked_if_object_value_includes_checked_value @post.secret = ['0'] assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + @post.secret = ['1'] assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', @@ -313,12 +403,109 @@ class FormHelperTest < ActionView::TestCase ) end - def test_check_box_with_explicit_checked_and_unchecked_values + def test_check_box_with_include_hidden_false + @post.secret = false + assert_dom_equal('<input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret", :include_hidden => false)) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_string @post.secret = "on" assert_dom_equal( '<input name="post[secret]" type="hidden" value="off" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" />', check_box("post", "secret", {}, "on", "off") ) + + @post.secret = "off" + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="off" /><input id="post_secret" name="post[secret]" type="checkbox" value="on" />', + check_box("post", "secret", {}, "on", "off") + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_boolean + @post.secret = false + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="true" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="false" />', + check_box("post", "secret", {}, false, true) + ) + + @post.secret = true + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="true" /><input id="post_secret" name="post[secret]" type="checkbox" value="false" />', + check_box("post", "secret", {}, false, true) + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_integer + @post.secret = 0 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 1 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 2 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_float + @post.secret = 0.0 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 1.1 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 2.2 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_big_decimal + @post.secret = BigDecimal.new(0) + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = BigDecimal.new(1) + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = BigDecimal.new(2.2, 1) + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + end + + def test_check_box_with_nil_unchecked_value + @post.secret = "on" + assert_dom_equal( + '<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" />', + check_box("post", "secret", {}, "on", nil) + ) + end + + def test_check_box_with_nil_unchecked_value_is_html_safe + assert check_box("post", "secret", {}, "on", nil).html_safe? end def test_check_box_with_multiple_behavior @@ -333,11 +520,17 @@ class FormHelperTest < ActionView::TestCase ) end + def test_checkbox_disabled_disables_hidden_field + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="0" disabled="disabled"/><input checked="checked" disabled="disabled" id="post_secret" name="post[secret]" type="checkbox" value="1" />', + check_box("post", "secret", { :disabled => true }) + ) + end - def test_checkbox_disabled_still_submits_checked_value + def test_checkbox_form_html5_attribute assert_dom_equal( - '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" disabled="disabled" id="post_secret" name="post[secret]" type="checkbox" value="1" />', - check_box("post", "secret", { :disabled => :true }) + '<input form="new_form" name="post[secret]" type="hidden" value="0" /><input checked="checked" form="new_form" id="post_secret" name="post[secret]" type="checkbox" value="1" />', + check_box("post", "secret", :form => "new_form") ) end @@ -382,7 +575,7 @@ class FormHelperTest < ActionView::TestCase def test_text_area assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea id="post_body" name="post[body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body") ) end @@ -390,14 +583,14 @@ class FormHelperTest < ActionView::TestCase def test_text_area_with_escapes @post.body = "Back to <i>the</i> hill and over it again!" assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to <i>the</i> hill and over it again!</textarea>', + %{<textarea id="post_body" name="post[body]">\nBack to <i>the</i> hill and over it again!</textarea>}, text_area("post", "body") ) end def test_text_area_with_alternate_value assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">Testing alternate values.</textarea>', + %{<textarea id="post_body" name="post[body]">\nTesting alternate values.</textarea>}, text_area("post", "body", :value => 'Testing alternate values.') ) end @@ -405,54 +598,110 @@ class FormHelperTest < ActionView::TestCase def test_text_area_with_html_entities @post.body = "The HTML Entity for & is &" assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">The HTML Entity for & is &amp;</textarea>', + %{<textarea id="post_body" name="post[body]">\nThe HTML Entity for & is &amp;</textarea>}, text_area("post", "body") ) end def test_text_area_with_size_option assert_dom_equal( - '<textarea cols="183" id="post_body" name="post[body]" rows="820">Back to the hill and over it again!</textarea>', + %{<textarea cols="183" id="post_body" name="post[body]" rows="820">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", :size => "183x820") ) end def test_search_field - expected = %{<input id="contact_notes_query" size="30" name="contact[notes_query]" type="search" />} + expected = %{<input id="contact_notes_query" name="contact[notes_query]" type="search" />} assert_dom_equal(expected, search_field("contact", "notes_query")) end def test_telephone_field - expected = %{<input id="user_cell" size="30" name="user[cell]" type="tel" />} + expected = %{<input id="user_cell" name="user[cell]" type="tel" />} assert_dom_equal(expected, telephone_field("user", "cell")) end + def test_date_field + expected = %{<input id="post_written_on" name="post[written_on]" type="date" value="2004-06-15" />} + assert_dom_equal(expected, date_field("post", "written_on")) + end + + def test_date_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="date" value="2004-06-15" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + assert_dom_equal(expected, date_field("post", "written_on")) + end + + def test_date_field_with_timewithzone_value + previous_time_zone, Time.zone = Time.zone, 'UTC' + expected = %{<input id="post_written_on" name="post[written_on]" type="date" value="2004-06-15" />} + @post.written_on = Time.zone.parse('2004-06-15 15:30:45') + assert_dom_equal(expected, date_field("post", "written_on")) + ensure + Time.zone = previous_time_zone + end + + def test_date_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="date" />} + @post.written_on = nil + assert_dom_equal(expected, date_field("post", "written_on")) + end + + def test_time_field + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="00:00:00.000" />} + assert_dom_equal(expected, time_field("post", "written_on")) + end + + def test_time_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + assert_dom_equal(expected, time_field("post", "written_on")) + end + + def test_time_field_with_timewithzone_value + previous_time_zone, Time.zone = Time.zone, 'UTC' + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = Time.zone.parse('2004-06-15 01:02:03') + assert_dom_equal(expected, time_field("post", "written_on")) + ensure + Time.zone = previous_time_zone + end + + def test_time_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="time" />} + @post.written_on = nil + assert_dom_equal(expected, time_field("post", "written_on")) + end + def test_url_field - expected = %{<input id="user_homepage" size="30" name="user[homepage]" type="url" />} + expected = %{<input id="user_homepage" name="user[homepage]" type="url" />} assert_dom_equal(expected, url_field("user", "homepage")) end def test_email_field - expected = %{<input id="user_address" size="30" name="user[address]" type="email" />} + expected = %{<input id="user_address" name="user[address]" type="email" />} assert_dom_equal(expected, email_field("user", "address")) end def test_number_field - expected = %{<input name="order[quantity]" size="30" max="9" id="order_quantity" type="number" min="1" />} + expected = %{<input name="order[quantity]" max="9" id="order_quantity" type="number" min="1" />} assert_dom_equal(expected, number_field("order", "quantity", :in => 1...10)) + expected = %{<input name="order[quantity]" size="30" max="9" id="order_quantity" type="number" min="1" />} + assert_dom_equal(expected, number_field("order", "quantity", :size => 30, :in => 1...10)) end def test_range_input - expected = %{<input name="hifi[volume]" step="0.1" size="30" max="11" id="hifi_volume" type="range" min="0" />} + expected = %{<input name="hifi[volume]" step="0.1" max="11" id="hifi_volume" type="range" min="0" />} assert_dom_equal(expected, range_field("hifi", "volume", :in => 0..11, :step => 0.1)) + expected = %{<input name="hifi[volume]" step="0.1" size="30" max="11" id="hifi_volume" type="range" min="0" />} + assert_dom_equal(expected, range_field("hifi", "volume", :size => 30, :in => 0..11, :step => 0.1)) end def test_explicit_name assert_dom_equal( - '<input id="post_title" name="dont guess" size="30" type="text" value="Hello World" />', text_field("post", "title", "name" => "dont guess") + '<input id="post_title" name="dont guess" type="text" value="Hello World" />', text_field("post", "title", "name" => "dont guess") ) assert_dom_equal( - '<textarea cols="40" id="post_body" name="really!" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea id="post_body" name="really!">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "name" => "really!") ) assert_dom_equal( @@ -469,10 +718,10 @@ class FormHelperTest < ActionView::TestCase def test_explicit_id assert_dom_equal( - '<input id="dont guess" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title", "id" => "dont guess") + '<input id="dont guess" name="post[title]" type="text" value="Hello World" />', text_field("post", "title", "id" => "dont guess") ) assert_dom_equal( - '<textarea cols="40" id="really!" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea id="really!" name="post[body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "id" => "really!") ) assert_dom_equal( @@ -489,10 +738,10 @@ class FormHelperTest < ActionView::TestCase def test_nil_id assert_dom_equal( - '<input name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title", "id" => nil) + '<input name="post[title]" type="text" value="Hello World" />', text_field("post", "title", "id" => nil) ) assert_dom_equal( - '<textarea cols="40" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea name="post[body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "id" => nil) ) assert_dom_equal( @@ -519,11 +768,11 @@ class FormHelperTest < ActionView::TestCase def test_index assert_dom_equal( - '<input name="post[5][title]" size="30" id="post_5_title" type="text" value="Hello World" />', + '<input name="post[5][title]" id="post_5_title" type="text" value="Hello World" />', text_field("post", "title", "index" => 5) ) assert_dom_equal( - '<textarea cols="40" name="post[5][body]" id="post_5_body" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea name="post[5][body]" id="post_5_body">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "index" => 5) ) assert_dom_equal( @@ -546,11 +795,11 @@ class FormHelperTest < ActionView::TestCase def test_index_with_nil_id assert_dom_equal( - '<input name="post[5][title]" size="30" type="text" value="Hello World" />', + '<input name="post[5][title]" type="text" value="Hello World" />', text_field("post", "title", "index" => 5, 'id' => nil) ) assert_dom_equal( - '<textarea cols="40" name="post[5][body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea name="post[5][body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "index" => 5, 'id' => nil) ) assert_dom_equal( @@ -572,16 +821,16 @@ class FormHelperTest < ActionView::TestCase end def test_auto_index - pid = @post.id + pid = 123 assert_dom_equal( "<label for=\"post_#{pid}_title\">Title</label>", label("post[]", "title") ) assert_dom_equal( - "<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title") + "<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title") ) assert_dom_equal( - "<textarea cols=\"40\" id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\" rows=\"20\">Back to the hill and over it again!</textarea>", + "<textarea id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\">\nBack to the hill and over it again!</textarea>", text_area("post[]", "body") ) assert_dom_equal( @@ -589,7 +838,7 @@ class FormHelperTest < ActionView::TestCase check_box("post[]", "secret") ) assert_dom_equal( -"<input checked=\"checked\" id=\"post_#{pid}_title_hello_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Hello World\" />", + "<input checked=\"checked\" id=\"post_#{pid}_title_hello_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Hello World\" />", radio_button("post[]", "title", "Hello World") ) assert_dom_equal("<input id=\"post_#{pid}_title_goodbye_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Goodbye World\" />", @@ -598,13 +847,13 @@ class FormHelperTest < ActionView::TestCase end def test_auto_index_with_nil_id - pid = @post.id + pid = 123 assert_dom_equal( - "<input name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", + "<input name=\"post[#{pid}][title]\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title", :id => nil) ) assert_dom_equal( - "<textarea cols=\"40\" name=\"post[#{pid}][body]\" rows=\"20\">Back to the hill and over it again!</textarea>", + "<textarea name=\"post[#{pid}][body]\">\nBack to the hill and over it again!</textarea>", text_area("post[]", "body", :id => nil) ) assert_dom_equal( @@ -633,15 +882,55 @@ class FormHelperTest < ActionView::TestCase concat f.text_area(:body) concat f.check_box(:secret) concat f.submit('Create post') + concat f.button('Create post') end - expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put") do + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch') do "<label for='post_title'>The Title</label>" + - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + - "<input name='commit' type='submit' value='Create post' />" + "<input name='commit' type='submit' value='Create post' />" + + "<button name='button' type='submit'>Create post</button>" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_collection_radio_buttons + post = Post.new + def post.active; false; end + form_for(post) do |f| + concat f.collection_radio_buttons(:active, [true, false], :to_s, :to_s) + end + + expected = whole_form("/posts", "new_post" , "new_post") do + "<input id='post_active_true' name='post[active]' type='radio' value='true' />" + + "<label for='post_active_true'>true</label>" + + "<input checked='checked' id='post_active_false' name='post[active]' type='radio' value='false' />" + + "<label for='post_active_false'>false</label>" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_collection_check_boxes + post = Post.new + def post.tag_ids; [1, 3]; end + collection = (1..3).map{|i| [i, "Tag #{i}"] } + form_for(post) do |f| + concat f.collection_check_boxes(:tag_ids, collection, :first, :last) + end + + expected = whole_form("/posts", "new_post" , "new_post") do + "<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" + + "<label for='post_tag_ids_1'>Tag 1</label>" + + "<input id='post_tag_ids_2' name='post[tag_ids][]' type='checkbox' value='2' />" + + "<label for='post_tag_ids_2'>Tag 2</label>" + + "<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" + + "<label for='post_tag_ids_3'>Tag 3</label>" + + "<input name='post[tag_ids][]' type='hidden' value='' />" end assert_dom_equal expected, output_buffer @@ -654,7 +943,7 @@ class FormHelperTest < ActionView::TestCase concat f.file_field(:file) end - expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put", :multipart => true) do + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch', :multipart => true) do "<input name='post[file]' type='file' id='post_file' />" end @@ -670,7 +959,7 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form("/posts/123", "edit_post_123" , "edit_post", :method => "put", :multipart => true) do + expected = whole_form("/posts/123", "edit_post_123" , "edit_post", :method => 'patch', :multipart => true) do "<input name='post[comment][file]' type='file' id='post_comment_file' />" end @@ -683,26 +972,25 @@ class FormHelperTest < ActionView::TestCase concat f.label(:title) end - expected = whole_form("/posts/123.json", "edit_post_123" , "edit_post", :method => "put") do + expected = whole_form("/posts/123.json", "edit_post_123" , "edit_post", :method => 'patch') do "<label for='post_title'>Title</label>" end assert_dom_equal expected, output_buffer end - def test_form_for_with_isolated_namespaced_model + def test_form_for_with_model_using_relative_model_naming form_for(@blog_post) do |f| concat f.text_field :title concat f.submit('Edit post') end - expected = - "<form accept-charset='UTF-8' action='/posts/44' method='post'>" + - snowman + - "<label for='post_title'>The Title</label>" + - "<input name='post[title]' size='30' type='text' id='post_title' value='And his name will be forty and four.' />" + - "<input name='commit' id='post_submit' type='submit' value='Edit post' />" + - "</form>" + expected = whole_form("/posts/44", "edit_post_44" , "edit_post", :method => 'patch') do + "<input name='post[title]' type='text' id='post_title' value='And his name will be forty and four.' />" + + "<input name='commit' type='submit' value='Edit post' />" + end + + assert_dom_equal expected, output_buffer end def test_form_for_with_symbol_object_name @@ -714,10 +1002,10 @@ class FormHelperTest < ActionView::TestCase concat f.submit('Create post') end - expected = whole_form("/posts/123", "create-post", "other_name_edit", :method => "put") do + expected = whole_form("/posts/123", "create-post", "edit_other_name", :method => 'patch') do "<label for='other_name_title' class='post_title'>Title</label>" + - "<input name='other_name[title]' size='30' id='other_name_title' value='Hello World' type='text' />" + - "<textarea name='other_name[body]' id='other_name_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='other_name[title]' id='other_name_title' value='Hello World' type='text' />" + + "<textarea name='other_name[body]' id='other_name_body'>\nBack to the hill and over it again!</textarea>" + "<input name='other_name[secret]' value='0' type='hidden' />" + "<input name='other_name[secret]' checked='checked' id='other_name_secret' value='1' type='checkbox' />" + "<input name='commit' value='Create post' type='submit' />" @@ -734,8 +1022,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/", "create-post", "edit_post", "delete") do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" end @@ -751,8 +1039,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/", "create-post", "edit_post", "delete") do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" end @@ -768,22 +1056,39 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/search", "search-post", "new_post", "get") do - "<input name='post[title]' size='30' type='search' id='post_title' />" + "<input name='post[title]' type='search' id='post_title' />" end assert_dom_equal expected, output_buffer end def test_form_for_with_remote - form_for(@post, :url => '/', :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| + form_for(@post, :url => '/', :remote => true, :html => { :id => 'create-post', :method => :patch}) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end + + expected = whole_form("/", "create-post", "edit_post", :method => 'patch', :remote => true) do + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + + "<input name='post[secret]' type='hidden' value='0' />" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_remote_in_html + form_for(@post, :url => '/', :html => { :remote => true, :id => 'create-post', :method => :patch }) do |f| concat f.text_field(:title) concat f.text_area(:body) concat f.check_box(:secret) end - expected = whole_form("/", "create-post", "edit_post", :method => "put", :remote => true) do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form("/", "create-post", "edit_post", :method => 'patch', :remote => true) do + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" end @@ -793,6 +1098,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_remote_without_html @post.persisted = false + @post.stubs(:to_key).returns(nil) form_for(@post, :remote => true) do |f| concat f.text_field(:title) concat f.text_area(:body) @@ -800,8 +1106,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", 'new_post', 'new_post', :remote => true) do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" end @@ -817,8 +1123,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/", "create-post") do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" end @@ -834,10 +1140,10 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'post[]_edit', 'post[]_edit', 'put') do + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do "<label for='post_123_title'>Title</label>" + - "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" + - "<textarea name='post[123][body]' id='post_123_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[123][title]' type='text' id='post_123_title' value='Hello World' />" + + "<textarea name='post[123][body]' id='post_123_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[123][secret]' type='hidden' value='0' />" + "<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />" end @@ -852,9 +1158,9 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'post[]_edit', 'post[]_edit', 'put') do - "<input name='post[][title]' size='30' type='text' id='post__title' value='Hello World' />" + - "<textarea name='post[][body]' id='post__body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[][title]' type='text' id='post__title' value='Hello World' />" + + "<textarea name='post[][body]' id='post__body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[][secret]' type='hidden' value='0' />" + "<input name='post[][secret]' checked='checked' type='checkbox' id='post__secret' value='1' />" end @@ -862,10 +1168,143 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_label_error_wrapping + form_for(@post) do |f| + concat f.label(:author_name, :class => 'label') + concat f.text_field(:author_name) + concat f.submit('Create post') + end + + expected = whole_form('/posts/123', 'edit_post_123' , 'edit_post', 'patch') do + "<div class='field_with_errors'><label for='post_author_name' class='label'>Author name</label></div>" + + "<div class='field_with_errors'><input name='post[author_name]' type='text' id='post_author_name' value='' /></div>" + + "<input name='commit' type='submit' value='Create post' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_label_error_wrapping_without_conventional_instance_variable + post = remove_instance_variable :@post + + form_for(post) do |f| + concat f.label(:author_name, :class => 'label') + concat f.text_field(:author_name) + concat f.submit('Create post') + end + + expected = whole_form('/posts/123', 'edit_post_123' , 'edit_post', 'patch') do + "<div class='field_with_errors'><label for='post_author_name' class='label'>Author name</label></div>" + + "<div class='field_with_errors'><input name='post[author_name]' type='text' id='post_author_name' value='' /></div>" + + "<input name='commit' type='submit' value='Create post' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_label_error_wrapping_block_and_non_block_versions + form_for(@post) do |f| + concat f.label(:author_name, 'Name', :class => 'label') + concat f.label(:author_name, :class => 'label') { 'Name' } + end + + expected = whole_form('/posts/123', 'edit_post_123' , 'edit_post', 'patch') do + "<div class='field_with_errors'><label for='post_author_name' class='label'>Name</label></div>" + + "<div class='field_with_errors'><label for='post_author_name' class='label'>Name</label></div>" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_namespace + form_for(@post, :namespace => 'namespace') do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'patch') do + "<input name='post[title]' type='text' id='namespace_post_title' value='Hello World' />" + + "<textarea name='post[body]' id='namespace_post_body'>\nBack to the hill and over it again!</textarea>" + + "<input name='post[secret]' type='hidden' value='0' />" + + "<input name='post[secret]' checked='checked' type='checkbox' id='namespace_post_secret' value='1' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_namespace_with_date_select + form_for(@post, :namespace => 'namespace') do |f| + concat f.date_select(:written_on) + end + + assert_select 'select#namespace_post_written_on_1i' + end + + def test_form_for_with_namespace_with_label + form_for(@post, :namespace => 'namespace') do |f| + concat f.label(:title) + concat f.text_field(:title) + end + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'patch') do + "<label for='namespace_post_title'>Title</label>" + + "<input name='post[title]' type='text' id='namespace_post_title' value='Hello World' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_two_form_for_with_namespace + form_for(@post, :namespace => 'namespace_1') do |f| + concat f.label(:title) + concat f.text_field(:title) + end + + expected_1 = whole_form('/posts/123', 'namespace_1_edit_post_123', 'edit_post', 'patch') do + "<label for='namespace_1_post_title'>Title</label>" + + "<input name='post[title]' type='text' id='namespace_1_post_title' value='Hello World' />" + end + + assert_dom_equal expected_1, output_buffer + + form_for(@post, :namespace => 'namespace_2') do |f| + concat f.label(:title) + concat f.text_field(:title) + end + + expected_2 = whole_form('/posts/123', 'namespace_2_edit_post_123', 'edit_post', 'patch') do + "<label for='namespace_2_post_title'>Title</label>" + + "<input name='post[title]' type='text' id='namespace_2_post_title' value='Hello World' />" + end + + assert_dom_equal expected_2, output_buffer + end + + def test_fields_for_with_namespace + @comment.body = 'Hello World' + form_for(@post, :namespace => 'namespace') do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.fields_for(@comment) { |c| + concat c.text_field(:body) + } + end + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'patch') do + "<input name='post[title]' type='text' id='namespace_post_title' value='Hello World' />" + + "<textarea name='post[body]' id='namespace_post_body'>\nBack to the hill and over it again!</textarea>" + + "<input name='post[comment][body]' type='text' id='namespace_post_comment_body' value='Hello World' />" + end + + assert_dom_equal expected, output_buffer + end + def test_submit_with_object_as_new_record_and_locale_strings old_locale, I18n.locale = I18n.locale, :submit @post.persisted = false + @post.stubs(:to_key).returns(nil) form_for(@post) do |f| concat f.submit end @@ -886,7 +1325,7 @@ class FormHelperTest < ActionView::TestCase concat f.submit end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do "<input name='commit' type='submit' value='Confirm Post changes' />" end @@ -918,7 +1357,7 @@ class FormHelperTest < ActionView::TestCase concat f.submit end - expected = whole_form('/posts/123', 'another_post_edit', 'another_post_edit', :method => 'put') do + expected = whole_form('/posts/123', 'edit_another_post', 'edit_another_post', :method => 'patch') do "<input name='commit' type='submit' value='Update your Post' />" end @@ -935,8 +1374,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - "<input name='post[comment][body]' size='30' type='text' id='post_comment_body' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<input name='post[comment][body]' type='text' id='post_comment_body' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -950,9 +1389,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'post[]_edit', 'post[]_edit', 'put') do - "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" + - "<input name='post[123][comment][][name]' size='30' type='text' id='post_123_comment__name' value='new comment' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][title]' type='text' id='post_123_title' value='Hello World' />" + + "<input name='post[123][comment][][name]' type='text' id='post_123_comment__name' value='new comment' />" end assert_dom_equal expected, output_buffer @@ -966,9 +1405,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[1][title]' size='30' type='text' id='post_1_title' value='Hello World' />" + - "<input name='post[1][comment][1][name]' size='30' type='text' id='post_1_comment_1_name' value='new comment' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[1][title]' type='text' id='post_1_title' value='Hello World' />" + + "<input name='post[1][comment][1][name]' type='text' id='post_1_comment_1_name' value='new comment' />" end assert_dom_equal expected, output_buffer @@ -981,8 +1420,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[1][comment][title]' size='30' type='text' id='post_1_comment_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[1][comment][title]' type='text' id='post_1_comment_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -995,8 +1434,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[1][comment][5][title]' size='30' type='text' id='post_1_comment_5_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[1][comment][5][title]' type='text' id='post_1_comment_5_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1009,8 +1448,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'post[]_edit', 'post[]_edit', 'put') do - "<input name='post[123][comment][title]' size='30' type='text' id='post_123_comment_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][comment][title]' type='text' id='post_123_comment_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1023,7 +1462,7 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do "<input name='post[comment][5][title]' type='radio' id='post_comment_5_title_hello' value='hello' />" end @@ -1037,8 +1476,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'post[]_edit', 'post[]_edit', 'put') do - "<input name='post[123][comment][123][title]' size='30' type='text' id='post_123_comment_123_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][comment][123][title]' type='text' id='post_123_comment_123_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1057,10 +1496,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'post[]_edit', 'post[]_edit', 'put') do - "<input name='post[123][comment][5][title]' size='30' type='text' id='post_123_comment_5_title' value='Hello World' />" - end + whole_form('/posts/123', 'post_edit', 'post_edit', 'put') do - "<input name='post[1][comment][123][title]' size='30' type='text' id='post_1_comment_123_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][comment][5][title]' type='text' id='post_123_comment_5_title' value='Hello World' />" + end + whole_form('/posts/123', 'edit_post', 'edit_post', 'patch') do + "<input name='post[1][comment][123][title]' type='text' id='post_1_comment_123_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1076,9 +1515,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="new author" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="new author" />' end assert_dom_equal expected, output_buffer @@ -1103,9 +1542,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' end @@ -1122,9 +1561,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' end @@ -1141,9 +1580,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' end assert_dom_equal expected, output_buffer @@ -1159,9 +1598,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' end assert_dom_equal expected, output_buffer @@ -1177,9 +1616,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' end @@ -1197,10 +1636,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' end assert_dom_equal expected, output_buffer @@ -1218,11 +1657,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1245,12 +1684,12 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1272,11 +1711,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1298,12 +1737,12 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1321,11 +1760,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1345,12 +1784,12 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1368,10 +1807,10 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="new comment" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="new comment" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="new comment" />' end assert_dom_equal expected, output_buffer @@ -1389,11 +1828,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #321" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="new comment" />' end assert_dom_equal expected, output_buffer @@ -1407,8 +1846,8 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' end assert_dom_equal expected, output_buffer @@ -1424,11 +1863,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1445,11 +1884,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1467,11 +1906,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1490,11 +1929,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #321" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="new comment" />' end assert_dom_equal expected, output_buffer @@ -1510,14 +1949,64 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" size="30" type="text" value="comment #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" type="text" value="comment #321" />' + '<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' end assert_dom_equal expected, output_buffer end + def test_nested_fields_for_index_method_with_existing_records_on_a_nested_attributes_collection_association + @post.comments = Array.new(2) { |id| Comment.new(id + 1) } + + form_for(@post) do |f| + expected = 0 + @post.comments.each do |comment| + f.fields_for(:comments, comment) { |cf| + assert_equal cf.index, expected + expected += 1 + } + end + end + end + + def test_nested_fields_for_index_method_with_existing_and_new_records_on_a_nested_attributes_collection_association + @post.comments = [Comment.new(321), Comment.new] + + form_for(@post) do |f| + expected = 0 + @post.comments.each do |comment| + f.fields_for(:comments, comment) { |cf| + assert_equal cf.index, expected + expected += 1 + } + end + end + end + + def test_nested_fields_for_index_method_with_existing_records_on_a_supplied_nested_attributes_collection + @post.comments = Array.new(2) { |id| Comment.new(id + 1) } + + form_for(@post) do |f| + expected = 0 + f.fields_for(:comments, @post.comments) { |cf| + assert_equal cf.index, expected + expected += 1 + } + end + end + + def test_nested_fields_for_index_method_with_child_index_option_override_on_a_nested_attributes_collection_association + @post.comments = [] + + form_for(@post) do |f| + f.fields_for(:comments, Comment.new(321), :child_index => 'abc') { |cf| + assert_equal cf.index, 'abc' + } + end + end + def test_nested_fields_uses_unique_indices_for_different_collection_associations @post.comments = [Comment.new(321)] @post.tags = [Tag.new(123), Tag.new(456)] @@ -1546,17 +2035,17 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' + - '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #321" />' + + '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" type="text" value="commentrelevance #314" />' + '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' + - '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' + - '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' + + '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" type="text" value="tag #123" />' + + '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" type="text" value="tagrelevance #3141" />' + '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' + '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' + - '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' + - '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' + + '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" type="text" value="tag #456" />' + + '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" type="text" value="tagrelevance #31415" />' + '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' + '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' end @@ -1564,6 +2053,22 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_nested_fields_for_with_hash_like_model + @author = HashBackedAuthor.new + + form_for(@post) do |f| + concat f.fields_for(:author, @author) { |af| + concat af.text_field(:name) + } + end + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="hash backed author" />' + end + + assert_dom_equal expected, output_buffer + end + def test_fields_for output_buffer = fields_for(:post, @post) do |f| concat f.text_field(:title) @@ -1572,8 +2077,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" @@ -1588,8 +2093,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" + - "<textarea name='post[123][body]' id='post_123_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[123][title]' type='text' id='post_123_title' value='Hello World' />" + + "<textarea name='post[123][body]' id='post_123_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[123][secret]' type='hidden' value='0' />" + "<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />" @@ -1604,8 +2109,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[][title]' size='30' type='text' id='post__title' value='Hello World' />" + - "<textarea name='post[][body]' id='post__body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[][title]' type='text' id='post__title' value='Hello World' />" + + "<textarea name='post[][body]' id='post__body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[][secret]' type='hidden' value='0' />" + "<input name='post[][secret]' checked='checked' type='checkbox' id='post__secret' value='1' />" @@ -1620,8 +2125,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[abc][title]' size='30' type='text' id='post_abc_title' value='Hello World' />" + - "<textarea name='post[abc][body]' id='post_abc_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[abc][title]' type='text' id='post_abc_title' value='Hello World' />" + + "<textarea name='post[abc][body]' id='post_abc_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[abc][secret]' type='hidden' value='0' />" + "<input name='post[abc][secret]' checked='checked' type='checkbox' id='post_abc_secret' value='1' />" @@ -1636,8 +2141,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" @@ -1652,8 +2157,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" @@ -1667,7 +2172,7 @@ class FormHelperTest < ActionView::TestCase end assert_dom_equal "<label for=\"author_post_title\">Title</label>" + - "<input name='author[post][title]' size='30' type='text' id='author_post_title' value='Hello World' />", + "<input name='author[post][title]' type='text' id='author_post_title' value='Hello World' />", output_buffer end @@ -1678,7 +2183,7 @@ class FormHelperTest < ActionView::TestCase end assert_dom_equal "<label for=\"author_post_1_title\">Title</label>" + - "<input name='author[post][1][title]' size='30' type='text' id='author_post_1_title' value='Hello World' />", + "<input name='author[post][1][title]' type='text' id='author_post_1_title' value='Hello World' />", output_buffer end @@ -1696,9 +2201,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'create-post', 'post_edit', :method => 'put') do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form('/posts/123', 'create-post', 'edit_post', :method => 'patch') do + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='parent_post[secret]' type='hidden' value='0' />" + "<input name='parent_post[secret]' checked='checked' type='checkbox' id='parent_post_secret' value='1' />" end @@ -1716,10 +2221,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'create-post', 'post_edit', :method => 'put') do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + - "<input name='post[comment][name]' type='text' id='post_comment_name' value='new comment' size='30' />" + expected = whole_form('/posts/123', 'create-post', 'edit_post', :method => 'patch') do + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + + "<input name='post[comment][name]' type='text' id='post_comment_name' value='new comment' />" end assert_dom_equal expected, output_buffer @@ -1732,8 +2237,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[category][name]' type='text' size='30' id='post_category_name' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[category][name]' type='text' id='post_category_name' />" end assert_dom_equal expected, output_buffer @@ -1756,60 +2261,46 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + - "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea><br/>" + "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" end assert_dom_equal expected, output_buffer end - def snowman(method = nil) - txt = %{<div style="margin:0;padding:0;display:inline">} - txt << %{<input name="utf8" type="hidden" value="✓" />} - if method && !method.to_s.in?(['get', 'post']) - txt << %{<input name="_method" type="hidden" value="#{method}" />} - end - txt << %{</div>} - end - - def form_text(action = "/", id = nil, html_class = nil, remote = nil, multipart = nil, method = nil) - txt = %{<form accept-charset="UTF-8" action="#{action}"} - txt << %{ enctype="multipart/form-data"} if multipart - txt << %{ data-remote="true"} if remote - txt << %{ class="#{html_class}"} if html_class - txt << %{ id="#{id}"} if id - method = method.to_s == "get" ? "get" : "post" - txt << %{ method="#{method}">} - end + def test_default_form_builder + old_default_form_builder, ActionView::Base.default_form_builder = + ActionView::Base.default_form_builder, LabelledFormBuilder - def whole_form(action = "/", id = nil, html_class = nil, options = nil) - contents = block_given? ? yield : "" + form_for(@post) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end - if options.is_a?(Hash) - method, remote, multipart = options.values_at(:method, :remote, :multipart) - else - method = options + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea><br/>" + + "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" end - form_text(action, id, html_class, remote, multipart, method) + snowman(method) + contents + "</form>" + assert_dom_equal expected, output_buffer + ensure + ActionView::Base.default_form_builder = old_default_form_builder end - def test_default_form_builder + def test_lazy_loading_default_form_builder old_default_form_builder, ActionView::Base.default_form_builder = - ActionView::Base.default_form_builder, LabelledFormBuilder + ActionView::Base.default_form_builder, "FormHelperTest::LabelledFormBuilder" form_for(@post) do |f| concat f.text_field(:title) - concat f.text_area(:body) - concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + - "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + - "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" end assert_dom_equal expected, output_buffer @@ -1825,8 +2316,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + - "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea><br/>" + "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" assert_dom_equal expected, output_buffer @@ -1858,6 +2349,17 @@ class FormHelperTest < ActionView::TestCase assert_equal LabelledFormBuilder, klass end + def test_form_for_with_labelled_builder_path + path = nil + + form_for(@post, :builder => LabelledFormBuilder) do |f| + path = f.to_partial_path + '' + end + + assert_equal 'labelled_form', path + end + class LabelledFormBuilderSubclass < LabelledFormBuilder; end def test_form_for_with_labelled_builder_with_nested_fields_for_with_custom_builder @@ -1875,7 +2377,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_html_options_adds_options_to_form_tag form_for(@post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end - expected = whole_form("/posts/123", "some_form", "some_class", 'put') + expected = whole_form("/posts/123", "some_form", "some_class", 'patch') assert_dom_equal expected, output_buffer end @@ -1883,7 +2385,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_string_url_option form_for(@post, :url => 'http://www.otherdomain.com') do |f| end - assert_equal whole_form("http://www.otherdomain.com", 'edit_post_123', 'edit_post', 'put'), output_buffer + assert_equal whole_form("http://www.otherdomain.com", 'edit_post_123', 'edit_post', 'patch'), output_buffer end def test_form_for_with_hash_url_option @@ -1896,21 +2398,21 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_record_url_option form_for(@post, :url => @post) do |f| end - expected = whole_form("/posts/123", 'edit_post_123', 'edit_post', 'put') + expected = whole_form("/posts/123", 'edit_post_123', 'edit_post', 'patch') assert_equal expected, output_buffer end def test_form_for_with_existing_object form_for(@post) do |f| end - expected = whole_form("/posts/123", "edit_post_123", "edit_post", "put") + expected = whole_form("/posts/123", "edit_post_123", "edit_post", 'patch') assert_equal expected, output_buffer end def test_form_for_with_new_object post = Post.new post.persisted = false - def post.id() nil end + def post.to_key; nil; end form_for(post) do |f| end @@ -1922,7 +2424,7 @@ class FormHelperTest < ActionView::TestCase @comment.save form_for([@post, @comment]) {} - expected = whole_form(post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") + expected = whole_form(post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", 'patch') assert_dom_equal expected, output_buffer end @@ -1937,7 +2439,7 @@ class FormHelperTest < ActionView::TestCase @comment.save form_for([:admin, @post, @comment]) {} - expected = whole_form(admin_post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") + expected = whole_form(admin_post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", 'patch') assert_dom_equal expected, output_buffer end @@ -1951,18 +2453,67 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_existing_object_and_custom_url form_for(@post, :url => "/super_posts") do |f| end - expected = whole_form("/super_posts", "edit_post_123", "edit_post", "put") + expected = whole_form("/super_posts", "edit_post_123", "edit_post", 'patch') assert_equal expected, output_buffer end + def test_form_for_with_default_method_as_patch + form_for(@post) {} + expected = whole_form("/posts/123", "edit_post_123", "edit_post", "patch") + assert_dom_equal expected, output_buffer + end + def test_fields_for_returns_block_result output = fields_for(Post.new) { |f| "fields" } assert_equal "fields", output end + def test_form_builder_block_argument_deprecation + builder_class = Class.new(ActionView::Helpers::FormBuilder) do + def initialize(object_name, object, template, options, block) + super + end + end + + assert_deprecated(/Giving a block to FormBuilder is deprecated and has no effect anymore/) do + builder_class.new(:foo, nil, nil, {}, proc {}) + end + end + protected - def protect_against_forgery? - false + + def hidden_fields(method = nil) + txt = %{<div style="margin:0;padding:0;display:inline">} + txt << %{<input name="utf8" type="hidden" value="✓" />} + if method && !method.to_s.in?(['get', 'post']) + txt << %{<input name="_method" type="hidden" value="#{method}" />} + end + txt << %{</div>} + end + + def form_text(action = "/", id = nil, html_class = nil, remote = nil, multipart = nil, method = nil) + txt = %{<form accept-charset="UTF-8" action="#{action}"} + txt << %{ enctype="multipart/form-data"} if multipart + txt << %{ data-remote="true"} if remote + txt << %{ class="#{html_class}"} if html_class + txt << %{ id="#{id}"} if id + method = method.to_s == "get" ? "get" : "post" + txt << %{ method="#{method}">} + end + + def whole_form(action = "/", id = nil, html_class = nil, options = nil) + contents = block_given? ? yield : "" + + if options.is_a?(Hash) + method, remote, multipart = options.values_at(:method, :remote, :multipart) + else + method = options end + form_text(action, id, html_class, remote, multipart, method) + hidden_fields(method) + contents + "</form>" + end + + def protect_against_forgery? + false + end end diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index b92e1d9890..2322fb0406 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -87,6 +87,20 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_collection_options_with_proc_for_value_method + assert_dom_equal( + "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>", + options_from_collection_for_select(dummy_posts, lambda { |p| p.author_name }, "title") + ) + end + + def test_collection_options_with_proc_for_text_method + assert_dom_equal( + "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>", + options_from_collection_for_select(dummy_posts, "author_name", lambda { |p| p.title }) + ) + end + def test_string_options_for_select options = "<option value=\"Denmark\">Denmark</option><option value=\"USA\">USA</option><option value=\"Sweden\">Sweden</option>" assert_dom_equal( @@ -144,6 +158,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_range_options_for_select + assert_dom_equal( + "<option value=\"1\">1</option>\n<option value=\"2\">2</option>\n<option value=\"3\">3</option>", + options_for_select(1..3) + ) + end + def test_array_options_for_string_include_in_other_string_bug_fix assert_dom_equal( "<option value=\"ruby\">ruby</option>\n<option value=\"rubyonrails\" selected=\"selected\">rubyonrails</option>", @@ -161,16 +182,16 @@ class FormOptionsHelperTest < ActionView::TestCase def test_hash_options_for_select assert_dom_equal( - "<option value=\"<Kroner>\"><DKR></option>\n<option value=\"Dollar\">$</option>", - options_for_select("$" => "Dollar", "<DKR>" => "<Kroner>").split("\n").sort.join("\n") + "<option value=\"Dollar\">$</option>\n<option value=\"<Kroner>\"><DKR></option>", + options_for_select("$" => "Dollar", "<DKR>" => "<Kroner>").split("\n").join("\n") ) assert_dom_equal( - "<option value=\"<Kroner>\"><DKR></option>\n<option value=\"Dollar\" selected=\"selected\">$</option>", - options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }, "Dollar").split("\n").sort.join("\n") + "<option value=\"Dollar\" selected=\"selected\">$</option>\n<option value=\"<Kroner>\"><DKR></option>", + options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }, "Dollar").split("\n").join("\n") ) assert_dom_equal( - "<option value=\"<Kroner>\" selected=\"selected\"><DKR></option>\n<option value=\"Dollar\" selected=\"selected\">$</option>", - options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }, [ "Dollar", "<Kroner>" ]).split("\n").sort.join("\n") + "<option value=\"Dollar\" selected=\"selected\">$</option>\n<option value=\"<Kroner>\" selected=\"selected\"><DKR></option>", + options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }, [ "Dollar", "<Kroner>" ]).split("\n").join("\n") ) end @@ -275,10 +296,34 @@ class FormOptionsHelperTest < ActionView::TestCase ) end - def test_grouped_options_for_select_with_selected_and_prompt + def test_grouped_options_for_select_with_optional_divider assert_dom_equal( + "<optgroup label=\"----------\"><option value=\"US\">US</option>\n<option value=\"Canada\">Canada</option></optgroup><optgroup label=\"----------\"><option value=\"GB\">GB</option>\n<option value=\"Germany\">Germany</option></optgroup>", + + grouped_options_for_select([['US',"Canada"] , ["GB", "Germany"]], nil, divider: "----------") + ) + end + + def test_grouped_options_for_select_with_selected_and_prompt_deprecated + assert_deprecated 'Passing the prompt to grouped_options_for_select as an argument is deprecated. Please use an options hash like `{ prompt: "Choose a product..." }`.' do + assert_dom_equal( "<option value=\"\">Choose a product...</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", "Choose a product...") + ) + end + end + + def test_grouped_options_for_select_with_selected_and_prompt + assert_dom_equal( + "<option value=\"\">Choose a product...</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", prompt: "Choose a product...") + ) + end + + def test_grouped_options_for_select_with_selected_and_prompt_true + assert_dom_equal( + "<option value=\"\">Please select</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", prompt: true) ) end @@ -286,10 +331,18 @@ class FormOptionsHelperTest < ActionView::TestCase assert grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]]).html_safe? end + def test_grouped_options_for_select_with_prompt_returns_html_escaped_string_deprecated + ActiveSupport::Deprecation.silence do + assert_dom_equal( + "<option value=\"\"><Choose One></option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, '<Choose One>')) + end + end + def test_grouped_options_for_select_with_prompt_returns_html_escaped_string assert_dom_equal( "<option value=\"\"><Choose One></option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", - grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, '<Choose One>')) + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, prompt: '<Choose One>')) end def test_optgroups_with_with_options_with_hash @@ -378,6 +431,49 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_without_multiple + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"></select>", + select(:post, :category, "", {}, :multiple => false) + ) + end + + def test_select_with_grouped_collection_as_nested_array + @post = Post.new + + countries_by_continent = [ + ["<Africa>", [["<South Africa>", "<sa>"], ["Somalia", "so"]]], + ["Europe", [["Denmark", "dk"], ["Ireland", "ie"]]], + ] + + assert_dom_equal( + [ + %Q{<select id="post_origin" name="post[origin]"><optgroup label="<Africa>"><option value="<sa>"><South Africa></option>}, + %Q{<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk">Denmark</option>}, + %Q{<option value="ie">Ireland</option></optgroup></select>}, + ].join("\n"), + select("post", "origin", countries_by_continent) + ) + end + + def test_select_with_grouped_collection_as_hash + @post = Post.new + + countries_by_continent = { + "<Africa>" => [["<South Africa>", "<sa>"], ["Somalia", "so"]], + "Europe" => [["Denmark", "dk"], ["Ireland", "ie"]], + } + + assert_dom_equal( + [ + %Q{<select id="post_origin" name="post[origin]"><optgroup label="<Africa>"><option value="<sa>"><South Africa></option>}, + %Q{<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk">Denmark</option>}, + %Q{<option value="ie">Ireland</option></optgroup></select>}, + ].join("\n"), + select("post", "origin", countries_by_continent) + ) + end + def test_select_with_boolean_method @post = Post.new @post.allow_comments = false @@ -445,7 +541,7 @@ class FormOptionsHelperTest < ActionView::TestCase def test_select_under_fields_for_with_string_and_given_prompt @post = Post.new - options = "<option value=\"abe\">abe</option><option value=\"mus\">mus</option><option value=\"hest\">hest</option>" + options = "<option value=\"abe\">abe</option><option value=\"mus\">mus</option><option value=\"hest\">hest</option>".html_safe output_buffer = fields_for :post, @post do |f| concat f.select(:category, options, :prompt => 'The prompt') @@ -457,6 +553,30 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_multiple_to_add_hidden_input + output_buffer = select(:post, :category, "", {}, :multiple => true) + assert_dom_equal( + "<input type=\"hidden\" name=\"post[category][]\" value=\"\"/><select multiple=\"multiple\" id=\"post_category\" name=\"post[category][]\"></select>", + output_buffer + ) + end + + def test_select_with_multiple_and_without_hidden_input + output_buffer = select(:post, :category, "", {:include_hidden => false}, :multiple => true) + assert_dom_equal( + "<select multiple=\"multiple\" id=\"post_category\" name=\"post[category][]\"></select>", + output_buffer + ) + end + + def test_select_with_multiple_and_disabled_to_add_disabled_hidden_input + output_buffer = select(:post, :category, "", {}, :multiple => true, :disabled => true) + assert_dom_equal( + "<input disabled=\"disabled\"type=\"hidden\" name=\"post[category][]\" value=\"\"/><select multiple=\"multiple\" disabled=\"disabled\" id=\"post_category\" name=\"post[category][]\"></select>", + output_buffer + ) + end + def test_select_with_blank @post = Post.new @post.category = "<mus>" @@ -528,6 +648,84 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_empty + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"\"></option>\n</select>", + select("post", "category", [], :prompt => true, :include_blank => true) + ) + end + + def test_select_with_nil + @post = Post.new + @post.category = "othervalue" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\"></option>\n<option value=\"othervalue\" selected=\"selected\">othervalue</option></select>", + select("post", "category", [nil, "othervalue"]) + ) + end + + def test_required_select + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required"><option value=""></option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true) + ) + end + + def test_required_select_with_include_blank_prompt + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required"><option value="">Select one</option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), { include_blank: "Select one" }, required: true) + ) + end + + def test_required_select_with_prompt + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required"><option value="">Select one</option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), { prompt: "Select one" }, required: true) + ) + end + + def test_required_select_display_size_equals_to_one + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required" size="1"><option value=""></option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true, size: 1) + ) + end + + def test_required_select_with_display_size_bigger_than_one + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required" size="2"><option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true, size: 2) + ) + end + + def test_required_select_with_multiple_option + assert_dom_equal( + %(<input name="post[category][]" type="hidden" value=""/><select id="post_category" multiple="multiple" name="post[category][]" required="required"><option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true, multiple: true) + ) + end + + def test_select_with_fixnum + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"\"></option>\n<option value=\"1\">1</option></select>", + select("post", "category", [1], :prompt => true, :include_blank => true) + ) + end + + def test_list_of_lists + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"\"></option>\n<option value=\"number\">Number</option>\n<option value=\"text\">Text</option>\n<option value=\"boolean\">Yes/No</option></select>", + select("post", "category", [["Number", "number"], ["Text", "text"], ["Yes/No", "boolean"]], :prompt => true, :include_blank => true) + ) + end + def test_select_with_selected_value @post = Post.new @post.category = "<mus>" @@ -549,6 +747,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_escapes_options + assert_dom_equal( + '<select id="post_title" name="post[title]"><script>alert(1)</script></select>', + select('post', 'title', '<script>alert(1)</script>') + ) + end + def test_select_with_selected_nil @post = Post.new @post.category = "<mus>" @@ -576,6 +781,15 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_range + @post = Post.new + @post.category = 0 + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"1\">1</option>\n<option value=\"2\">2</option>\n<option value=\"3\">3</option></select>", + select("post", "category", 1..3) + ) + end + def test_collection_select @post = Post.new @post.author_name = "Babe" @@ -649,11 +863,11 @@ class FormOptionsHelperTest < ActionView::TestCase ) end - def test_collection_select_with_multiple_option_appends_array_brackets + def test_collection_select_with_multiple_option_appends_array_brackets_and_hidden_input @post = Post.new @post.author_name = "Babe" - expected = "<select id=\"post_author_name\" name=\"post[author_name][]\" multiple=\"multiple\"><option value=\"\"></option>\n<option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>" + expected = "<input type=\"hidden\" name=\"post[author_name][]\" value=\"\"/><select id=\"post_author_name\" name=\"post[author_name][]\" multiple=\"multiple\"><option value=\"\"></option>\n<option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>" # Should suffix default name with []. assert_dom_equal expected, collection_select("post", "author_name", dummy_posts, "author_name", "author_name", { :include_blank => true }, :multiple => true) @@ -679,7 +893,25 @@ class FormOptionsHelperTest < ActionView::TestCase assert_dom_equal( "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\" disabled=\"disabled\">Cabe</option></select>", collection_select("post", "author_name", dummy_posts, "author_name", "author_name", :disabled => 'Cabe') - ) + ) + end + + def test_collection_select_with_proc_for_value_method + @post = Post.new + + assert_dom_equal( + "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option></select>", + collection_select("post", "author_name", dummy_posts, lambda { |p| p.author_name }, "title") + ) + end + + def test_collection_select_with_proc_for_text_method + @post = Post.new + + assert_dom_equal( + "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option></select>", + collection_select("post", "author_name", dummy_posts, "author_name", lambda { |p| p.title }) + ) end def test_time_zone_select @@ -913,36 +1145,36 @@ class FormOptionsHelperTest < ActionView::TestCase end def test_option_html_attributes_from_without_hash - assert_dom_equal( - "", + assert_equal( + {}, option_html_attributes([ 'foo', 'bar' ]) ) end def test_option_html_attributes_with_single_element_hash - assert_dom_equal( - " class=\"fancy\"", + assert_equal( + {:class => 'fancy'}, option_html_attributes([ 'foo', 'bar', { :class => 'fancy' } ]) ) end def test_option_html_attributes_with_multiple_element_hash - assert_dom_equal( - " class=\"fancy\" onclick=\"alert('Hello World');\"", + assert_equal( + {:class => 'fancy', 'onclick' => "alert('Hello World');"}, option_html_attributes([ 'foo', 'bar', { :class => 'fancy', 'onclick' => "alert('Hello World');" } ]) ) end def test_option_html_attributes_with_multiple_hashes - assert_dom_equal( - " class=\"fancy\" onclick=\"alert('Hello World');\"", + assert_equal( + {:class => 'fancy', 'onclick' => "alert('Hello World');"}, option_html_attributes([ 'foo', 'bar', { :class => 'fancy' }, { 'onclick' => "alert('Hello World');" } ]) ) end def test_option_html_attributes_with_special_characters - assert_dom_equal( - " onclick=\"alert("<code>")\"", + assert_equal( + {:onclick => "alert("<code>")"}, option_html_attributes([ 'foo', 'bar', { :onclick => %(alert("<code>")) } ]) ) end @@ -957,6 +1189,24 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_grouped_collection_select_with_selected + @post = Post.new + + assert_dom_equal( + %Q{<select id="post_origin" name="post[origin]"><optgroup label="<Africa>"><option value="<sa>"><South Africa></option>\n<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk" selected="selected">Denmark</option>\n<option value="ie">Ireland</option></optgroup></select>}, + grouped_collection_select("post", "origin", dummy_continents, :countries, :continent_name, :country_id, :country_name, :selected => 'dk') + ) + end + + def test_grouped_collection_select_with_disabled_value + @post = Post.new + + assert_dom_equal( + %Q{<select id="post_origin" name="post[origin]"><optgroup label="<Africa>"><option value="<sa>"><South Africa></option>\n<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option disabled="disabled" value="dk">Denmark</option>\n<option value="ie">Ireland</option></optgroup></select>}, + grouped_collection_select("post", "origin", dummy_continents, :countries, :continent_name, :country_id, :country_name, :disabled => 'dk') + ) + end + def test_grouped_collection_select_under_fields_for @post = Post.new @post.origin = 'dk' @@ -973,14 +1223,14 @@ class FormOptionsHelperTest < ActionView::TestCase private - def dummy_posts - [ Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), - Post.new("Babe went home", "Babe", "To a little house", "shh!"), - Post.new("Cabe went home", "Cabe", "To a little house", "shh!") ] - end + def dummy_posts + [ Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") ] + end - def dummy_continents - [ Continent.new("<Africa>", [Country.new("<sa>", "<South Africa>"), Country.new("so", "Somalia")] ), - Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) ] - end + def dummy_continents + [ Continent.new("<Africa>", [Country.new("<sa>", "<South Africa>"), Country.new("so", "Somalia")]), + Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")]) ] + end end diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index f95308b847..6574e13558 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -2,6 +2,8 @@ require 'abstract_unit' require 'active_support/core_ext/object/inclusion' class FormTagHelperTest < ActionView::TestCase + include RenderERBUtils + tests ActionView::Helpers::FormTagHelper def setup @@ -9,7 +11,7 @@ class FormTagHelperTest < ActionView::TestCase @controller = BasicController.new end - def snowman(options = {}) + def hidden_fields(options = {}) method = options[:method] txt = %{<div style="margin:0;padding:0;display:inline">} @@ -34,7 +36,7 @@ class FormTagHelperTest < ActionView::TestCase end def whole_form(action = "http://www.example.com", options = {}) - out = form_text(action, options) + snowman(options) + out = form_text(action, options) + hidden_fields(options) if block_given? out << yield << "</form>" @@ -76,6 +78,12 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal expected, actual end + def test_form_tag_with_method_patch + actual = form_tag({}, { :method => :patch }) + expected = whole_form("http://www.example.com", :method => :patch) + assert_dom_equal expected, actual + end + def test_form_tag_with_method_put actual = form_tag({}, { :method => :put }) expected = whole_form("http://www.example.com", :method => :put) @@ -104,14 +112,14 @@ class FormTagHelperTest < ActionView::TestCase end def test_form_tag_with_block_in_erb - output_buffer = form_tag("http://www.example.com") { concat "Hello world!" } + output_buffer = render_erb("<%= form_tag('http://www.example.com') do %>Hello world!<% end %>") expected = whole_form { "Hello world!" } assert_dom_equal expected, output_buffer end def test_form_tag_with_block_and_method_in_erb - output_buffer = form_tag("http://www.example.com", :method => :put) { concat "Hello world!" } + output_buffer = render_erb("<%= form_tag('http://www.example.com', :method => :put) do %>Hello world!<% end %>") expected = whole_form("http://www.example.com", :method => "put") do "Hello world!" @@ -214,19 +222,19 @@ class FormTagHelperTest < ActionView::TestCase def test_text_area_tag_size_string actual = text_area_tag "body", "hello world", "size" => "20x40" - expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\nhello world</textarea>) assert_dom_equal expected, actual end def test_text_area_tag_size_symbol actual = text_area_tag "body", "hello world", :size => "20x40" - expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\nhello world</textarea>) assert_dom_equal expected, actual end def test_text_area_tag_should_disregard_size_if_its_given_as_an_integer actual = text_area_tag "body", "hello world", :size => 20 - expected = %(<textarea id="body" name="body">hello world</textarea>) + expected = %(<textarea id="body" name="body">\nhello world</textarea>) assert_dom_equal expected, actual end @@ -237,19 +245,19 @@ class FormTagHelperTest < ActionView::TestCase def test_text_area_tag_escape_content actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40" - expected = %(<textarea cols="20" id="body" name="body" rows="40"><b>hello world</b></textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\n<b>hello world</b></textarea>) assert_dom_equal expected, actual end def test_text_area_tag_unescaped_content actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40", :escape => false - expected = %(<textarea cols="20" id="body" name="body" rows="40"><b>hello world</b></textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\n<b>hello world</b></textarea>) assert_dom_equal expected, actual end def test_text_area_tag_unescaped_nil_content actual = text_area_tag "body", nil, :escape => false - expected = %(<textarea id="body" name="body"></textarea>) + expected = %(<textarea id="body" name="body">\n</textarea>) assert_dom_equal expected, actual end @@ -367,14 +375,7 @@ class FormTagHelperTest < ActionView::TestCase def test_submit_tag assert_dom_equal( %(<input name='commit' data-disable-with="Saving..." onclick="alert('hello!')" type="submit" value="Save" />), - submit_tag("Save", :disable_with => "Saving...", :onclick => "alert('hello!')") - ) - end - - def test_submit_tag_with_no_onclick_options - assert_dom_equal( - %(<input name='commit' data-disable-with="Saving..." type="submit" value="Save" />), - submit_tag("Save", :disable_with => "Saving...") + submit_tag("Save", 'data-disable-with' => "Saving...", :onclick => "alert('hello!')") ) end @@ -385,13 +386,6 @@ class FormTagHelperTest < ActionView::TestCase ) end - def test_submit_tag_with_confirmation_and_with_disable_with - assert_dom_equal( - %(<input name="commit" data-disable-with="Saving..." data-confirm="Are you sure?" type="submit" value="Save" />), - submit_tag("Save", :disable_with => "Saving...", :confirm => "Are you sure?") - ) - end - def test_button_tag assert_dom_equal( %(<button name="button" type="submit">Button</button>), @@ -455,11 +449,21 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal(expected, search_field_tag("query")) end - def telephone_field_tag + def test_telephone_field_tag expected = %{<input id="cell" name="cell" type="tel" />} assert_dom_equal(expected, telephone_field_tag("cell")) end + def test_date_field_tag + expected = %{<input id="cell" name="cell" type="date" />} + assert_dom_equal(expected, date_field_tag("cell")) + end + + def test_time_field_tag + expected = %{<input id="cell" name="cell" type="time" />} + assert_dom_equal(expected, time_field_tag("cell")) + end + def test_url_field_tag expected = %{<input id="homepage" name="homepage" type="url" />} assert_dom_equal(expected, url_field_tag("homepage")) @@ -480,30 +484,66 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal(expected, range_field_tag("volume", nil, :in => 0..11, :step => 0.1)) end - def test_pass - assert_equal 1, 1 - end - def test_field_set_tag_in_erb - output_buffer = field_set_tag("Your details") { concat "Hello world!" } + output_buffer = render_erb("<%= field_set_tag('Your details') do %>Hello world!<% end %>") expected = %(<fieldset><legend>Your details</legend>Hello world!</fieldset>) assert_dom_equal expected, output_buffer - output_buffer = field_set_tag { concat "Hello world!" } + output_buffer = render_erb("<%= field_set_tag do %>Hello world!<% end %>") expected = %(<fieldset>Hello world!</fieldset>) assert_dom_equal expected, output_buffer - output_buffer = field_set_tag('') { concat "Hello world!" } + output_buffer = render_erb("<%= field_set_tag('') do %>Hello world!<% end %>") expected = %(<fieldset>Hello world!</fieldset>) assert_dom_equal expected, output_buffer - output_buffer = field_set_tag('', :class => 'format') { concat "Hello world!" } + output_buffer = render_erb("<%= field_set_tag('', :class => 'format') do %>Hello world!<% end %>") expected = %(<fieldset class="format">Hello world!</fieldset>) assert_dom_equal expected, output_buffer + + output_buffer = render_erb("<%= field_set_tag %>") + + expected = %(<fieldset></fieldset>) + assert_dom_equal expected, output_buffer + + output_buffer = render_erb("<%= field_set_tag('You legend!') %>") + + expected = %(<fieldset><legend>You legend!</legend></fieldset>) + assert_dom_equal expected, output_buffer + end + + def test_text_area_tag_options_symbolize_keys_side_effects + options = { :option => "random_option" } + text_area_tag "body", "hello world", options + assert_equal options, { :option => "random_option" } + end + + def test_submit_tag_options_symbolize_keys_side_effects + options = { :option => "random_option" } + submit_tag "submit value", options + assert_equal options, { :option => "random_option" } + end + + def test_button_tag_options_symbolize_keys_side_effects + options = { :option => "random_option" } + button_tag "button value", options + assert_equal options, { :option => "random_option" } + end + + def test_image_submit_tag_options_symbolize_keys_side_effects + options = { :option => "random_option" } + image_submit_tag "submit source", options + assert_equal options, { :option => "random_option" } + end + + def test_image_label_tag_options_symbolize_keys_side_effects + options = { :option => "random_option" } + label_tag "submit source", "title", options + assert_equal options, { :option => "random_option" } end def protect_against_forgery? diff --git a/actionpack/test/template/html-scanner/cdata_node_test.rb b/actionpack/test/template/html-scanner/cdata_node_test.rb index 1822cc565a..9b58174641 100644 --- a/actionpack/test/template/html-scanner/cdata_node_test.rb +++ b/actionpack/test/template/html-scanner/cdata_node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class CDATANodeTest < Test::Unit::TestCase +class CDATANodeTest < ActiveSupport::TestCase def setup @node = HTML::CDATA.new(nil, 0, 0, "<p>howdy</p>") end diff --git a/actionpack/test/template/html-scanner/document_test.rb b/actionpack/test/template/html-scanner/document_test.rb index ddfb351595..17f045d549 100644 --- a/actionpack/test/template/html-scanner/document_test.rb +++ b/actionpack/test/template/html-scanner/document_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class DocumentTest < Test::Unit::TestCase +class DocumentTest < ActiveSupport::TestCase def test_handle_doctype doc = nil assert_nothing_raised do @@ -123,7 +123,7 @@ HTML def test_parse_invalid_document assert_nothing_raised do - doc = HTML::Document.new("<html> + HTML::Document.new("<html> <table> <tr> <td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td> @@ -135,7 +135,7 @@ HTML def test_invalid_document_raises_exception_when_strict assert_raise RuntimeError do - doc = HTML::Document.new("<html> + HTML::Document.new("<html> <table> <tr> <td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td> diff --git a/actionpack/test/template/html-scanner/node_test.rb b/actionpack/test/template/html-scanner/node_test.rb index f4b9b198e8..5b5d092036 100644 --- a/actionpack/test/template/html-scanner/node_test.rb +++ b/actionpack/test/template/html-scanner/node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class NodeTest < Test::Unit::TestCase +class NodeTest < ActiveSupport::TestCase class MockNode def initialize(matched, value) diff --git a/actionpack/test/template/html-scanner/sanitizer_test.rb b/actionpack/test/template/html-scanner/sanitizer_test.rb index 678cb9eeeb..324caef224 100644 --- a/actionpack/test/template/html-scanner/sanitizer_test.rb +++ b/actionpack/test/template/html-scanner/sanitizer_test.rb @@ -5,6 +5,13 @@ class SanitizerTest < ActionController::TestCase @sanitizer = nil # used by assert_sanitizer end + def test_strip_tags_with_quote + sanitizer = HTML::FullSanitizer.new + string = '<" <img src="trollface.gif" onload="alert(1)"> hi' + + assert_equal ' hi', sanitizer.sanitize(string) + end + def test_strip_tags sanitizer = HTML::FullSanitizer.new assert_equal("<<<bad html", sanitizer.sanitize("<<<bad html")) @@ -49,7 +56,6 @@ class SanitizerTest < ActionController::TestCase assert_sanitized "a b c<script language=\"Javascript\">blah blah blah</script>d e f", "a b cd e f" end - # TODO: Clean up 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>} @@ -119,6 +125,24 @@ class SanitizerTest < ActionController::TestCase assert_equal(text, sanitizer.sanitize(text, :attributes => ['foo'])) end + def test_should_raise_argument_error_if_tags_is_not_enumerable + sanitizer = HTML::WhiteListSanitizer.new + e = assert_raise(ArgumentError) do + sanitizer.sanitize('', :tags => 'foo') + end + + assert_equal "You should pass :tags as an Enumerable", e.message + end + + def test_should_raise_argument_error_if_attributes_is_not_enumerable + sanitizer = HTML::WhiteListSanitizer.new + e = assert_raise(ArgumentError) do + sanitizer.sanitize('', :attributes => 'foo') + end + + assert_equal "You should pass :attributes as an Enumerable", e.message + 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}>) @@ -131,7 +155,7 @@ class SanitizerTest < ActionController::TestCase assert sanitizer.send(:contains_bad_protocols?, 'src', "#{proto}://bad") end end - + def test_should_accept_good_protocols_ignoring_case sanitizer = HTML::WhiteListSanitizer.new HTML::WhiteListSanitizer.allowed_protocols.each do |proto| @@ -139,6 +163,13 @@ class SanitizerTest < ActionController::TestCase end end + def test_should_accept_good_protocols_ignoring_space + 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_accept_good_protocols sanitizer = HTML::WhiteListSanitizer.new HTML::WhiteListSanitizer.allowed_protocols.each do |proto| @@ -201,7 +232,6 @@ class SanitizerTest < ActionController::TestCase assert_sanitized img_hack, "<img>" end - # TODO: Clean up def test_should_sanitize_attributes assert_sanitized %(<SPAN title="'><script>alert()</script>">blah</SPAN>), %(<span title="'><script>alert()</script>">blah</span>) end diff --git a/actionpack/test/template/html-scanner/tag_node_test.rb b/actionpack/test/template/html-scanner/tag_node_test.rb index 0d87f1bd42..a29d2d43d7 100644 --- a/actionpack/test/template/html-scanner/tag_node_test.rb +++ b/actionpack/test/template/html-scanner/tag_node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class TagNodeTest < Test::Unit::TestCase +class TagNodeTest < ActiveSupport::TestCase def test_open_without_attributes node = tag("<tag>") assert_equal "tag", node.name @@ -55,7 +55,12 @@ class TagNodeTest < Test::Unit::TestCase 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 + node = node.to_s + assert node.include?('a') + assert node.include?('b="c"') + assert node.include?('d="f"') + assert node.include?('g="h') + assert node.include?('i') end def test_tag diff --git a/actionpack/test/template/html-scanner/text_node_test.rb b/actionpack/test/template/html-scanner/text_node_test.rb index 6f61253ffa..cbcb9e78f0 100644 --- a/actionpack/test/template/html-scanner/text_node_test.rb +++ b/actionpack/test/template/html-scanner/text_node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class TextNodeTest < Test::Unit::TestCase +class TextNodeTest < ActiveSupport::TestCase def setup @node = HTML::Text.new(nil, 0, 0, "hello, howdy, aloha, annyeong") end diff --git a/actionpack/test/template/html-scanner/tokenizer_test.rb b/actionpack/test/template/html-scanner/tokenizer_test.rb index bf45a7c2e3..1d59de23b6 100644 --- a/actionpack/test/template/html-scanner/tokenizer_test.rb +++ b/actionpack/test/template/html-scanner/tokenizer_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class TokenizerTest < Test::Unit::TestCase +class TokenizerTest < ActiveSupport::TestCase def test_blank tokenize "" diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 538e0e9874..fe7607ee26 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -27,50 +27,32 @@ class JavaScriptHelperTest < ActionView::TestCase assert_equal %(This \\"thing\\" is really\\n netos\\'), escape_javascript(%(This "thing" is really\n netos')) assert_equal %(backslash\\\\test), escape_javascript( %(backslash\\test) ) assert_equal %(dont <\\/close> tags), escape_javascript(%(dont </close> tags)) - assert_equal %(dont <\\/close> tags), j(%(dont </close> tags)) - end - - def test_button_to_function - assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />), - button_to_function("Greeting", "alert('Hello world!')") - end - - def test_button_to_function_with_onclick - assert_dom_equal "<input onclick=\"alert('Goodbye World :('); alert('Hello world!');\" type=\"button\" value=\"Greeting\" />", - button_to_function("Greeting", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')") - end + assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\250 newline).force_encoding('UTF-8').encode!) + assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\251 newline).force_encoding('UTF-8').encode!) - def test_button_to_function_without_function - assert_dom_equal "<input onclick=\";\" type=\"button\" value=\"Greeting\" />", - button_to_function("Greeting") - end - - def test_link_to_function - assert_dom_equal %(<a href="#" onclick="alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')") - end - - def test_link_to_function_with_existing_onclick - assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')") + assert_equal %(dont <\\/close> tags), j(%(dont </close> tags)) end - def test_function_with_href - assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') + def test_escape_javascript_with_safebuffer + given = %('quoted' "double-quoted" new-line:\n </closed>) + expect = %(\\'quoted\\' \\"double-quoted\\" new-line:\\n <\\/closed>) + assert_equal expect, escape_javascript(given) + assert_equal expect, escape_javascript(ActiveSupport::SafeBuffer.new(given)) + assert_instance_of String, escape_javascript(given) + assert_instance_of ActiveSupport::SafeBuffer, escape_javascript(ActiveSupport::SafeBuffer.new(given)) end def test_javascript_tag self.output_buffer = 'foo' - assert_dom_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", + assert_dom_equal "<script>\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", javascript_tag("alert('hello')") assert_equal 'foo', output_buffer, 'javascript_tag without a block should not concat to output_buffer' end def test_javascript_tag_with_options - assert_dom_equal "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", + assert_dom_equal "<script id=\"the_js_tag\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", javascript_tag("alert('hello')", :id => "the_js_tag") end diff --git a/actionpack/test/template/log_subscriber_test.rb b/actionpack/test/template/log_subscriber_test.rb index 50e1cccd3b..1713ce935c 100644 --- a/actionpack/test/template/log_subscriber_test.rb +++ b/actionpack/test/template/log_subscriber_test.rb @@ -8,7 +8,6 @@ class AVLogSubscriberTest < ActiveSupport::TestCase def setup super - @old_logger = ActionController::Base.logger @controller = Object.new @controller.stubs(:_prefixes).returns(%w(test)) @view = ActionView::Base.new(ActionController::Base.view_paths, {}, @controller) @@ -19,15 +18,14 @@ class AVLogSubscriberTest < ActiveSupport::TestCase def teardown super ActiveSupport::LogSubscriber.log_subscribers.clear - ActionController::Base.logger = @old_logger end def set_logger(logger) - ActionController::Base.logger = logger + ActionView::Base.logger = logger end def test_render_file_template - @view.render(:file => "test/hello_world.erb") + @view.render(:file => "test/hello_world") wait assert_equal 1, @logger.logged(:info).size diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index 47b70f05ab..96b14a0acd 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -1,20 +1,14 @@ require "abstract_unit" require "abstract_controller/rendering" -ActionView::LookupContext::DetailsKey.class_eval do - def self.details_keys - @details_keys - end -end - class LookupContextTest < ActiveSupport::TestCase def setup @lookup_context = ActionView::LookupContext.new(FIXTURE_LOAD_PATH, {}) + ActionView::LookupContext::DetailsKey.clear end def teardown I18n.locale = :en - ActionView::LookupContext::DetailsKey.details_keys.clear end test "process view paths on initialization" do @@ -31,16 +25,6 @@ class LookupContextTest < ActiveSupport::TestCase assert @lookup_context.formats.frozen? end - test "allows me to change some details to execute an specific block of code" do - formats = Mime::SET - @lookup_context.update_details(:locale => :pt) do - assert_equal formats, @lookup_context.formats - assert_equal :pt, @lookup_context.locale - end - assert_equal formats, @lookup_context.formats - assert_equal :en, @lookup_context.locale - end - test "provides getters and setters for formats" do @lookup_context.formats = [:html] assert_equal [:html], @lookup_context.formats @@ -94,9 +78,9 @@ class LookupContextTest < ActiveSupport::TestCase end test "found templates respects given formats if one cannot be found from template or handler" do - ActionView::Template::Handlers::ERB.expects(:default_format).returns(nil) + ActionView::Template::Handlers::Builder.expects(:default_format).returns(nil) @lookup_context.formats = [:text] - template = @lookup_context.find("hello_world", %w(test)) + template = @lookup_context.find("hello", %w(test)) assert_equal [:text], template.formats end diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb index 5df09b4d3b..d6e9de9555 100644 --- a/actionpack/test/template/number_helper_i18n_test.rb +++ b/actionpack/test/template/number_helper_i18n_test.rb @@ -53,6 +53,13 @@ class NumberHelperTest < ActionView::TestCase assert_equal("-$10.00", number_to_currency(-10)) end end + + def test_number_to_currency_without_currency_negative_format + clean_i18n do + I18n.backend.store_translations 'ts', :number => { :currency => { :format => { :unit => '@', :format => '%n %u' } } } + assert_equal("-10.00 @", number_to_currency(-10, :locale => 'ts')) + end + end def test_number_with_i18n_precision #Delimiter was set to "" diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 63b92aadf4..14ca6d9879 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -19,15 +19,6 @@ class NumberHelperTest < ActionView::TestCase gigabytes(number) * 1024 end - def silence_deprecation_warnings - @old_deprecatios_silenced = ActiveSupport::Deprecation.silenced - ActiveSupport::Deprecation.silenced = true - end - - def restore_deprecation_warnings - ActiveSupport::Deprecation.silenced = @old_deprecatios_silenced - end - def test_number_to_phone assert_equal("555-1234", number_to_phone(5551234)) assert_equal("800-555-1212", number_to_phone(8005551212)) @@ -36,6 +27,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal("800 555 1212", number_to_phone(8005551212, {:delimiter => " "})) assert_equal("(800) 555-1212 x 123", number_to_phone(8005551212, {:area_code => true, :extension => 123})) assert_equal("800-555-1212", number_to_phone(8005551212, :extension => " ")) + assert_equal("555.1212", number_to_phone(5551212, :delimiter => '.')) assert_equal("800-555-1212", number_to_phone("8005551212")) assert_equal("+1-800-555-1212", number_to_phone(8005551212, :country_code => 1)) assert_equal("+18005551212", number_to_phone(8005551212, :country_code => 1, :delimiter => '')) @@ -65,6 +57,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal("1000.000%", number_to_percentage("1000")) assert_equal("123.4%", number_to_percentage(123.400, :precision => 3, :strip_insignificant_zeros => true)) assert_equal("1.000,000%", number_to_percentage(1000, :delimiter => '.', :separator => ',')) + assert_equal("1000.000 %", number_to_percentage(1000, :format => "%n %")) end def test_number_with_delimiter @@ -85,6 +78,8 @@ class NumberHelperTest < ActionView::TestCase assert_equal '12,345,678-05', number_with_delimiter(12345678.05, :separator => '-') assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :separator => ',', :delimiter => '.') assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :delimiter => '.', :separator => ',') + assert_equal '1<script></script>01', number_with_delimiter(1.01, :separator => "<script></script>") + assert_equal '1<script></script>000', number_with_delimiter(1000, :delimiter => "<script></script>") end def test_number_with_precision @@ -103,6 +98,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal("0.001", number_with_precision(0.00111, :precision => 3)) assert_equal("10.00", number_with_precision(9.995, :precision => 2)) assert_equal("11.00", number_with_precision(10.995, :precision => 2)) + assert_equal("0.00", number_with_precision(-0.001, :precision => 2)) end def test_number_with_precision_with_custom_delimiter_and_separator @@ -275,6 +271,31 @@ class NumberHelperTest < ActionView::TestCase assert_nil number_to_human(nil) end + def test_number_helpers_do_not_mutate_options_hash + options = { 'raise' => true } + + number_to_phone(1, options) + assert_equal({ 'raise' => true }, options) + + number_to_currency(1, options) + assert_equal({ 'raise' => true }, options) + + number_to_percentage(1, options) + assert_equal({ 'raise' => true }, options) + + number_with_delimiter(1, options) + assert_equal({ 'raise' => true }, options) + + number_with_precision(1, options) + assert_equal({ 'raise' => true }, options) + + number_to_human_size(1, options) + assert_equal({ 'raise' => true }, options) + + number_to_human(1, options) + assert_equal({ 'raise' => true }, options) + end + def test_number_helpers_should_return_non_numeric_param_unchanged assert_equal("+1-x x 123", number_to_phone("x", :country_code => 1, :extension => 123)) assert_equal("x", number_to_phone("x")) @@ -292,33 +313,40 @@ class NumberHelperTest < ActionView::TestCase assert number_to_human(1).html_safe? assert !number_to_human("<script></script>").html_safe? assert number_to_human("asdf".html_safe).html_safe? + assert number_to_human("1".html_safe).html_safe? assert number_to_human_size(1).html_safe? assert number_to_human_size(1000000).html_safe? assert !number_to_human_size("<script></script>").html_safe? assert number_to_human_size("asdf".html_safe).html_safe? + assert number_to_human_size("1".html_safe).html_safe? assert number_with_precision(1, :strip_insignificant_zeros => false).html_safe? assert number_with_precision(1, :strip_insignificant_zeros => true).html_safe? assert !number_with_precision("<script></script>").html_safe? assert number_with_precision("asdf".html_safe).html_safe? + assert number_with_precision("1".html_safe).html_safe? assert number_to_currency(1).html_safe? assert !number_to_currency("<script></script>").html_safe? assert number_to_currency("asdf".html_safe).html_safe? + assert number_to_currency("1".html_safe).html_safe? assert number_to_percentage(1).html_safe? assert !number_to_percentage("<script></script>").html_safe? assert number_to_percentage("asdf".html_safe).html_safe? + assert number_to_percentage("1".html_safe).html_safe? assert number_to_phone(1).html_safe? assert_equal "<script></script>", number_to_phone("<script></script>") assert number_to_phone("<script></script>").html_safe? assert number_to_phone("asdf".html_safe).html_safe? + assert number_to_phone("1".html_safe).html_safe? assert number_with_delimiter(1).html_safe? assert !number_with_delimiter("<script></script>").html_safe? assert number_with_delimiter("asdf".html_safe).html_safe? + assert number_with_delimiter("1".html_safe).html_safe? end def test_number_helpers_should_raise_error_if_invalid_when_specified diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb index bd49a11af1..eb0df3d1ab 100644 --- a/actionpack/test/template/output_buffer_test.rb +++ b/actionpack/test/template/output_buffer_test.rb @@ -39,15 +39,13 @@ class OutputBufferTest < ActionController::TestCase assert_equal ['foo', 'bar'], body_parts end - if '1.9'.respond_to?(:force_encoding) - test 'flushing preserves output buffer encoding' do - original_buffer = ' '.force_encoding(Encoding::EUC_JP) - @vc.output_buffer = original_buffer - @vc.flush_output_buffer - assert_equal ['foo', original_buffer], body_parts - assert_not_equal original_buffer, output_buffer - assert_equal Encoding::EUC_JP, output_buffer.encoding - end + test 'flushing preserves output buffer encoding' do + original_buffer = ' '.force_encoding(Encoding::EUC_JP) + @vc.output_buffer = original_buffer + @vc.flush_output_buffer + assert_equal ['foo', original_buffer], body_parts + assert_not_equal original_buffer, output_buffer + assert_equal Encoding::EUC_JP, output_buffer.encoding end protected diff --git a/actionpack/test/template/output_safety_helper_test.rb b/actionpack/test/template/output_safety_helper_test.rb index fc127c24e9..76c71c9e6d 100644 --- a/actionpack/test/template/output_safety_helper_test.rb +++ b/actionpack/test/template/output_safety_helper_test.rb @@ -1,9 +1,7 @@ require 'abstract_unit' -require 'testing_sandbox' class OutputSafetyHelperTest < ActionView::TestCase tests ActionView::Helpers::OutputSafetyHelper - include TestingSandbox def setup @string = "hello" diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb index 74d7bba4fe..a84034c02e 100644 --- a/actionpack/test/template/record_tag_helper_test.rb +++ b/actionpack/test/template/record_tag_helper_test.rb @@ -1,63 +1,103 @@ require 'abstract_unit' -require 'controller/fake_models' -class Post +class RecordTagPost extend ActiveModel::Naming include ActiveModel::Conversion - def id - 45 - end - def body - super || "What a wonderful world!" + attr_accessor :id, :body + + def initialize + @id = 45 + @body = "What a wonderful world!" + + yield self if block_given? end end class RecordTagHelperTest < ActionView::TestCase + include RenderERBUtils + tests ActionView::Helpers::RecordTagHelper def setup super - @post = Post.new - @post.persisted = true + @post = RecordTagPost.new end def test_content_tag_for - expected = %(<li class="post bar" id="post_45"></li>) - actual = content_tag_for(:li, @post, :class => 'bar') { } + expected = %(<li class="record_tag_post" id="record_tag_post_45"></li>) + actual = content_tag_for(:li, @post) { } assert_dom_equal expected, actual end def test_content_tag_for_prefix - expected = %(<ul class="archived_post" id="archived_post_45"></ul>) + expected = %(<ul class="archived_record_tag_post" id="archived_record_tag_post_45"></ul>) actual = content_tag_for(:ul, @post, :archived) { } assert_dom_equal expected, actual end - def test_content_tag_for_with_extra_html_tags - expected = %(<tr class="post bar" id="post_45" style='background-color: #f0f0f0'></tr>) - actual = content_tag_for(:tr, @post, {:class => "bar", :style => "background-color: #f0f0f0"}) { } + def test_content_tag_for_with_extra_html_options + expected = %(<tr class="record_tag_post special" id="record_tag_post_45" style='background-color: #f0f0f0'></tr>) + actual = content_tag_for(:tr, @post, :class => "special", :style => "background-color: #f0f0f0") { } + assert_dom_equal expected, actual + end + + def test_content_tag_for_with_prefix_and_extra_html_options + expected = %(<tr class="archived_record_tag_post special" id="archived_record_tag_post_45" style='background-color: #f0f0f0'></tr>) + actual = content_tag_for(:tr, @post, :archived, :class => "special", :style => "background-color: #f0f0f0") { } assert_dom_equal expected, actual end def test_block_not_in_erb_multiple_calls - expected = %(<div class="post bar" id="post_45">#{@post.body}</div>) - actual = div_for(@post, :class => "bar") { @post.body } + expected = %(<div class="record_tag_post special" id="record_tag_post_45">What a wonderful world!</div>) + actual = div_for(@post, :class => "special") { @post.body } assert_dom_equal expected, actual - actual = div_for(@post, :class => "bar") { @post.body } + actual = div_for(@post, :class => "special") { @post.body } assert_dom_equal expected, actual end def test_block_works_with_content_tag_for_in_erb - __in_erb_template = '' - expected = %(<tr class="post" id="post_45">#{@post.body}</tr>) - actual = content_tag_for(:tr, @post) { concat @post.body } + expected = %(<tr class="record_tag_post" id="record_tag_post_45">What a wonderful world!</tr>) + actual = render_erb("<%= content_tag_for(:tr, @post) do %><%= @post.body %><% end %>") assert_dom_equal expected, actual end def test_div_for_in_erb - __in_erb_template = '' - expected = %(<div class="post bar" id="post_45">#{@post.body}</div>) - actual = div_for(@post, :class => "bar") { concat @post.body } + expected = %(<div class="record_tag_post special" id="record_tag_post_45">What a wonderful world!</div>) + actual = render_erb("<%= div_for(@post, :class => 'special') do %><%= @post.body %><% end %>") + assert_dom_equal expected, actual + end + + def test_content_tag_for_collection + post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" } + post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" } + expected = %(<li class="record_tag_post" id="record_tag_post_101">Hello!</li>\n<li class="record_tag_post" id="record_tag_post_102">World!</li>) + actual = content_tag_for(:li, [post_1, post_2]) { |post| post.body } assert_dom_equal expected, actual end + + def test_div_for_collection + post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" } + post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" } + expected = %(<div class="record_tag_post" id="record_tag_post_101">Hello!</div>\n<div class="record_tag_post" id="record_tag_post_102">World!</div>) + actual = div_for([post_1, post_2]) { |post| post.body } + assert_dom_equal expected, actual + end + + def test_content_tag_for_single_record_is_html_safe + result = div_for(@post, :class => "special") { @post.body } + assert result.html_safe? + end + + def test_content_tag_for_collection_is_html_safe + post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" } + post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" } + result = content_tag_for(:li, [post_1, post_2]) { |post| post.body } + assert result.html_safe? + end + + def test_content_tag_for_does_not_change_options_hash + options = { :class => "important" } + content_tag_for(:li, @post, options) { } + assert_equal({ :class => "important" }, options) + end end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 86d08a43a5..88ed8664c2 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -20,19 +20,74 @@ module RenderTestCases assert_equal ORIGINAL_LOCALES, I18n.available_locales.map {|l| l.to_s }.sort end + def test_render_without_options + e = assert_raises(ArgumentError) { @view.render() } + assert_match "You invoked render but did not give any of :partial, :template, :inline, :file or :text option.", e.message + end + def test_render_file - assert_equal "Hello world!", @view.render(:file => "test/hello_world.erb") + assert_equal "Hello world!", @view.render(:file => "test/hello_world") end def test_render_file_not_using_full_path - assert_equal "Hello world!", @view.render(:file => "test/hello_world.erb") + assert_equal "Hello world!", @view.render(:file => "test/hello_world") end def test_render_file_without_specific_extension assert_equal "Hello world!", @view.render(:file => "test/hello_world") end - def test_render_file_with_localization + # Test if :formats, :locale etc. options are passed correctly to the resolvers. + def test_render_file_with_format + assert_match "<h1>No Comment</h1>", @view.render(:file => "comments/empty", :formats => [:html]) + assert_match "<error>No Comment</error>", @view.render(:file => "comments/empty", :formats => [:xml]) + assert_match "<error>No Comment</error>", @view.render(:file => "comments/empty", :formats => :xml) + end + + def test_render_template_with_format + assert_match "<h1>No Comment</h1>", @view.render(:template => "comments/empty", :formats => [:html]) + assert_match "<error>No Comment</error>", @view.render(:template => "comments/empty", :formats => [:xml]) + end + + def test_render_partial_implicitly_use_format_of_the_rendered_template + @view.lookup_context.formats = [:json] + assert_equal "Hello world", @view.render(:template => "test/one", :formats => [:html]) + end + + def test_render_template_with_a_missing_partial_of_another_format + @view.lookup_context.formats = [:html] + assert_raise ActionView::Template::Error, "Missing partial /missing with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder]}" do + @view.render(:template => "with_format", :formats => [:json]) + end + end + + def test_render_file_with_locale + assert_equal "<h1>Kein Kommentar</h1>", @view.render(:file => "comments/empty", :locale => [:de]) + assert_equal "<h1>Kein Kommentar</h1>", @view.render(:file => "comments/empty", :locale => :de) + end + + def test_render_template_with_locale + assert_equal "<h1>Kein Kommentar</h1>", @view.render(:template => "comments/empty", :locale => [:de]) + end + + def test_render_file_with_handlers + assert_equal "<h1>No Comment</h1>\n", @view.render(:file => "comments/empty", :handlers => [:builder]) + assert_equal "<h1>No Comment</h1>\n", @view.render(:file => "comments/empty", :handlers => :builder) + end + + def test_render_template_with_handlers + assert_equal "<h1>No Comment</h1>\n", @view.render(:template => "comments/empty", :handlers => [:builder]) + end + + def test_render_raw_template_with_handlers + assert_equal "<%= hello_world %>\n", @view.render(:template => "plain_text") + end + + def test_render_raw_template_with_quotes + assert_equal %q;Here are some characters: !@#$%^&*()-="'}{`; + "\n", @view.render(:template => "plain_text_with_characters") + end + + def test_render_file_with_localization_on_context_level old_locale, @view.locale = @view.locale, :da assert_equal "Hey verden", @view.render(:file => "test/hello_world") ensure @@ -51,17 +106,17 @@ module RenderTestCases end def test_render_file_with_full_path - template_path = File.join(File.dirname(__FILE__), '../fixtures/test/hello_world.erb') + template_path = File.join(File.dirname(__FILE__), '../fixtures/test/hello_world') assert_equal "Hello world!", @view.render(:file => template_path) end def test_render_file_with_instance_variables - assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_ivar.erb") + assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_ivar") end def test_render_file_with_locals locals = { :secret => 'in the sauce' } - assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_locals.erb", :locals => locals) + assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_locals", :locals => locals) end def test_render_file_not_using_full_path_with_dot_in_path @@ -80,13 +135,18 @@ module RenderTestCases assert_equal 'partial html', @view.render(:partial => 'test/partial') end + def test_render_partial_with_selected_format + assert_equal 'partial html', @view.render(:partial => 'test/partial', :formats => :html) + assert_equal 'partial js', @view.render(:partial => 'test/partial', :formats => [:js]) + end + def test_render_partial_at_top_level - # file fixtures/_top_level_partial_only.erb (not fixtures/test) + # file fixtures/_top_level_partial_only (not fixtures/test) assert_equal 'top level partial', @view.render(:partial => '/top_level_partial_only') end def test_render_partial_with_format_at_top_level - # file fixtures/_top_level_partial.html.erb (not fixtures/test, with format extension) + # file fixtures/_top_level_partial.html (not fixtures/test, with format extension) assert_equal 'top level partial html', @view.render(:partial => '/top_level_partial') end @@ -98,10 +158,27 @@ module RenderTestCases assert_equal "only partial", @view.render("test/partial_only", :counter_counter => 5) end + def test_render_partial_with_invalid_name + e = assert_raises(ArgumentError) { @view.render(:partial => "test/200") } + assert_equal "The partial name (test/200) is not a valid Ruby identifier; " + + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores.", e.message + end + + def test_render_partial_with_missing_filename + e = assert_raises(ArgumentError) { @view.render(:partial => "test/") } + assert_equal "The partial name (test/) is not a valid Ruby identifier; " + + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores.", e.message + end + + def test_render_partial_with_incompatible_object + e = assert_raises(ArgumentError) { @view.render(:partial => nil) } + assert_equal "'#{nil.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.", e.message + end + def test_render_partial_with_errors - @view.render(:partial => "test/raise") - flunk "Render did not raise Template::Error" - rescue ActionView::Template::Error => e + e = assert_raises(ActionView::Template::Error) { @view.render(:partial => "test/raise") } assert_match %r!method.*doesnt_exist!, e.message assert_equal "", e.sub_template_message assert_equal "1", e.line_number @@ -110,9 +187,7 @@ module RenderTestCases end def test_render_sub_template_with_errors - @view.render(:template => "test/sub_template_raise") - flunk "Render did not raise Template::Error" - rescue ActionView::Template::Error => e + e = assert_raises(ActionView::Template::Error) { @view.render(:template => "test/sub_template_raise") } assert_match %r!method.*doesnt_exist!, e.message assert_equal "Trace of template inclusion: #{File.expand_path("#{FIXTURE_LOAD_PATH}/test/sub_template_raise.html.erb")}", e.sub_template_message assert_equal "1", e.line_number @@ -120,9 +195,7 @@ module RenderTestCases end def test_render_file_with_errors - @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH)) - flunk "Render did not raise Template::Error" - rescue ActionView::Template::Error => e + e = assert_raises(ActionView::Template::Error) { @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH)) } assert_match %r!method.*doesnt_exist!, e.message assert_equal "", e.sub_template_message assert_equal "1", e.line_number @@ -169,6 +242,25 @@ module RenderTestCases assert_equal "Hello: davidHello: Anonymous", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), nil ]) end + def test_render_partial_with_layout_using_collection_and_template + assert_equal "<b>Hello: Amazon</b><b>Hello: Yahoo</b>", @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ]) + end + + def test_render_partial_with_layout_using_collection_and_template_makes_current_item_available_in_layout + assert_equal '<b class="amazon">Hello: Amazon</b><b class="yahoo">Hello: Yahoo</b>', + @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ]) + end + + def test_render_partial_with_layout_using_collection_and_template_makes_current_item_counter_available_in_layout + assert_equal '<b data-counter="0">Hello: Amazon</b><b data-counter="1">Hello: Yahoo</b>', + @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object_counter', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ]) + end + + def test_render_partial_with_layout_using_object_and_template_makes_object_available_in_layout + assert_equal '<b class="amazon">Hello: Amazon</b>', + @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :object => Customer.new("Amazon")) + end + def test_render_partial_with_empty_array_should_return_nil assert_nil @view.render(:partial => []) end @@ -200,13 +292,13 @@ module RenderTestCases # TODO: The reason for this test is unclear, improve documentation def test_render_missing_xml_partial_and_raise_missing_template @view.formats = [:xml] - assert_raise(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") } + assert_raises(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") } ensure @view.formats = nil end def test_render_layout_with_block_and_other_partial_inside - render = @view.render(:layout => "test/layout_with_partial_and_yield.html.erb") { "Yield!" } + render = @view.render(:layout => "test/layout_with_partial_and_yield") { "Yield!" } assert_equal "Before\npartial html\nYield!\nAfter\n", render end @@ -242,25 +334,33 @@ module RenderTestCases assert_equal 'source: "Hello, <%= name %>!"', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo) end + def test_render_knows_about_types_registered_when_extensions_are_checked_earlier_in_initialization + ActionView::Template::Handlers.extensions + ActionView::Template.register_template_handler :foo, CustomHandler + assert ActionView::Template::Handlers.extensions.include?(:foo) + end + def test_render_ignores_templates_with_malformed_template_handlers - %w(malformed malformed.erb malformed.html.erb malformed.en.html.erb).each do |name| - assert_raise(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") } + ActiveSupport::Deprecation.silence do + %w(malformed malformed.erb malformed.html.erb malformed.en.html.erb).each do |name| + assert_raises(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") } + end end end def test_render_with_layout assert_equal %(<title></title>\nHello world!\n), - @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield") + @view.render(:file => "test/hello_world", :layout => "layouts/yield") end def test_render_with_layout_which_has_render_inline assert_equal %(welcome\nHello world!\n), - @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_inline_inside") + @view.render(:file => "test/hello_world", :layout => "layouts/yield_with_render_inline_inside") end def test_render_with_layout_which_renders_another_partial assert_equal %(partial html\nHello world!\n), - @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_partial_inside") + @view.render(:file => "test/hello_world", :layout => "layouts/yield_with_render_partial_inside") end def test_render_layout_with_block_and_yield @@ -305,17 +405,17 @@ module RenderTestCases def test_render_with_nested_layout assert_equal %(<title>title</title>\n\n<div id="column">column</div>\n<div id="content">content</div>\n), - @view.render(:file => "test/nested_layout.erb", :layout => "layouts/yield") + @view.render(:file => "test/nested_layout", :layout => "layouts/yield") end def test_render_with_file_in_layout assert_equal %(\n<title>title</title>\n\n), - @view.render(:file => "test/layout_render_file.erb") + @view.render(:file => "test/layout_render_file") end def test_render_layout_with_object assert_equal %(<title>David</title>), - @view.render(:file => "test/layout_render_object.erb") + @view.render(:file => "test/layout_render_object") end end @@ -341,7 +441,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase # is not eager loaded def setup path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) - view_paths = ActionView::Base.process_view_paths(path) + view_paths = ActionView::PathSet.new([path]) assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first setup_view(view_paths) end @@ -350,51 +450,41 @@ class LazyViewRenderTest < ActiveSupport::TestCase GC.start end - if '1.9'.respond_to?(:force_encoding) - def test_render_utf8_template_with_magic_comment - with_external_encoding Encoding::ASCII_8BIT do - result = @view.render(:file => "test/utf8_magic.html.erb", :layouts => "layouts/yield") - assert_equal Encoding::UTF_8, result.encoding - assert_equal "\nРусский \nтекст\n\nUTF-8\nUTF-8\nUTF-8\n", result - end + def test_render_utf8_template_with_magic_comment + with_external_encoding Encoding::ASCII_8BIT do + result = @view.render(:file => "test/utf8_magic", :formats => [:html], :layouts => "layouts/yield") + assert_equal Encoding::UTF_8, result.encoding + assert_equal "\nРусский \nтекст\n\nUTF-8\nUTF-8\nUTF-8\n", result end + end - def test_render_utf8_template_with_default_external_encoding - with_external_encoding Encoding::UTF_8 do - result = @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield") - assert_equal Encoding::UTF_8, result.encoding - assert_equal "Русский текст\n\nUTF-8\nUTF-8\nUTF-8\n", result - end + def test_render_utf8_template_with_default_external_encoding + with_external_encoding Encoding::UTF_8 do + result = @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") + assert_equal Encoding::UTF_8, result.encoding + assert_equal "Русский текст\n\nUTF-8\nUTF-8\nUTF-8\n", result end + end - def test_render_utf8_template_with_incompatible_external_encoding - with_external_encoding Encoding::SHIFT_JIS do - begin - result = @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield") - flunk 'Should have raised incompatible encoding error' - rescue ActionView::Template::Error => error - assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message - end - end + def test_render_utf8_template_with_incompatible_external_encoding + with_external_encoding Encoding::SHIFT_JIS do + e = assert_raises(ActionView::Template::Error) { @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") } + assert_match 'Your template was not saved as valid Shift_JIS', e.original_exception.message end + end - def test_render_utf8_template_with_partial_with_incompatible_encoding - with_external_encoding Encoding::SHIFT_JIS do - begin - result = @view.render(:file => "test/utf8_magic_with_bare_partial.html.erb", :layouts => "layouts/yield") - flunk 'Should have raised incompatible encoding error' - rescue ActionView::Template::Error => error - assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message - end - end + def test_render_utf8_template_with_partial_with_incompatible_encoding + with_external_encoding Encoding::SHIFT_JIS do + e = assert_raises(ActionView::Template::Error) { @view.render(:file => "test/utf8_magic_with_bare_partial", :formats => [:html], :layouts => "layouts/yield") } + assert_match 'Your template was not saved as valid Shift_JIS', e.original_exception.message end + end - def with_external_encoding(encoding) - old = Encoding.default_external - silence_warnings { Encoding.default_external = encoding } - yield - ensure - silence_warnings { Encoding.default_external = old } - end + def with_external_encoding(encoding) + old = Encoding.default_external + silence_warnings { Encoding.default_external = encoding } + yield + ensure + silence_warnings { Encoding.default_external = old } end end diff --git a/actionpack/test/template/sanitize_helper_test.rb b/actionpack/test/template/sanitize_helper_test.rb index 222d4dbf4c..4182af590e 100644 --- a/actionpack/test/template/sanitize_helper_test.rb +++ b/actionpack/test/template/sanitize_helper_test.rb @@ -1,11 +1,9 @@ require 'abstract_unit' -require 'testing_sandbox' # The exhaustive tests are in test/controller/html/sanitizer_test.rb. # This tests the that the helpers hook up correctly to the sanitizer classes. class SanitizeHelperTest < ActionView::TestCase tests ActionView::Helpers::SanitizeHelper - include TestingSandbox def test_strip_links assert_equal "Dont touch me", strip_links("Dont touch me") diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb deleted file mode 100644 index 8d3be09a4f..0000000000 --- a/actionpack/test/template/sprockets_helper_test.rb +++ /dev/null @@ -1,119 +0,0 @@ -require 'abstract_unit' -require 'sprockets' -require 'mocha' - -module Rails; end - -class SprocketsHelperTest < ActionView::TestCase - tests ActionView::Helpers::SprocketsHelper - - attr_accessor :assets - - def setup - super - - @controller = BasicController.new - - @request = Class.new do - def protocol() 'http://' end - def ssl?() false end - def host_with_port() 'localhost' end - end.new - - @controller.request = @request - - @assets = Sprockets::Environment.new - @assets.paths << FIXTURES.join("sprockets/app/javascripts") - @assets.paths << FIXTURES.join("sprockets/app/stylesheets") - @assets.paths << FIXTURES.join("sprockets/app/images") - - application = Object.new - Rails.stubs(:application).returns(application) - application.stubs(:config).returns(config) - application.stubs(:assets).returns(@assets) - - config.perform_caching = true - end - - def url_for(*args) - "http://www.example.com" - end - - test "asset path" do - assert_equal "/assets/logo-9c0a079bdd7701d7e729bd956823d153.png", - asset_path("logo.png") - - assert_equal "/images/logo", - asset_path("/images/logo") - assert_equal "/images/logo.gif", - asset_path("/images/logo.gif") - - assert_equal "/dir/audio", - asset_path("/dir/audio") - - assert_equal "http://www.example.com/video/play", - asset_path("http://www.example.com/video/play") - assert_equal "http://www.example.com/video/play.mp4", - asset_path("http://www.example.com/video/play.mp4") - end - - test "javascript path" do - assert_equal "/assets/application-d41d8cd98f00b204e9800998ecf8427e.js", - asset_path(:application, "js") - - assert_equal "/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js", - asset_path("xmlhr", "js") - assert_equal "/assets/dir/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js", - asset_path("dir/xmlhr.js", "js") - - assert_equal "/dir/xmlhr.js", - asset_path("/dir/xmlhr", "js") - - assert_equal "http://www.example.com/js/xmlhr", - asset_path("http://www.example.com/js/xmlhr", "js") - assert_equal "http://www.example.com/js/xmlhr.js", - asset_path("http://www.example.com/js/xmlhr.js", "js") - end - - test "javascript include tag" do - assert_equal '<script src="/assets/application-d41d8cd98f00b204e9800998ecf8427e.js" type="text/javascript"></script>', - sprockets_javascript_include_tag(:application) - - assert_equal '<script src="/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js" type="text/javascript"></script>', - sprockets_javascript_include_tag("xmlhr") - assert_equal '<script src="/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js" type="text/javascript"></script>', - sprockets_javascript_include_tag("xmlhr.js") - assert_equal '<script src="http://www.example.com/xmlhr" type="text/javascript"></script>', - sprockets_javascript_include_tag("http://www.example.com/xmlhr") - end - - test "stylesheet path" do - assert_equal "/assets/application-d41d8cd98f00b204e9800998ecf8427e.css", asset_path(:application, "css") - - assert_equal "/assets/style-d41d8cd98f00b204e9800998ecf8427e.css", asset_path("style", "css") - assert_equal "/assets/dir/style-d41d8cd98f00b204e9800998ecf8427e.css", asset_path("dir/style.css", "css") - assert_equal "/dir/style.css", asset_path("/dir/style.css", "css") - - assert_equal "http://www.example.com/css/style", - asset_path("http://www.example.com/css/style", "css") - assert_equal "http://www.example.com/css/style.css", - asset_path("http://www.example.com/css/style.css", "css") - end - - test "stylesheet link tag" do - assert_equal '<link href="/assets/application-d41d8cd98f00b204e9800998ecf8427e.css" media="screen" rel="stylesheet" type="text/css" />', - sprockets_stylesheet_link_tag(:application) - - assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="screen" rel="stylesheet" type="text/css" />', - sprockets_stylesheet_link_tag("style") - assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="screen" rel="stylesheet" type="text/css" />', - sprockets_stylesheet_link_tag("style.css") - - assert_equal '<link href="http://www.example.com/style.css" media="screen" rel="stylesheet" type="text/css" />', - sprockets_stylesheet_link_tag("http://www.example.com/style.css") - assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="all" rel="stylesheet" type="text/css" />', - sprockets_stylesheet_link_tag("style", :media => "all") - assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="print" rel="stylesheet" type="text/css" />', - sprockets_stylesheet_link_tag("style", :media => "print") - end -end diff --git a/actionpack/test/template/streaming_render_test.rb b/actionpack/test/template/streaming_render_test.rb index b2df8efee3..520bf3a824 100644 --- a/actionpack/test/template/streaming_render_test.rb +++ b/actionpack/test/template/streaming_render_test.rb @@ -8,7 +8,7 @@ end class FiberedTest < ActiveSupport::TestCase def setup view_paths = ActionController::Base.view_paths - @assigns = { :secret => 'in the sauce' } + @assigns = { :secret => 'in the sauce', :name => nil } @view = ActionView::Base.new(view_paths, @assigns) @controller_view = TestController.new.view_context end @@ -28,7 +28,7 @@ class FiberedTest < ActiveSupport::TestCase def test_streaming_works content = [] - body = render_body(:template => "test/hello_world.erb", :layout => "layouts/yield") + body = render_body(:template => "test/hello_world", :layout => "layouts/yield") body.each do |piece| content << piece @@ -42,12 +42,12 @@ class FiberedTest < ActiveSupport::TestCase end def test_render_file - assert_equal "Hello world!", buffered_render(:file => "test/hello_world.erb") + assert_equal "Hello world!", buffered_render(:file => "test/hello_world") end def test_render_file_with_locals locals = { :secret => 'in the sauce' } - assert_equal "The secret is in the sauce\n", buffered_render(:file => "test/render_file_with_locals.erb", :locals => locals) + assert_equal "The secret is in the sauce\n", buffered_render(:file => "test/render_file_with_locals", :locals => locals) end def test_render_partial @@ -64,27 +64,27 @@ class FiberedTest < ActiveSupport::TestCase def test_render_with_layout assert_equal %(<title></title>\nHello world!\n), - buffered_render(:template => "test/hello_world.erb", :layout => "layouts/yield") + buffered_render(:template => "test/hello_world", :layout => "layouts/yield") end def test_render_with_layout_which_has_render_inline assert_equal %(welcome\nHello world!\n), - buffered_render(:template => "test/hello_world.erb", :layout => "layouts/yield_with_render_inline_inside") + buffered_render(:template => "test/hello_world", :layout => "layouts/yield_with_render_inline_inside") end def test_render_with_layout_which_renders_another_partial assert_equal %(partial html\nHello world!\n), - buffered_render(:template => "test/hello_world.erb", :layout => "layouts/yield_with_render_partial_inside") + buffered_render(:template => "test/hello_world", :layout => "layouts/yield_with_render_partial_inside") end def test_render_with_nested_layout assert_equal %(<title>title</title>\n\n<div id="column">column</div>\n<div id="content">content</div>\n), - buffered_render(:template => "test/nested_layout.erb", :layout => "layouts/yield") + buffered_render(:template => "test/nested_layout", :layout => "layouts/yield") end def test_render_with_file_in_layout assert_equal %(\n<title>title</title>\n\n), - buffered_render(:template => "test/layout_render_file.erb") + buffered_render(:template => "test/layout_render_file") end def test_render_with_handler_without_streaming_support @@ -106,4 +106,4 @@ class FiberedTest < ActiveSupport::TestCase buffered_render(:template => "test/nested_streaming", :layout => "layouts/streaming") end -end if defined?(Fiber)
\ No newline at end of file +end diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb index 60b466a9ff..f0a7ce0bc9 100644 --- a/actionpack/test/template/tag_helper_test.rb +++ b/actionpack/test/template/tag_helper_test.rb @@ -1,6 +1,8 @@ require 'abstract_unit' class TagHelperTest < ActionView::TestCase + include RenderERBUtils + tests ActionView::Helpers::TagHelper def test_tag @@ -28,8 +30,8 @@ class TagHelperTest < ActionView::TestCase end def test_tag_options_converts_boolean_option - assert_equal '<p disabled="disabled" multiple="multiple" readonly="readonly" />', - tag("p", :disabled => true, :multiple => true, :readonly => true) + assert_equal '<p disabled="disabled" itemscope="itemscope" multiple="multiple" readonly="readonly" />', + tag("p", :disabled => true, :itemscope => true, :multiple => true, :readonly => true) end def test_content_tag @@ -44,12 +46,12 @@ class TagHelperTest < ActionView::TestCase end def test_content_tag_with_block_in_erb - buffer = content_tag(:div) { concat "Hello world!" } + buffer = render_erb("<%= content_tag(:div) do %>Hello world!<% end %>") assert_dom_equal "<div>Hello world!</div>", buffer end def test_content_tag_with_block_and_options_in_erb - buffer = content_tag(:div, :class => "green") { concat "Hello world!" } + buffer = render_erb("<%= content_tag(:div, :class => 'green') do %>Hello world!<% end %>") assert_dom_equal %(<div class="green">Hello world!</div>), buffer end @@ -68,10 +70,8 @@ class TagHelperTest < ActionView::TestCase output_buffer end - # TAG TODO: Move this into a real template def test_content_tag_nested_in_content_tag_in_erb - buffer = content_tag("p") { concat content_tag("b", "Hello") } - assert_equal '<p><b>Hello</b></p>', buffer + assert_equal "<p>\n <b>Hello</b>\n</p>", view.render("test/content_tag_nested_in_content_tag") end def test_content_tag_with_escaped_array_class @@ -91,6 +91,11 @@ class TagHelperTest < ActionView::TestCase assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>") end + def test_cdata_section_splitted + assert_equal "<![CDATA[hello]]]]><![CDATA[>world]]>", cdata_section("hello]]>world") + assert_equal "<![CDATA[hello]]]]><![CDATA[>world]]]]><![CDATA[>again]]>", cdata_section("hello]]>world]]>again") + end + def test_escape_once assert_equal '1 < 2 & 3', escape_once('1 < 2 & 3') end @@ -113,8 +118,8 @@ class TagHelperTest < ActionView::TestCase def test_data_attributes ['data', :data].each { |data| - assert_dom_equal '<a data-a-number="1" data-array="[1,2,3]" data-hash="{"key":"value"}" data-string="hello" data-symbol="foo" />', - tag('a', { data => { :a_number => 1, :string => 'hello', :symbol => :foo, :array => [1, 2, 3], :hash => { :key => 'value'} } }) + assert_dom_equal '<a data-a-float="3.14" data-a-big-decimal="-123.456" data-a-number="1" data-array="[1,2,3]" data-hash="{"key":"value"}" data-string="hello" data-symbol="foo" />', + tag('a', { data => { :a_float => 3.14, :a_big_decimal => BigDecimal.new("-123.456"), :a_number => 1, :string => 'hello', :symbol => :foo, :array => [1, 2, 3], :hash => { :key => 'value'} } }) } end end diff --git a/actionpack/test/template/template_error_test.rb b/actionpack/test/template/template_error_test.rb index 3a874082d9..91424daeed 100644 --- a/actionpack/test/template/template_error_test.rb +++ b/actionpack/test/template/template_error_test.rb @@ -2,12 +2,12 @@ require "abstract_unit" class TemplateErrorTest < ActiveSupport::TestCase def test_provides_original_message - error = ActionView::Template::Error.new("test", {}, Exception.new("original")) + error = ActionView::Template::Error.new("test", Exception.new("original")) assert_equal "original", error.message end def test_provides_useful_inspect - error = ActionView::Template::Error.new("test", {}, Exception.new("original")) + error = ActionView::Template::Error.new("test", Exception.new("original")) assert_equal "#<ActionView::Template::Error: original>", error.inspect end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 81fb34b80f..322bea3fb0 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -8,6 +8,11 @@ class TestERBTemplate < ActiveSupport::TestCase def disable_cache yield end + + def find_template(*args) + end + + attr_accessor :formats end class Context @@ -34,7 +39,7 @@ class TestERBTemplate < ActiveSupport::TestCase end def logger - Logger.new(STDERR) + ActiveSupport::Logger.new(STDERR) end def my_buffer @@ -43,7 +48,7 @@ class TestERBTemplate < ActiveSupport::TestCase end def new_template(body = "<%= hello %>", details = {}) - ActionView::Template.new(body, "hello template", ERBHandler, {:virtual_path => "hello"}.merge!(details)) + ActionView::Template.new(body, "hello template", details.fetch(:handler) { ERBHandler }, {:virtual_path => "hello"}.merge!(details)) end def render(locals = {}) @@ -59,6 +64,11 @@ class TestERBTemplate < ActiveSupport::TestCase assert_equal "Hello", render end + def test_raw_template + @template = new_template("<%= hello %>", :handler => ActionView::Template::Handlers::Raw.new) + assert_equal "<%= hello %>", render + end + def test_template_loses_its_source_after_rendering @template = new_template render @@ -111,67 +121,65 @@ class TestERBTemplate < ActiveSupport::TestCase end end - if "ruby".encoding_aware? - def test_resulting_string_is_utf8 - @template = new_template - assert_equal Encoding::UTF_8, render.encoding - end + def test_resulting_string_is_utf8 + @template = new_template + assert_equal Encoding::UTF_8, render.encoding + end - def test_no_magic_comment_word_with_utf_8 - @template = new_template("hello \u{fc}mlat") + def test_no_magic_comment_word_with_utf_8 + @template = new_template("hello \u{fc}mlat") + assert_equal Encoding::UTF_8, render.encoding + assert_equal "hello \u{fc}mlat", render + end + + # This test ensures that if the default_external + # is set to something other than UTF-8, we don't + # get any errors and get back a UTF-8 String. + def test_default_external_works + with_external_encoding "ISO-8859-1" do + @template = new_template("hello \xFCmlat") assert_equal Encoding::UTF_8, render.encoding assert_equal "hello \u{fc}mlat", render end + end - # This test ensures that if the default_external - # is set to something other than UTF-8, we don't - # get any errors and get back a UTF-8 String. - def test_default_external_works - with_external_encoding "ISO-8859-1" do - @template = new_template("hello \xFCmlat") - assert_equal Encoding::UTF_8, render.encoding - assert_equal "hello \u{fc}mlat", render - end - end - - def test_encoding_can_be_specified_with_magic_comment - @template = new_template("# encoding: ISO-8859-1\nhello \xFCmlat") - assert_equal Encoding::UTF_8, render.encoding - assert_equal "\nhello \u{fc}mlat", render - end + def test_encoding_can_be_specified_with_magic_comment + @template = new_template("# encoding: ISO-8859-1\nhello \xFCmlat") + assert_equal Encoding::UTF_8, render.encoding + assert_equal "\nhello \u{fc}mlat", render + end - # TODO: This is currently handled inside ERB. The case of explicitly - # lying about encodings via the normal Rails API should be handled - # inside Rails. - def test_lying_with_magic_comment - assert_raises(ActionView::Template::Error) do - @template = new_template("# encoding: UTF-8\nhello \xFCmlat", :virtual_path => nil) - render - end + # TODO: This is currently handled inside ERB. The case of explicitly + # lying about encodings via the normal Rails API should be handled + # inside Rails. + def test_lying_with_magic_comment + assert_raises(ActionView::Template::Error) do + @template = new_template("# encoding: UTF-8\nhello \xFCmlat", :virtual_path => nil) + render end + end - def test_encoding_can_be_specified_with_magic_comment_in_erb - with_external_encoding Encoding::UTF_8 do - @template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat", :virtual_path => nil) - result = render - assert_equal Encoding::UTF_8, render.encoding - assert_equal "hello \u{fc}mlat", render - end + def test_encoding_can_be_specified_with_magic_comment_in_erb + with_external_encoding Encoding::UTF_8 do + @template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat", :virtual_path => nil) + assert_equal Encoding::UTF_8, render.encoding + assert_equal "hello \u{fc}mlat", render end + end - def test_error_when_template_isnt_valid_utf8 - assert_raises(ActionView::Template::Error, /\xFC/) do - @template = new_template("hello \xFCmlat", :virtual_path => nil) - render - end + def test_error_when_template_isnt_valid_utf8 + assert_raises(ActionView::Template::Error, /\xFC/) do + @template = new_template("hello \xFCmlat", :virtual_path => nil) + render end + end - def with_external_encoding(encoding) - old = Encoding.default_external - silence_warnings { Encoding.default_external = encoding } - yield - ensure - silence_warnings { Encoding.default_external = old } - end + def with_external_encoding(encoding) + old = Encoding.default_external + Encoding::Converter.new old, encoding if old != encoding + silence_warnings { Encoding.default_external = encoding } + yield + ensure + silence_warnings { Encoding.default_external = old } end end diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index cd4618a505..f2ed2ec609 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -45,6 +45,10 @@ module ActionView assert_same _view, view end + test "retrieve non existing config values" do + assert_equal nil, ActionView::Base.new.config.something_odd + end + test "works without testing a helper module" do assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) end @@ -141,22 +145,6 @@ module ActionView end end - class AssignsTest < ActionView::TestCase - setup do - ActiveSupport::Deprecation.stubs(:warn) - end - - test "_assigns delegates to user_defined_ivars" do - self.expects(:view_assigns) - _assigns - end - - test "_assigns is deprecated" do - ActiveSupport::Deprecation.expects(:warn) - _assigns - end - end - class ViewAssignsTest < ActionView::TestCase test "view_assigns returns a Hash of user defined ivars" do @a = 'b' @@ -167,7 +155,7 @@ module ActionView test "view_assigns excludes internal ivars" do INTERNAL_IVARS.each do |ivar| assert defined?(ivar), "expected #{ivar} to be defined" - assert !view_assigns.keys.include?(ivar.sub('@','').to_sym), "expected #{ivar} to be excluded from view_assigns" + assert !view_assigns.keys.include?(ivar.to_s.sub('@', '').to_sym), "expected #{ivar} to be excluded from view_assigns" end end end @@ -289,6 +277,12 @@ module ActionView end class RenderTemplateTest < ActionView::TestCase + test "supports specifying templates with a Regexp" do + controller.controller_path = "fun" + render(:template => "fun/games/hello_world") + assert_template %r{\Afun/games/hello_world\Z} + end + test "supports specifying partials" do controller.controller_path = "test" render(:template => "test/calling_partial_with_layout") diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb index 3d0bbba435..108a674d95 100644 --- a/actionpack/test/template/test_test.rb +++ b/actionpack/test/template/test_test.rb @@ -39,7 +39,7 @@ class PeopleHelperTest < ActionView::TestCase with_test_route_set do person = mock(:name => "David") person.class.extend ActiveModel::Naming - _routes.url_helpers.expects(:hash_for_mocha_mock_path).with(person).returns("/people/1") + expects(:mocha_mock_path).with(person).returns("/people/1") assert_equal '<a href="/people/1">David</a>', link_to_person(person) end end @@ -48,7 +48,7 @@ class PeopleHelperTest < ActionView::TestCase def with_test_route_set with_routing do |set| set.draw do - match 'people', :to => 'people#index', :as => :people + get 'people', :to => 'people#index', :as => :people end yield end @@ -62,3 +62,19 @@ class CrazyHelperTest < ActionView::TestCase assert_equal PeopleHelper, self.class.helper_class end end + +class CrazySymbolHelperTest < ActionView::TestCase + tests :people + + def test_set_helper_class_using_symbol + assert_equal PeopleHelper, self.class.helper_class + end +end + +class CrazyStringHelperTest < ActionView::TestCase + tests 'people' + + def test_set_helper_class_using_string + assert_equal PeopleHelper, self.class.helper_class + end +end diff --git a/actionpack/test/template/testing/fixture_resolver_test.rb b/actionpack/test/template/testing/fixture_resolver_test.rb index de83540468..9649f349cb 100644 --- a/actionpack/test/template/testing/fixture_resolver_test.rb +++ b/actionpack/test/template/testing/fixture_resolver_test.rb @@ -8,8 +8,8 @@ class FixtureResolverTest < ActiveSupport::TestCase end def test_should_return_template_for_declared_path - resolver = ActionView::FixtureResolver.new("arbitrary/path" => "this text") - templates = resolver.find_all("path", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => []}) + resolver = ActionView::FixtureResolver.new("arbitrary/path.erb" => "this text") + templates = resolver.find_all("path", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => [:erb]}) assert_equal 1, templates.size, "expected one template" assert_equal "this text", templates.first.source assert_equal "arbitrary/path", templates.first.virtual_path diff --git a/actionpack/test/template/testing/null_resolver_test.rb b/actionpack/test/template/testing/null_resolver_test.rb index e142506e6a..535ad3ab14 100644 --- a/actionpack/test/template/testing/null_resolver_test.rb +++ b/actionpack/test/template/testing/null_resolver_test.rb @@ -3,10 +3,10 @@ require 'abstract_unit' class NullResolverTest < ActiveSupport::TestCase def test_should_return_template_for_any_path resolver = ActionView::NullResolver.new() - templates = resolver.find_all("path", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => []}) + templates = resolver.find_all("path.erb", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => []}) assert_equal 1, templates.size, "expected one template" assert_equal "Template generated by Null Resolver", templates.first.source - assert_equal "arbitrary/path", templates.first.virtual_path + assert_equal "arbitrary/path.erb", templates.first.virtual_path assert_equal [:html], templates.first.formats end end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 740f577a6e..f58e474759 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -1,10 +1,8 @@ # encoding: utf-8 require 'abstract_unit' -require 'testing_sandbox' class TextHelperTest < ActionView::TestCase tests ActionView::Helpers::TextHelper - include TestingSandbox def setup super @@ -36,8 +34,8 @@ class TextHelperTest < ActionView::TestCase text = "A\r\n \nB\n\n\r\n\t\nC\nD".freeze assert_equal "<p>A\n<br /> \n<br />B</p>\n\n<p>\t\n<br />C\n<br />D</p>", simple_format(text) - assert_equal %q(<p class="test">This is a classy test</p>), simple_format("This is a classy test", :class => 'test') - assert_equal %Q(<p class="test">para 1</p>\n\n<p class="test">para 2</p>), simple_format("para 1\n\npara 2", :class => 'test') + assert_equal %q(<p class="test">This is a classy test</p>), simple_format("This is a classy test", :class => 'test') + assert_equal %Q(<p class="test">para 1</p>\n\n<p class="test">para 2</p>), simple_format("para 1\n\npara 2", :class => 'test') end def test_simple_format_should_sanitize_input_when_sanitize_option_is_not_false @@ -48,6 +46,35 @@ class TextHelperTest < ActionView::TestCase assert_equal "<p><b> test with unsafe string </b><script>code!</script></p>", simple_format("<b> test with unsafe string </b><script>code!</script>", {}, :sanitize => false) end + def test_simple_format_with_custom_wrapper + assert_equal "<div></div>", simple_format(nil, {}, :wrapper_tag => "div") + end + + def test_simple_format_with_custom_wrapper_and_multi_line_breaks + assert_equal "<div>We want to put a wrapper...</div>\n\n<div>...right there.</div>", simple_format("We want to put a wrapper...\n\n...right there.", {}, :wrapper_tag => "div") + end + + def test_simple_format_should_not_change_the_text_passed + text = "<b>Ok</b><script>code!</script>" + text_clone = text.dup + simple_format(text) + assert_equal text_clone, text + end + + def test_simple_format_does_not_modify_the_html_options_hash + options = { :class => "foobar"} + passed_options = options.dup + simple_format("some text", passed_options) + assert_equal options, passed_options + end + + def test_simple_format_does_not_modify_the_options_hash + options = { :wrapper_tag => :div, :sanitize => false } + passed_options = options.dup + simple_format("some text", {}, passed_options) + assert_equal options, passed_options + end + def test_truncate_should_not_be_html_safe assert !truncate("Hello World!", :length => 12).html_safe? end @@ -75,25 +102,16 @@ class TextHelperTest < ActionView::TestCase assert_equal "Hello Big[...]", truncate("Hello Big World!", :omission => "[...]", :length => 15, :separator => ' ') end - if RUBY_VERSION < '1.9.0' - def test_truncate_multibyte - with_kcode 'none' do - assert_equal "\354\225\210\353\205\225\355...", truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) - end - with_kcode 'u' do - assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...", - truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244", :length => 10) - end - end - else - def test_truncate_multibyte - # .mb_chars always returns a UTF-8 String. - # assert_equal "\354\225\210\353\205\225\355...", - # truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) - - assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), - truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) - end + def test_truncate_multibyte + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), + truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) + end + + def test_truncate_does_not_modify_the_options_hash + options = { :length => 10 } + passed_options = options.dup + truncate("some text", passed_options) + assert_equal options, passed_options end def test_highlight_should_be_html_safe @@ -102,18 +120,18 @@ class TextHelperTest < ActionView::TestCase def test_highlight assert_equal( - "This is a <strong class=\"highlight\">beautiful</strong> morning", + "This is a <mark>beautiful</mark> morning", highlight("This is a beautiful morning", "beautiful") ) assert_equal( - "This is a <strong class=\"highlight\">beautiful</strong> morning, but also a <strong class=\"highlight\">beautiful</strong> day", + "This is a <mark>beautiful</mark> morning, but also a <mark>beautiful</mark> day", highlight("This is a beautiful morning, but also a beautiful day", "beautiful") ) assert_equal( "This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day", - highlight("This is a beautiful morning, but also a beautiful day", "beautiful", '<b>\1</b>') + highlight("This is a beautiful morning, but also a beautiful day", "beautiful", :highlighter => '<b>\1</b>') ) assert_equal( @@ -126,104 +144,107 @@ class TextHelperTest < ActionView::TestCase def test_highlight_should_sanitize_input assert_equal( - "This is a <strong class=\"highlight\">beautiful</strong> morning", + "This is a <mark>beautiful</mark> morning", highlight("This is a beautiful morning<script>code!</script>", "beautiful") ) end def test_highlight_should_not_sanitize_if_sanitize_option_if_false assert_equal( - "This is a <strong class=\"highlight\">beautiful</strong> morning<script>code!</script>", + "This is a <mark>beautiful</mark> morning<script>code!</script>", highlight("This is a beautiful morning<script>code!</script>", "beautiful", :sanitize => false) ) end def test_highlight_with_regexp assert_equal( - "This is a <strong class=\"highlight\">beautiful!</strong> morning", + "This is a <mark>beautiful!</mark> morning", highlight("This is a beautiful! morning", "beautiful!") ) assert_equal( - "This is a <strong class=\"highlight\">beautiful! morning</strong>", + "This is a <mark>beautiful! morning</mark>", highlight("This is a beautiful! morning", "beautiful! morning") ) assert_equal( - "This is a <strong class=\"highlight\">beautiful? morning</strong>", + "This is a <mark>beautiful? morning</mark>", highlight("This is a beautiful? morning", "beautiful? morning") ) end def test_highlight_with_multiple_phrases_in_one_pass - assert_equal %(<em>wow</em> <em>em</em>), highlight('wow em', %w(wow em), '<em>\1</em>') - end - - def test_highlight_with_options_hash - assert_equal( - "This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day", - highlight("This is a beautiful morning, but also a beautiful day", "beautiful", :highlighter => '<b>\1</b>') - ) + assert_equal %(<em>wow</em> <em>em</em>), highlight('wow em', %w(wow em), :highlighter => '<em>\1</em>') end def test_highlight_with_html assert_equal( - "<p>This is a <strong class=\"highlight\">beautiful</strong> morning, but also a <strong class=\"highlight\">beautiful</strong> day</p>", + "<p>This is a <mark>beautiful</mark> morning, but also a <mark>beautiful</mark> day</p>", highlight("<p>This is a beautiful morning, but also a beautiful day</p>", "beautiful") ) assert_equal( - "<p>This is a <em><strong class=\"highlight\">beautiful</strong></em> morning, but also a <strong class=\"highlight\">beautiful</strong> day</p>", + "<p>This is a <em><mark>beautiful</mark></em> morning, but also a <mark>beautiful</mark> day</p>", highlight("<p>This is a <em>beautiful</em> morning, but also a beautiful day</p>", "beautiful") ) assert_equal( - "<p>This is a <em class=\"error\"><strong class=\"highlight\">beautiful</strong></em> morning, but also a <strong class=\"highlight\">beautiful</strong> <span class=\"last\">day</span></p>", + "<p>This is a <em class=\"error\"><mark>beautiful</mark></em> morning, but also a <mark>beautiful</mark> <span class=\"last\">day</span></p>", highlight("<p>This is a <em class=\"error\">beautiful</em> morning, but also a beautiful <span class=\"last\">day</span></p>", "beautiful") ) assert_equal( - "<p class=\"beautiful\">This is a <strong class=\"highlight\">beautiful</strong> morning, but also a <strong class=\"highlight\">beautiful</strong> day</p>", + "<p class=\"beautiful\">This is a <mark>beautiful</mark> morning, but also a <mark>beautiful</mark> day</p>", highlight("<p class=\"beautiful\">This is a beautiful morning, but also a beautiful day</p>", "beautiful") ) assert_equal( - "<p>This is a <strong class=\"highlight\">beautiful</strong> <a href=\"http://example.com/beautiful#top?what=beautiful%20morning&when=now+then\">morning</a>, but also a <strong class=\"highlight\">beautiful</strong> day</p>", + "<p>This is a <mark>beautiful</mark> <a href=\"http://example.com/beautiful#top?what=beautiful%20morning&when=now+then\">morning</a>, but also a <mark>beautiful</mark> day</p>", highlight("<p>This is a beautiful <a href=\"http://example.com/beautiful\#top?what=beautiful%20morning&when=now+then\">morning</a>, but also a beautiful day</p>", "beautiful") ) + assert_equal( + "<div>abc <b>div</b></div>", + highlight("<div>abc div</div>", "div", :highlighter => '<b>\1</b>') + ) + end + + def test_highlight_does_not_modify_the_options_hash + options = { :highlighter => '<b>\1</b>', :sanitize => false } + passed_options = options.dup + highlight("<div>abc div</div>", "div", passed_options) + assert_equal options, passed_options end def test_excerpt - assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", 5)) - assert_equal("This is a...", excerpt("This is a beautiful morning", "this", 5)) - assert_equal("...iful morning", excerpt("This is a beautiful morning", "morning", 5)) + assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", :radius => 5)) + assert_equal("This is a...", excerpt("This is a beautiful morning", "this", :radius => 5)) + assert_equal("...iful morning", excerpt("This is a beautiful morning", "morning", :radius => 5)) assert_nil excerpt("This is a beautiful morning", "day") end def test_excerpt_should_not_be_html_safe - assert !excerpt('This is a beautiful! morning', 'beautiful', 5).html_safe? + assert !excerpt('This is a beautiful! morning', 'beautiful', :radius => 5).html_safe? end def test_excerpt_in_borderline_cases - assert_equal("", excerpt("", "", 0)) - assert_equal("a", excerpt("a", "a", 0)) - assert_equal("...b...", excerpt("abc", "b", 0)) - assert_equal("abc", excerpt("abc", "b", 1)) - assert_equal("abc...", excerpt("abcd", "b", 1)) - assert_equal("...abc", excerpt("zabc", "b", 1)) - assert_equal("...abc...", excerpt("zabcd", "b", 1)) - assert_equal("zabcd", excerpt("zabcd", "b", 2)) + assert_equal("", excerpt("", "", :radius => 0)) + assert_equal("a", excerpt("a", "a", :radius => 0)) + assert_equal("...b...", excerpt("abc", "b", :radius => 0)) + assert_equal("abc", excerpt("abc", "b", :radius => 1)) + assert_equal("abc...", excerpt("abcd", "b", :radius => 1)) + assert_equal("...abc", excerpt("zabc", "b", :radius => 1)) + assert_equal("...abc...", excerpt("zabcd", "b", :radius => 1)) + assert_equal("zabcd", excerpt("zabcd", "b", :radius => 2)) # excerpt strips the resulting string before ap-/prepending excerpt_string. # whether this behavior is meaningful when excerpt_string is not to be # appended is questionable. - assert_equal("zabcd", excerpt(" zabcd ", "b", 4)) - assert_equal("...abc...", excerpt("z abc d", "b", 1)) + assert_equal("zabcd", excerpt(" zabcd ", "b", :radius => 4)) + assert_equal("...abc...", excerpt("z abc d", "b", :radius => 1)) end def test_excerpt_with_regex - assert_equal('...is a beautiful! mor...', excerpt('This is a beautiful! morning', 'beautiful', 5)) - assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', 5)) + assert_equal('...is a beautiful! mor...', excerpt('This is a beautiful! morning', 'beautiful', :radius => 5)) + assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', :radius => 5)) end - def test_excerpt_with_options_hash - assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", :radius => 5)) + def test_excerpt_with_omission assert_equal("[...]is a beautiful morn[...]", excerpt("This is a beautiful morning", "beautiful", :omission => "[...]",:radius => 5)) assert_equal( "This is the ultimate supercalifragilisticexpialidoceous very looooooooooooooooooong looooooooooooong beautiful morning with amazing sunshine and awesome tempera[...]", @@ -232,33 +253,30 @@ class TextHelperTest < ActionView::TestCase ) end - if RUBY_VERSION < '1.9' - def test_excerpt_with_utf8 - with_kcode('u') do - assert_equal("...\357\254\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped", 'could', 8)) - end - with_kcode('none') do - assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped", 'could', 8)) - end - end - else - def test_excerpt_with_utf8 - assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', 8)) - # .mb_chars always returns UTF-8, even in 1.9. This is not great, but it's how it works. Let's work this out. - # assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped".force_encoding("BINARY"), 'could', 8)) - end + def test_excerpt_with_utf8 + assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', :radius => 8)) + end + + def test_excerpt_does_not_modify_the_options_hash + options = { :omission => "[...]",:radius => 5 } + passed_options = options.dup + excerpt("This is a beautiful morning", "beautiful", passed_options) + assert_equal options, passed_options end def test_word_wrap - assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", 15)) + assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15)) end def test_word_wrap_with_extra_newlines - assert_equal("my very very\nvery long\nstring\n\nwith another\nline", word_wrap("my very very very long string\n\nwith another line", 15)) + assert_equal("my very very\nvery long\nstring\n\nwith another\nline", word_wrap("my very very very long string\n\nwith another line", :line_width => 15)) end - - def test_word_wrap_with_options_hash - assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15)) + + def test_word_wrap_does_not_modify_the_options_hash + options = { :line_width => 15 } + passed_options = options.dup + word_wrap("some text", passed_options) + assert_equal options, passed_options end def test_pluralization @@ -291,7 +309,7 @@ class TextHelperTest < ActionView::TestCase end def test_cycle_class_with_no_arguments - assert_raise(ArgumentError) { value = Cycle.new() } + assert_raise(ArgumentError) { Cycle.new } end def test_cycle @@ -304,7 +322,7 @@ class TextHelperTest < ActionView::TestCase end def test_cycle_with_no_arguments - assert_raise(ArgumentError) { value = cycle() } + assert_raise(ArgumentError) { cycle } end def test_cycle_resets_with_new_values diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb index 9b5c6d127c..97777ccff0 100644 --- a/actionpack/test/template/translation_helper_test.rb +++ b/actionpack/test/template/translation_helper_test.rb @@ -11,14 +11,20 @@ class TranslationHelperTest < ActiveSupport::TestCase :translations => { :templates => { :found => { :foo => 'Foo' }, - :array => { :foo => { :bar => 'Foo Bar' } } + :array => { :foo => { :bar => 'Foo Bar' } }, + :default => { :foo => 'Foo' } }, :foo => 'Foo', :hello => '<a>Hello World</a>', :html => '<a>Hello World</a>', :hello_html => '<a>Hello World</a>', + :interpolated_html => '<a>Hello %{word}</a>', :array_html => %w(foo bar), - :array => %w(foo bar) + :array => %w(foo bar), + :count_html => { + :one => '<a>One %{count}</a>', + :other => '<a>Other %{count}</a>' + } } ) @view = ::ActionView::Base.new(ActionController::Base.view_paths, {}) @@ -38,11 +44,19 @@ class TranslationHelperTest < ActiveSupport::TestCase def test_returns_missing_translation_message_wrapped_into_span expected = '<span class="translation_missing" title="translation missing: en.translations.missing">Missing</span>' assert_equal expected, translate(:"translations.missing") + assert_equal true, translate(:"translations.missing").html_safe? end def test_returns_missing_translation_message_using_nil_as_rescue_format expected = 'translation missing: en.translations.missing' assert_equal expected, translate(:"translations.missing", :rescue_format => nil) + assert_equal false, translate(:"translations.missing", :rescue_format => nil).html_safe? + end + + def test_i18n_translate_defaults_to_nil_rescue_format + expected = 'translation missing: en.translations.missing' + assert_equal expected, I18n.translate(:"translations.missing") + assert_equal false, I18n.translate(:"translations.missing").html_safe? end def test_translation_returning_an_array @@ -58,6 +72,10 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal 'Foo Bar', @view.render(:file => 'translations/templates/array').strip end + def test_default_lookup_scoped_by_partial + assert_equal 'Foo', view.render(:file => 'translations/templates/default').strip + end + def test_missing_translation_scoped_by_partial expected = '<span class="translation_missing" title="translation missing: en.translations.templates.missing.missing">Missing</span>' assert_equal expected, view.render(:file => 'translations/templates/missing').strip @@ -75,7 +93,36 @@ class TranslationHelperTest < ActiveSupport::TestCase assert translate(:'translations.hello_html').html_safe? end + def test_translate_escapes_interpolations_in_translations_with_a_html_suffix + assert_equal '<a>Hello <World></a>', translate(:'translations.interpolated_html', :word => '<World>') + assert_equal '<a>Hello <World></a>', translate(:'translations.interpolated_html', :word => stub(:to_s => "<World>")) + end + + def test_translate_with_html_count + assert_equal '<a>One 1</a>', translate(:'translations.count_html', :count => 1) + assert_equal '<a>Other 2</a>', translate(:'translations.count_html', :count => 2) + assert_equal '<a>Other <One></a>', translate(:'translations.count_html', :count => '<One>') + end + def test_translation_returning_an_array_ignores_html_suffix assert_equal ["foo", "bar"], translate(:'translations.array_html') end + + def test_translate_with_default_named_html + translation = translate(:'translations.missing', :default => :'translations.hello_html') + assert_equal '<a>Hello World</a>', translation + assert translation.html_safe? + end + + def test_translate_with_two_defaults_named_html + translation = translate(:'translations.missing', :default => [:'translations.missing_html', :'translations.hello_html']) + assert_equal '<a>Hello World</a>', translation + assert translation.html_safe? + end + + def test_translate_with_last_default_named_html + translation = translate(:'translations.missing', :default => [:'translations.missing', :'translations.hello_html']) + assert_equal '<a>Hello World</a>', translation + assert translation.html_safe? + end end diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 8d0f0124c2..fb5b35bac6 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -1,6 +1,5 @@ # encoding: utf-8 require 'abstract_unit' -require 'active_support/ordered_hash' require 'controller/fake_controllers' class UrlHelperTest < ActiveSupport::TestCase @@ -11,10 +10,14 @@ class UrlHelperTest < ActiveSupport::TestCase # In those cases, we'll set up a simple mock attr_accessor :controller, :request + cattr_accessor :request_forgery + self.request_forgery = false + routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/" => "foo#bar" - match "/other" => "foo#other" + get "/" => "foo#bar" + get "/other" => "foo#other" + get "/article/:id" => "foo#article", :as => :article end include routes.url_helpers @@ -25,13 +28,15 @@ class UrlHelperTest < ActiveSupport::TestCase include ActionView::Context include RenderERBUtils - def hash_for(opts = []) - ActiveSupport::OrderedHash[*([:controller, "foo", :action, "bar"].concat(opts))] + setup :_prepare_context + + def hash_for(options = {}) + { :controller => "foo", :action => "bar" }.merge!(options) end alias url_hash hash_for def test_url_for_does_not_escape_urls - assert_equal "/?a=b&c=d", url_for(hash_for([:a, :b, :c, :d])) + assert_equal "/?a=b&c=d", url_for(hash_for(:a => :b, :c => :d)) end def test_url_for_with_back @@ -46,11 +51,22 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal 'javascript:history.back()', url_for(:back) end - # todo: missing test cases + # TODO: missing test cases def test_button_to_with_straight_url assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com") end + def test_button_to_with_straight_url_and_request_forgery + self.request_forgery = true + + assert_dom_equal( + %{<form method="post" action="http://www.example.com" class="button_to"><div><input type="submit" value="Hello" /><input name="form_token" type="hidden" value="secret" /></div></form>}, + button_to("Hello", "http://www.example.com") + ) + ensure + self.request_forgery = false + end + def test_button_to_with_form_class assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"custom-class\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com", :form_class => 'custom-class') end @@ -81,10 +97,14 @@ class UrlHelperTest < ActiveSupport::TestCase def test_button_to_with_javascript_disable_with assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :disable_with => "Greeting...") + button_to("Hello", "http://www.example.com", 'data-disable-with' => "Greeting...") ) end + def test_button_to_with_remote_and_form_options + assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"custom-class\" data-remote=\"true\" data-type=\"json\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com", :remote => true, :form => { :class => "custom-class", "data-type" => "json" } ) + end + def test_button_to_with_remote_and_javascript_confirm assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", @@ -92,20 +112,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_button_to_with_remote_and_javascript_disable_with - assert_dom_equal( - "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :remote => true, :disable_with => "Greeting...") - ) - end - - def test_button_to_with_remote_and_javascript_confirm_and_javascript_disable_with - assert_dom_equal( - "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :remote => true, :confirm => "Are you sure?", :disable_with => "Greeting...") - ) - end - def test_button_to_with_remote_false assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", @@ -147,7 +153,7 @@ class UrlHelperTest < ActiveSupport::TestCase end def test_link_tag_with_host_option - hash = hash_for([:host, "www.example.com"]) + hash = hash_for(:host => "www.example.com") expected = %q{<a href="http://www.example.com/">Test Link</a>} assert_dom_equal(expected, link_to('Test Link', hash)) end @@ -242,6 +248,13 @@ class UrlHelperTest < ActiveSupport::TestCase ) end + def test_link_tag_using_post_javascript_and_rel + assert_dom_equal( + "<a href='http://www.example.com' data-method=\"post\" rel=\"example nofollow\">Hello</a>", + link_to("Hello", "http://www.example.com", :method => :post, :rel => 'example') + ) + end + def test_link_tag_using_post_javascript_and_confirm assert_dom_equal( "<a href=\"http://www.example.com\" data-method=\"post\" rel=\"nofollow\" data-confirm=\"Are you serious?\">Hello</a>", @@ -262,6 +275,13 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal '<a href="/">Example site</a>', out end + def test_link_tag_with_html_safe_string + assert_dom_equal( + "<a href=\"/article/Gerd_M%C3%BCller\">Gerd Müller</a>", + link_to("Gerd Müller", article_path("Gerd_Müller".html_safe)) + ) + end + def test_link_to_unless assert_equal "Showing", link_to_unless(true, "Showing", url_hash) @@ -287,8 +307,8 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal "Showing", link_to_if(false, "Showing", url_hash) end - def request_for_url(url) - env = Rack::MockRequest.env_for("http://www.example.com#{url}") + def request_for_url(url, opts = {}) + env = Rack::MockRequest.env_for("http://www.example.com#{url}", opts) ActionDispatch::Request.new(env) end @@ -308,10 +328,16 @@ class UrlHelperTest < ActiveSupport::TestCase def test_current_page_with_params_that_match @request = request_for_url("/?order=desc&page=1") - assert current_page?(hash_for([:order, "desc", :page, "1"])) + assert current_page?(hash_for(:order => "desc", :page => "1")) assert current_page?("http://www.example.com/?order=desc&page=1") end + def test_current_page_with_not_get_verb + @request = request_for_url("/events", :method => :post) + + assert !current_page?('/events') + end + def test_link_unless_current @request = request_for_url("/") @@ -330,20 +356,20 @@ class UrlHelperTest < ActiveSupport::TestCase @request = request_for_url("/?order=desc&page=1") assert_equal "Showing", - link_to_unless_current("Showing", hash_for([:order, 'desc', :page, '1'])) + link_to_unless_current("Showing", hash_for(:order => 'desc', :page => '1')) assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/?order=desc&page=1") @request = request_for_url("/?order=desc") assert_equal %{<a href="/?order=asc">Showing</a>}, - link_to_unless_current("Showing", hash_for([:order, :asc])) + link_to_unless_current("Showing", hash_for(:order => :asc)) assert_equal %{<a href="http://www.example.com/?order=asc">Showing</a>}, link_to_unless_current("Showing", "http://www.example.com/?order=asc") @request = request_for_url("/?order=desc") assert_equal %{<a href="/?order=desc&page=2\">Showing</a>}, - link_to_unless_current("Showing", hash_for([:order, "desc", :page, 2])) + link_to_unless_current("Showing", hash_for(:order => "desc", :page => 2)) assert_equal %{<a href="http://www.example.com/?order=desc&page=2">Showing</a>}, link_to_unless_current("Showing", "http://www.example.com/?order=desc&page=2") @@ -368,14 +394,12 @@ class UrlHelperTest < ActiveSupport::TestCase def test_mail_to_with_javascript snippet = mail_to("me@domain.com", "My email", :encode => "javascript") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet - assert snippet.html_safe? + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet end def test_mail_to_with_javascript_unicode snippet = mail_to("unicode@example.com", "únicode", :encode => "javascript") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet - assert snippet.html_safe + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet end def test_mail_with_options @@ -400,13 +424,26 @@ class UrlHelperTest < ActiveSupport::TestCase assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain.com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain(dot)com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + end + + def test_mail_to_returns_html_safe_string + assert mail_to("david@loudthinking.com").html_safe? + assert mail_to("me@domain.com", "My email", :encode => "javascript").html_safe? + assert mail_to("me@domain.com", "My email", :encode => "hex").html_safe? end - # TODO: button_to looks at this ... why? def protect_against_forgery? - false + self.request_forgery + end + + def form_authenticity_token + "secret" + end + + def request_forgery_protection_token + "form_token" end private @@ -420,25 +457,25 @@ end class UrlHelperControllerTest < ActionController::TestCase class UrlHelperController < ActionController::Base test_routes do - match 'url_helper_controller_test/url_helper/show/:id', + get 'url_helper_controller_test/url_helper/show/:id', :to => 'url_helper_controller_test/url_helper#show', :as => :show - match 'url_helper_controller_test/url_helper/profile/:name', + get 'url_helper_controller_test/url_helper/profile/:name', :to => 'url_helper_controller_test/url_helper#show', :as => :profile - match 'url_helper_controller_test/url_helper/show_named_route', + get 'url_helper_controller_test/url_helper/show_named_route', :to => 'url_helper_controller_test/url_helper#show_named_route', :as => :show_named_route - match "/:controller(/:action(/:id))" + get "/:controller(/:action(/:id))" - match 'url_helper_controller_test/url_helper/normalize_recall_params', + get 'url_helper_controller_test/url_helper/normalize_recall_params', :to => UrlHelperController.action(:normalize_recall), :as => :normalize_recall_params - match '/url_helper_controller_test/url_helper/override_url_helper/default', + get '/url_helper_controller_test/url_helper/override_url_helper/default', :to => 'url_helper_controller_test/url_helper#override_url_helper', :as => :override_url_helper end @@ -475,8 +512,6 @@ class UrlHelperControllerTest < ActionController::TestCase render :inline => '<%= url_for(:action => :show_url_for) %>' end - def rescue_action(e) raise e end - def override_url_helper render :inline => '<%= override_url_helper_path %>' end @@ -517,7 +552,7 @@ class UrlHelperControllerTest < ActionController::TestCase def test_named_route_should_show_host_and_path_using_controller_default_url_options class << @controller - def default_url_options(options = nil) + def default_url_options {:host => 'testtwo.host'} end end @@ -564,8 +599,6 @@ class TasksController < ActionController::Base render_default end - def rescue_action(e) raise e end - protected def render_default render :inline => @@ -624,8 +657,6 @@ class WorkshopsController < ActionController::Base @workshop = Workshop.new(params[:id]) render :inline => "<%= url_for(@workshop) %>\n<%= link_to('Workshop', @workshop) %>" end - - def rescue_action(e) raise e end end class SessionsController < ActionController::Base @@ -646,8 +677,6 @@ class SessionsController < ActionController::Base @session = Session.new(params[:id]) render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" end - - def rescue_action(e) raise e end end class PolymorphicControllerTest < ActionController::TestCase diff --git a/actionpack/test/ts_isolated.rb b/actionpack/test/ts_isolated.rb index 5670d93613..c44c5d8968 100644 --- a/actionpack/test/ts_isolated.rb +++ b/actionpack/test/ts_isolated.rb @@ -1,17 +1,15 @@ -$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') - -require 'test/unit' +require 'minitest/autorun' require 'rbconfig' -require 'active_support/core_ext/kernel/reporting' +require 'abstract_unit' -class TestIsolated < Test::Unit::TestCase +class TestIsolated < ActiveSupport::TestCase ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) Dir["#{File.dirname(__FILE__)}/{abstract,controller,dispatch,template}/**/*_test.rb"].each do |file| define_method("test #{file}") do command = "#{ruby} -Ilib:test #{file}" result = silence_stderr { `#{command}` } - assert_block("#{command}\n#{result}") { $?.to_i.zero? } + assert $?.to_i.zero?, "#{command}\n#{result}" end end end |