diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index 8dd2e443ae3ae64b3517906a2d1fdcb1b3e9e944..8e6c81b375c25ce9f3109e06618683a8dc4c4dee 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -72,10 +72,16 @@ def assign_parameters(controller_path, action, parameters) extra_keys = ActionController::Routing::Routes.extra_keys(parameters) non_path_parameters = get? ? query_parameters : request_parameters parameters.each do |key, value| + if value.is_a? Fixnum + value = value.to_s + elsif value.is_a? Array + value = ActionController::Routing::PathComponent::Result.new(value) + end + if extra_keys.include?(key.to_sym) non_path_parameters[key] = value else - path_parameters[key] = value.is_a?(Fixnum) ? value.to_s : value + path_parameters[key.to_s] = value end end end @@ -352,6 +358,36 @@ def method_missing(selector, *args) return @controller.send(selector, *args) if ActionController::Routing::NamedRoutes::Helpers.include?(selector) return super end + + # A helper to make it easier to test different route configurations. + # This method temporarily replaces ActionController::Routing::Routes + # with a new RouteSet instance. + # + # The new instance is yielded to the passed block. Typically the block + # will create some routes using map.draw { map.connect ... }: + # + # with_routing do |set| + # set.draw { set.connect ':controller/:id/:action' } + # assert_equal( + # ['/content/10/show', {}], + # set.generate(:controller => 'content', :id => 10, :action => 'show') + # ) + # end + # + def with_routing + real_routes = ActionController::Routing::Routes + ActionController::Routing.send :remove_const, :Routes + + temporary_routes = ActionController::Routing::RouteSet.new + ActionController::Routing.send :const_set, :Routes, temporary_routes + + yield temporary_routes + ensure + if ActionController::Routing.const_defined? :Routes + ActionController::Routing.send(:remove_const, :Routes) + end + ActionController::Routing.const_set(:Routes, real_routes) if real_routes + end end end end diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index 996c3c6cc2e9e610d42fe6a830c6099e54b1028c..201fe03b448010705495fc1d1cf4fa015c6156d8 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -114,10 +114,44 @@ def test_params_passing ) end - def test_path_params_are_strings + def test_id_converted_to_string get :test_params, :id => 20, :foo => Object.new - @request.path_parameters.each do |key, value| - assert_kind_of String, value + assert_kind_of String, @request.path_parameters['id'] + end + + def test_array_path_parameter_handled_properly + with_routing do |set| + set.draw do + set.connect 'file/*path', :controller => 'test_test/test', :action => 'test_params' + set.connect ':controller/:action/:id' + end + + get :test_params, :path => ['hello', 'world'] + assert_equal ['hello', 'world'], @request.path_parameters['path'] + assert_equal 'hello/world', @request.path_parameters['path'].to_s + end + end + + def test_assert_realistic_path_parameters + get :test_params, :id => 20, :foo => Object.new + + # All elements of path_parameters should use string keys + @request.path_parameters.keys.each do |key| + assert_kind_of String, key + end + end + + def test_with_routing_places_routes_back + assert ActionController::Routing::Routes + routes_id = ActionController::Routing::Routes.object_id + + begin + with_routing { raise 'fail' } + fail 'Should not be here.' + rescue RuntimeError end + + assert ActionController::Routing::Routes + assert_equal routes_id, ActionController::Routing::Routes.object_id end end