diff options
Diffstat (limited to 'actionpack/test')
124 files changed, 1746 insertions, 849 deletions
diff --git a/actionpack/test/abstract/collector_test.rb b/actionpack/test/abstract/collector_test.rb index b1a5044399..fc59bf19c4 100644 --- a/actionpack/test/abstract/collector_test.rb +++ b/actionpack/test/abstract/collector_test.rb @@ -24,15 +24,21 @@ module AbstractController test "does not respond to unknown mime types" do collector = MyCollector.new - assert !collector.respond_to?(:unknown) + assert_not_respond_to collector, :unknown end test "register mime types on method missing" do AbstractController::Collector.send(:remove_method, :js) - collector = MyCollector.new - assert !collector.respond_to?(:js) - collector.js - assert_respond_to collector, :js + begin + collector = MyCollector.new + assert_not_respond_to collector, :js + collector.js + assert_respond_to collector, :js + ensure + unless AbstractController::Collector.method_defined? :js + AbstractController::Collector.generate_method_for_mime :js + end + end end test "does not register unknown mime types" do diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 03a4741f42..4e17d57dad 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -15,6 +15,12 @@ silence_warnings do Encoding.default_external = "UTF-8" end +require 'drb' +require 'drb/unix' +require 'tempfile' + +PROCESS_COUNT = (ENV['N'] || 4).to_i + require 'active_support/testing/autorun' require 'abstract_controller' require 'action_controller' @@ -105,6 +111,9 @@ end module ActiveSupport class TestCase include ActionDispatch::DrawOnce + if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0 + parallelize_me! + end end end @@ -251,7 +260,6 @@ end module ActionController class Base - include ActionController::Testing # This stub emulates the Railtie including the URL helpers from a Rails application include SharedTestRoutes.url_helpers include SharedTestRoutes.mounted_helpers @@ -306,22 +314,95 @@ end module ActionDispatch module RoutingVerbs - def get(uri_or_host, path = nil) + def send_request(uri_or_host, method, path) host = uri_or_host.host unless path path ||= uri_or_host.path params = {'PATH_INFO' => path, - 'REQUEST_METHOD' => 'GET', + 'REQUEST_METHOD' => method, 'HTTP_HOST' => host} - routes.call(params)[2].join + routes.call(params) + end + + def request_path_params(path, options = {}) + method = options[:method] || 'GET' + resp = send_request URI('http://localhost' + path), method.to_s.upcase, nil + status = resp.first + if status == 404 + raise ActionController::RoutingError, "No route matches #{path.inspect}" + end + controller.request.path_parameters + end + + def get(uri_or_host, path = nil) + send_request(uri_or_host, 'GET', path)[2].join + end + + def post(uri_or_host, path = nil) + send_request(uri_or_host, 'POST', path)[2].join + end + + def put(uri_or_host, path = nil) + send_request(uri_or_host, 'PUT', path)[2].join + end + + def delete(uri_or_host, path = nil) + send_request(uri_or_host, 'DELETE', path)[2].join + end + + def patch(uri_or_host, path = nil) + send_request(uri_or_host, 'PATCH', path)[2].join end end end module RoutingTestHelpers - def url_for(set, options, recall = nil) - set.send(:url_for, options.merge(:only_path => true, :_recall => recall)) + def url_for(set, options) + route_name = options.delete :use_route + set.url_for options.merge(:only_path => true), route_name + end + + def make_set(strict = true) + tc = self + TestSet.new ->(c) { tc.controller = c }, strict + end + + class TestSet < ActionDispatch::Routing::RouteSet + attr_reader :strict + + def initialize(block, strict = false) + @block = block + @strict = strict + super() + end + + class Dispatcher < ActionDispatch::Routing::RouteSet::Dispatcher + def initialize(defaults, set, block) + super(defaults) + @block = block + @set = set + end + + def controller(params, default_controller=true) + super(params, @set.strict) + end + + def controller_reference(controller_param) + block = @block + set = @set + super if @set.strict + Class.new(ActionController::Base) { + include set.url_helpers + define_method(:process) { |name| block.call(self) } + def to_a; [200, {}, []]; end + } + end + end + + def dispatcher defaults + TestSet::Dispatcher.new defaults, self, @block + end end end @@ -360,3 +441,59 @@ end def jruby_skip(message = '') skip message if defined?(JRUBY_VERSION) end + +require 'mocha/setup' # FIXME: stop using mocha + +class ForkingExecutor + class Server + include DRb::DRbUndumped + + def initialize + @queue = Queue.new + end + + def record reporter, result + reporter.record result + end + + def << o + o[2] = DRbObject.new(o[2]) if o + @queue << o + end + def pop; @queue.pop; end + end + + def initialize size + @size = size + @queue = Server.new + file = File.join Dir.tmpdir, Dir::Tmpname.make_tmpname('tests', 'fd') + @url = "drbunix://#{file}" + @pool = nil + DRb.start_service @url, @queue + end + + def << work; @queue << work; end + + def shutdown + pool = @size.times.map { + fork { + DRb.stop_service + queue = DRbObject.new_with_uri @url + while job = queue.pop + klass = job[0] + method = job[1] + reporter = job[2] + result = Minitest.run_one_method klass, method + queue.record reporter, result + end + } + } + @size.times { @queue << nil } + pool.each { |pid| Process.waitpid pid } + end +end + +if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0 + # Use N processes (N defaults to 4) + Minitest.parallel_executor = ForkingExecutor.new(PROCESS_COUNT) +end diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index 580604df3a..f07d201563 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -56,13 +56,16 @@ class AssertSelectTest < ActionController::TestCase def setup super + @old_delivery_method = ActionMailer::Base.delivery_method + @old_perform_deliveries = ActionMailer::Base.perform_deliveries ActionMailer::Base.delivery_method = :test ActionMailer::Base.perform_deliveries = true - ActionMailer::Base.deliveries = [] end def teardown super + ActionMailer::Base.delivery_method = @old_delivery_method + ActionMailer::Base.perform_deliveries = @old_perform_deliveries ActionMailer::Base.deliveries.clear end diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 58a86ce9af..c0e6a2ebd1 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -227,6 +227,22 @@ CACHED @store.read("views/test.host/functional_caching/inline_fragment_cached/#{template_digest("functional_caching/inline_fragment_cached")}")) end + def test_fragment_cache_instrumentation + payload = nil + + subscriber = proc do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + payload = event.payload + end + + ActiveSupport::Notifications.subscribed(subscriber, "read_fragment.action_controller") do + get :inline_fragment_cached + end + + assert_equal "functional_caching", payload[:controller] + assert_equal "inline_fragment_cached", payload[:action] + end + def test_html_formatted_fragment_caching get :formatted_fragment_cached, :format => "html" assert_response :success diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index 03d5d27cf4..89667df3a4 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -68,12 +68,11 @@ class ContentTypeTest < ActionController::TestCase end def test_render_changed_charset_default - ActionDispatch::Response.default_charset = "utf-16" - get :render_defaults - assert_equal "utf-16", @response.charset - assert_equal Mime::HTML, @response.content_type - ensure - ActionDispatch::Response.default_charset = "utf-8" + with_default_charset "utf-16" do + get :render_defaults + assert_equal "utf-16", @response.charset + assert_equal Mime::HTML, @response.content_type + end end # :ported: @@ -105,12 +104,11 @@ class ContentTypeTest < ActionController::TestCase end def test_nil_default_for_erb - 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 - ActionDispatch::Response.default_charset = "utf-8" + with_default_charset nil do + get :render_default_for_erb + assert_equal Mime::HTML, @response.content_type + assert_nil @response.charset, @response.headers.inspect + end end def test_default_for_erb @@ -130,6 +128,16 @@ class ContentTypeTest < ActionController::TestCase assert_equal Mime::HTML, @response.content_type assert_equal "utf-8", @response.charset end + + private + + def with_default_charset(charset) + old_default_charset = ActionDispatch::Response.default_charset + ActionDispatch::Response.default_charset = charset + yield + ensure + ActionDispatch::Response.default_charset = old_default_charset + end end class AcceptBasedContentTypeTest < ActionController::TestCase diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index c87494aa64..b2b01b3fa9 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -2,13 +2,13 @@ require 'abstract_unit' class ActionController::Base class << self - %w(append_around_filter prepend_after_filter prepend_around_filter prepend_before_filter skip_after_filter skip_before_filter skip_filter).each do |pending| + %w(append_around_action prepend_after_action prepend_around_action prepend_before_action skip_after_action skip_before_action skip_action_callback).each do |pending| define_method(pending) do |*args| $stderr.puts "#{pending} unimplemented: #{args.inspect}" end unless method_defined?(pending) end - def before_filters + def before_actions filters = _process_action_callbacks.select { |c| c.kind == :before } filters.map! { |c| c.raw_filter } end @@ -28,8 +28,8 @@ end class FilterTest < ActionController::TestCase class TestController < ActionController::Base - before_filter :ensure_login - after_filter :clean_up + before_action :ensure_login + after_action :clean_up def show render :inline => "ran action" @@ -42,13 +42,13 @@ class FilterTest < ActionController::TestCase end def clean_up - @ran_after_filter ||= [] - @ran_after_filter << "clean_up" + @ran_after_action ||= [] + @ran_after_action << "clean_up" end end class ChangingTheRequirementsController < TestController - before_filter :ensure_login, :except => [:go_wild] + before_action :ensure_login, :except => [:go_wild] def go_wild render :text => "gobble" @@ -56,9 +56,9 @@ class FilterTest < ActionController::TestCase end class TestMultipleFiltersController < ActionController::Base - before_filter :try_1 - before_filter :try_2 - before_filter :try_3 + before_action :try_1 + before_action :try_2 + before_action :try_3 (1..3).each do |i| define_method "fail_#{i}" do @@ -78,8 +78,8 @@ class FilterTest < ActionController::TestCase end class RenderingController < ActionController::Base - before_filter :before_filter_rendering - after_filter :unreached_after_filter + before_action :before_action_rendering + after_action :unreached_after_action def show @ran_action = true @@ -87,29 +87,29 @@ class FilterTest < ActionController::TestCase end private - def before_filter_rendering + def before_action_rendering @ran_filter ||= [] - @ran_filter << "before_filter_rendering" + @ran_filter << "before_action_rendering" render :inline => "something else" end - def unreached_after_filter - @ran_filter << "unreached_after_filter_after_render" + def unreached_after_action + @ran_filter << "unreached_after_action_after_render" end end - class RenderingForPrependAfterFilterController < RenderingController - prepend_after_filter :unreached_prepend_after_filter + class RenderingForPrependAfterActionController < RenderingController + prepend_after_action :unreached_prepend_after_action private - def unreached_prepend_after_filter - @ran_filter << "unreached_preprend_after_filter_after_render" + def unreached_prepend_after_action + @ran_filter << "unreached_preprend_after_action_after_render" end end - class BeforeFilterRedirectionController < ActionController::Base - before_filter :before_filter_redirects - after_filter :unreached_after_filter + class BeforeActionRedirectionController < ActionController::Base + before_action :before_action_redirects + after_action :unreached_after_action def show @ran_action = true @@ -122,23 +122,23 @@ class FilterTest < ActionController::TestCase end private - def before_filter_redirects + def before_action_redirects @ran_filter ||= [] - @ran_filter << "before_filter_redirects" + @ran_filter << "before_action_redirects" redirect_to(:action => 'target_of_redirection') end - def unreached_after_filter - @ran_filter << "unreached_after_filter_after_redirection" + def unreached_after_action + @ran_filter << "unreached_after_action_after_redirection" end end - class BeforeFilterRedirectionForPrependAfterFilterController < BeforeFilterRedirectionController - prepend_after_filter :unreached_prepend_after_filter_after_redirection + class BeforeActionRedirectionForPrependAfterActionController < BeforeActionRedirectionController + prepend_after_action :unreached_prepend_after_action_after_redirection private - def unreached_prepend_after_filter_after_redirection - @ran_filter << "unreached_prepend_after_filter_after_redirection" + def unreached_prepend_after_action_after_redirection + @ran_filter << "unreached_prepend_after_action_after_redirection" end end @@ -151,8 +151,8 @@ class FilterTest < ActionController::TestCase render :inline => "ran action" end - def show_without_filter - render :inline => "ran action without filter" + def show_without_action + render :inline => "ran action without action" end private @@ -168,70 +168,70 @@ class FilterTest < ActionController::TestCase end class ConditionalCollectionFilterController < ConditionalFilterController - before_filter :ensure_login, :except => [ :show_without_filter, :another_action ] + before_action :ensure_login, :except => [ :show_without_action, :another_action ] end class OnlyConditionSymController < ConditionalFilterController - before_filter :ensure_login, :only => :show + before_action :ensure_login, :only => :show end class ExceptConditionSymController < ConditionalFilterController - before_filter :ensure_login, :except => :show_without_filter + before_action :ensure_login, :except => :show_without_action end class BeforeAndAfterConditionController < ConditionalFilterController - before_filter :ensure_login, :only => :show - after_filter :clean_up_tmp, :only => :show + before_action :ensure_login, :only => :show + after_action :clean_up_tmp, :only => :show end class OnlyConditionProcController < ConditionalFilterController - before_filter(:only => :show) {|c| c.instance_variable_set(:"@ran_proc_filter", true) } + before_action(:only => :show) {|c| c.instance_variable_set(:"@ran_proc_action", true) } end class ExceptConditionProcController < ConditionalFilterController - before_filter(:except => :show_without_filter) {|c| c.instance_variable_set(:"@ran_proc_filter", true) } + before_action(:except => :show_without_action) {|c| c.instance_variable_set(:"@ran_proc_action", true) } end class ConditionalClassFilter - def self.before(controller) controller.instance_variable_set(:"@ran_class_filter", true) end + def self.before(controller) controller.instance_variable_set(:"@ran_class_action", true) end end class OnlyConditionClassController < ConditionalFilterController - before_filter ConditionalClassFilter, :only => :show + before_action ConditionalClassFilter, :only => :show end class ExceptConditionClassController < ConditionalFilterController - before_filter ConditionalClassFilter, :except => :show_without_filter + before_action ConditionalClassFilter, :except => :show_without_action end class AnomolousYetValidConditionController < ConditionalFilterController - before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.instance_variable_set(:"@ran_proc_filter1", true)}, :except => :show_without_filter) { |c| c.instance_variable_set(:"@ran_proc_filter2", true)} + before_action(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.instance_variable_set(:"@ran_proc_action1", true)}, :except => :show_without_action) { |c| c.instance_variable_set(:"@ran_proc_action2", true)} end class OnlyConditionalOptionsFilter < ConditionalFilterController - before_filter :ensure_login, :only => :index, :if => Proc.new {|c| c.instance_variable_set(:"@ran_conditional_index_proc", true) } + before_action :ensure_login, :only => :index, :if => Proc.new {|c| c.instance_variable_set(:"@ran_conditional_index_proc", true) } end class ConditionalOptionsFilter < ConditionalFilterController - before_filter :ensure_login, :if => Proc.new { |c| true } - before_filter :clean_up_tmp, :if => Proc.new { |c| false } + before_action :ensure_login, :if => Proc.new { |c| true } + before_action :clean_up_tmp, :if => Proc.new { |c| false } end class ConditionalOptionsSkipFilter < ConditionalFilterController - before_filter :ensure_login - before_filter :clean_up_tmp + before_action :ensure_login + before_action :clean_up_tmp - skip_before_filter :ensure_login, if: -> { false } - skip_before_filter :clean_up_tmp, if: -> { true } + skip_before_action :ensure_login, if: -> { false } + skip_before_action :clean_up_tmp, if: -> { true } end class ClassController < ConditionalFilterController - before_filter ConditionalClassFilter + before_action ConditionalClassFilter end class PrependingController < TestController - prepend_before_filter :wonderful_life - # skip_before_filter :fire_flash + prepend_before_action :wonderful_life + # skip_before_action :fire_flash private def wonderful_life @@ -241,8 +241,8 @@ class FilterTest < ActionController::TestCase end class SkippingAndLimitedController < TestController - skip_before_filter :ensure_login - before_filter :ensure_login, :only => :index + skip_before_action :ensure_login + before_action :ensure_login, :only => :index def index render :text => 'ok' @@ -254,9 +254,9 @@ class FilterTest < ActionController::TestCase end class SkippingAndReorderingController < TestController - skip_before_filter :ensure_login - before_filter :find_record - before_filter :ensure_login + skip_before_action :ensure_login + before_action :find_record + before_action :ensure_login def index render :text => 'ok' @@ -270,10 +270,10 @@ class FilterTest < ActionController::TestCase end class ConditionalSkippingController < TestController - skip_before_filter :ensure_login, :only => [ :login ] - skip_after_filter :clean_up, :only => [ :login ] + skip_before_action :ensure_login, :only => [ :login ] + skip_after_action :clean_up, :only => [ :login ] - before_filter :find_user, :only => [ :change_password ] + before_action :find_user, :only => [ :change_password ] def login render :inline => "ran action" @@ -291,8 +291,8 @@ class FilterTest < ActionController::TestCase end class ConditionalParentOfConditionalSkippingController < ConditionalFilterController - before_filter :conditional_in_parent_before, :only => [:show, :another_action] - after_filter :conditional_in_parent_after, :only => [:show, :another_action] + before_action :conditional_in_parent_before, :only => [:show, :another_action] + after_action :conditional_in_parent_after, :only => [:show, :another_action] private @@ -308,20 +308,20 @@ class FilterTest < ActionController::TestCase end class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController - skip_before_filter :conditional_in_parent_before, :only => :another_action - skip_after_filter :conditional_in_parent_after, :only => :another_action + skip_before_action :conditional_in_parent_before, :only => :another_action + skip_after_action :conditional_in_parent_after, :only => :another_action end class AnotherChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController - skip_before_filter :conditional_in_parent_before, :only => :show + skip_before_action :conditional_in_parent_before, :only => :show end class ProcController < PrependingController - before_filter(proc { |c| c.instance_variable_set(:"@ran_proc_filter", true) }) + before_action(proc { |c| c.instance_variable_set(:"@ran_proc_action", true) }) end class ImplicitProcController < PrependingController - before_filter { |c| c.instance_variable_set(:"@ran_proc_filter", true) } + before_action { |c| c.instance_variable_set(:"@ran_proc_action", true) } end class AuditFilter @@ -367,7 +367,7 @@ class FilterTest < ActionController::TestCase end class AuditController < ActionController::Base - before_filter(AuditFilter) + before_action(AuditFilter) def show render :text => "hello" @@ -375,14 +375,14 @@ class FilterTest < ActionController::TestCase end class AroundFilterController < PrependingController - around_filter AroundFilter.new + around_action AroundFilter.new end class BeforeAfterClassFilterController < PrependingController begin filter = AroundFilter.new - before_filter filter - after_filter filter + before_action filter + after_action filter end end @@ -394,18 +394,18 @@ class FilterTest < ActionController::TestCase super() end - before_filter { |c| c.class.execution_log << " before procfilter " } - prepend_around_filter AroundFilter.new + before_action { |c| c.class.execution_log << " before procfilter " } + prepend_around_action AroundFilter.new - after_filter { |c| c.class.execution_log << " after procfilter " } - append_around_filter AppendedAroundFilter.new + after_action { |c| c.class.execution_log << " after procfilter " } + append_around_action AppendedAroundFilter.new end class MixedSpecializationController < ActionController::Base class OutOfOrder < StandardError; end - before_filter :first - before_filter :second, :only => :foo + before_action :first + before_action :second, :only => :foo def foo render :text => 'foo' @@ -426,7 +426,7 @@ class FilterTest < ActionController::TestCase end class DynamicDispatchController < ActionController::Base - before_filter :choose + before_action :choose %w(foo bar baz).each do |action| define_method(action) { render :text => action } @@ -439,9 +439,9 @@ class FilterTest < ActionController::TestCase end class PrependingBeforeAndAfterController < ActionController::Base - prepend_before_filter :before_all - prepend_after_filter :after_all - before_filter :between_before_all_and_after_all + prepend_before_action :before_all + prepend_after_action :after_all + before_action :between_before_all_and_after_all def before_all @ran_filter ||= [] @@ -473,7 +473,7 @@ class FilterTest < ActionController::TestCase end class RescuedController < ActionController::Base - around_filter RescuingAroundFilterWithBlock.new + around_action RescuingAroundFilterWithBlock.new def show raise ErrorToRescue.new("Something made the bad noise.") @@ -482,10 +482,10 @@ class FilterTest < ActionController::TestCase class NonYieldingAroundFilterController < ActionController::Base - before_filter :filter_one - around_filter :non_yielding_filter - before_filter :filter_two - after_filter :filter_three + before_action :filter_one + around_action :non_yielding_action + before_action :action_two + after_action :action_three def index render :inline => "index" @@ -498,24 +498,24 @@ class FilterTest < ActionController::TestCase @filters << "filter_one" end - def filter_two - @filters << "filter_two" + def action_two + @filters << "action_two" end - def non_yielding_filter + def non_yielding_action @filters << "it didn't yield" @filter_return_value end - def filter_three - @filters << "filter_three" + def action_three + @filters << "action_three" end end class ImplicitActionsController < ActionController::Base - before_filter :find_only, :only => :edit - before_filter :find_except, :except => :edit + before_action :find_only, :only => :edit + before_action :find_except, :except => :edit private @@ -528,7 +528,7 @@ class FilterTest < ActionController::TestCase end end - def test_non_yielding_around_filters_not_returning_false_do_not_raise + def test_non_yielding_around_actions_not_returning_false_do_not_raise controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", true assert_nothing_raised do @@ -536,7 +536,7 @@ class FilterTest < ActionController::TestCase end end - def test_non_yielding_around_filters_returning_false_do_not_raise + def test_non_yielding_around_actions_returning_false_do_not_raise controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", false assert_nothing_raised do @@ -544,64 +544,64 @@ class FilterTest < ActionController::TestCase end end - def test_after_filters_are_not_run_if_around_filter_returns_false + def test_after_actions_are_not_run_if_around_action_returns_false controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", false test_process(controller, "index") assert_equal ["filter_one", "it didn't yield"], controller.assigns['filters'] end - def test_after_filters_are_not_run_if_around_filter_does_not_yield + def test_after_actions_are_not_run_if_around_action_does_not_yield controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", true test_process(controller, "index") assert_equal ["filter_one", "it didn't yield"], controller.assigns['filters'] end - def test_added_filter_to_inheritance_graph - assert_equal [ :ensure_login ], TestController.before_filters + def test_added_action_to_inheritance_graph + assert_equal [ :ensure_login ], TestController.before_actions end def test_base_class_in_isolation - assert_equal [ ], ActionController::Base.before_filters + assert_equal [ ], ActionController::Base.before_actions end - def test_prepending_filter - assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters + def test_prepending_action + assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_actions end - def test_running_filters + def test_running_actions test_process(PrependingController) assert_equal %w( wonderful_life ensure_login ), assigns["ran_filter"] end - def test_running_filters_with_proc + def test_running_actions_with_proc test_process(ProcController) - assert assigns["ran_proc_filter"] + assert assigns["ran_proc_action"] end - def test_running_filters_with_implicit_proc + def test_running_actions_with_implicit_proc test_process(ImplicitProcController) - assert assigns["ran_proc_filter"] + assert assigns["ran_proc_action"] end - def test_running_filters_with_class + def test_running_actions_with_class test_process(AuditController) assert assigns["was_audited"] end - def test_running_anomolous_yet_valid_condition_filters + def test_running_anomolous_yet_valid_condition_actions test_process(AnomolousYetValidConditionController) assert_equal %w( ensure_login ), assigns["ran_filter"] - assert assigns["ran_class_filter"] - assert assigns["ran_proc_filter1"] - assert assigns["ran_proc_filter2"] + assert assigns["ran_class_action"] + assert assigns["ran_proc_action1"] + assert assigns["ran_proc_action2"] - test_process(AnomolousYetValidConditionController, "show_without_filter") + test_process(AnomolousYetValidConditionController, "show_without_action") assert_nil assigns["ran_filter"] - assert !assigns["ran_class_filter"] - assert !assigns["ran_proc_filter1"] - assert !assigns["ran_proc_filter2"] + assert !assigns["ran_class_action"] + assert !assigns["ran_proc_action1"] + assert !assigns["ran_proc_action2"] end def test_running_conditional_options @@ -614,59 +614,59 @@ class FilterTest < ActionController::TestCase assert_equal %w( ensure_login ), assigns["ran_filter"] end - def test_skipping_class_filters + def test_skipping_class_actions test_process(ClassController) - assert_equal true, assigns["ran_class_filter"] + assert_equal true, assigns["ran_class_action"] skipping_class_controller = Class.new(ClassController) do - skip_before_filter ConditionalClassFilter + skip_before_action ConditionalClassFilter end test_process(skipping_class_controller) - assert_nil assigns['ran_class_filter'] + assert_nil assigns['ran_class_action'] end - def test_running_collection_condition_filters + def test_running_collection_condition_actions test_process(ConditionalCollectionFilterController) assert_equal %w( ensure_login ), assigns["ran_filter"] - test_process(ConditionalCollectionFilterController, "show_without_filter") + test_process(ConditionalCollectionFilterController, "show_without_action") assert_nil assigns["ran_filter"] test_process(ConditionalCollectionFilterController, "another_action") assert_nil assigns["ran_filter"] end - def test_running_only_condition_filters + def test_running_only_condition_actions test_process(OnlyConditionSymController) assert_equal %w( ensure_login ), assigns["ran_filter"] - test_process(OnlyConditionSymController, "show_without_filter") + test_process(OnlyConditionSymController, "show_without_action") assert_nil assigns["ran_filter"] test_process(OnlyConditionProcController) - assert assigns["ran_proc_filter"] - test_process(OnlyConditionProcController, "show_without_filter") - assert !assigns["ran_proc_filter"] + assert assigns["ran_proc_action"] + test_process(OnlyConditionProcController, "show_without_action") + assert !assigns["ran_proc_action"] test_process(OnlyConditionClassController) - assert assigns["ran_class_filter"] - test_process(OnlyConditionClassController, "show_without_filter") - assert !assigns["ran_class_filter"] + assert assigns["ran_class_action"] + test_process(OnlyConditionClassController, "show_without_action") + assert !assigns["ran_class_action"] end - def test_running_except_condition_filters + def test_running_except_condition_actions test_process(ExceptConditionSymController) assert_equal %w( ensure_login ), assigns["ran_filter"] - test_process(ExceptConditionSymController, "show_without_filter") + test_process(ExceptConditionSymController, "show_without_action") assert_nil assigns["ran_filter"] test_process(ExceptConditionProcController) - assert assigns["ran_proc_filter"] - test_process(ExceptConditionProcController, "show_without_filter") - assert !assigns["ran_proc_filter"] + assert assigns["ran_proc_action"] + test_process(ExceptConditionProcController, "show_without_action") + assert !assigns["ran_proc_action"] test_process(ExceptConditionClassController) - assert assigns["ran_class_filter"] - test_process(ExceptConditionClassController, "show_without_filter") - assert !assigns["ran_class_filter"] + assert assigns["ran_class_action"] + test_process(ExceptConditionClassController, "show_without_action") + assert !assigns["ran_class_action"] end def test_running_only_condition_and_conditional_options @@ -674,70 +674,70 @@ class FilterTest < ActionController::TestCase assert_not assigns["ran_conditional_index_proc"] end - def test_running_before_and_after_condition_filters + def test_running_before_and_after_condition_actions test_process(BeforeAndAfterConditionController) assert_equal %w( ensure_login clean_up_tmp), assigns["ran_filter"] - test_process(BeforeAndAfterConditionController, "show_without_filter") + test_process(BeforeAndAfterConditionController, "show_without_action") assert_nil assigns["ran_filter"] end - def test_around_filter + def test_around_action test_process(AroundFilterController) assert assigns["before_ran"] assert assigns["after_ran"] end - def test_before_after_class_filter + def test_before_after_class_action test_process(BeforeAfterClassFilterController) assert assigns["before_ran"] assert assigns["after_ran"] end - def test_having_properties_in_around_filter + def test_having_properties_in_around_action test_process(AroundFilterController) assert_equal "before and after", assigns["execution_log"] end - def test_prepending_and_appending_around_filter + def test_prepending_and_appending_around_action test_process(MixedFilterController) assert_equal " before aroundfilter before procfilter before appended aroundfilter " + " after appended aroundfilter after procfilter after aroundfilter ", MixedFilterController.execution_log end - def test_rendering_breaks_filtering_chain + def test_rendering_breaks_actioning_chain response = test_process(RenderingController) assert_equal "something else", response.body assert !assigns["ran_action"] end - def test_before_filter_rendering_breaks_filtering_chain_for_after_filter + def test_before_action_rendering_breaks_actioning_chain_for_after_action test_process(RenderingController) - assert_equal %w( before_filter_rendering ), assigns["ran_filter"] + assert_equal %w( before_action_rendering ), assigns["ran_filter"] assert !assigns["ran_action"] end - def test_before_filter_redirects_breaks_filtering_chain_for_after_filter - test_process(BeforeFilterRedirectionController) + def test_before_action_redirects_breaks_actioning_chain_for_after_action + test_process(BeforeActionRedirectionController) assert_response :redirect - assert_equal "http://test.host/filter_test/before_filter_redirection/target_of_redirection", redirect_to_url - assert_equal %w( before_filter_redirects ), assigns["ran_filter"] + assert_equal "http://test.host/filter_test/before_action_redirection/target_of_redirection", redirect_to_url + assert_equal %w( before_action_redirects ), assigns["ran_filter"] end - def test_before_filter_rendering_breaks_filtering_chain_for_preprend_after_filter - test_process(RenderingForPrependAfterFilterController) - assert_equal %w( before_filter_rendering ), assigns["ran_filter"] + def test_before_action_rendering_breaks_actioning_chain_for_preprend_after_action + test_process(RenderingForPrependAfterActionController) + assert_equal %w( before_action_rendering ), assigns["ran_filter"] assert !assigns["ran_action"] end - def test_before_filter_redirects_breaks_filtering_chain_for_preprend_after_filter - test_process(BeforeFilterRedirectionForPrependAfterFilterController) + def test_before_action_redirects_breaks_actioning_chain_for_preprend_after_action + test_process(BeforeActionRedirectionForPrependAfterActionController) assert_response :redirect - assert_equal "http://test.host/filter_test/before_filter_redirection_for_prepend_after_filter/target_of_redirection", redirect_to_url - assert_equal %w( before_filter_redirects ), assigns["ran_filter"] + assert_equal "http://test.host/filter_test/before_action_redirection_for_prepend_after_action/target_of_redirection", redirect_to_url + assert_equal %w( before_action_redirects ), assigns["ran_filter"] end - def test_filters_with_mixed_specialization_run_in_order + def test_actions_with_mixed_specialization_run_in_order assert_nothing_raised do response = test_process(MixedSpecializationController, 'bar') assert_equal 'bar', response.body @@ -758,7 +758,7 @@ class FilterTest < ActionController::TestCase end end - def test_running_prepended_before_and_after_filter + def test_running_prepended_before_and_after_action test_process(PrependingBeforeAndAfterController) assert_equal %w( before_all between_before_all_and_after_all after_all ), assigns["ran_filter"] end @@ -775,26 +775,26 @@ class FilterTest < ActionController::TestCase assert_equal %w( find_record ensure_login ), assigns["ran_filter"] end - def test_conditional_skipping_of_filters + def test_conditional_skipping_of_actions test_process(ConditionalSkippingController, "login") assert_nil assigns["ran_filter"] test_process(ConditionalSkippingController, "change_password") assert_equal %w( ensure_login find_user ), assigns["ran_filter"] test_process(ConditionalSkippingController, "login") - assert !@controller.instance_variable_defined?("@ran_after_filter") + assert !@controller.instance_variable_defined?("@ran_after_action") test_process(ConditionalSkippingController, "change_password") - assert_equal %w( clean_up ), @controller.instance_variable_get("@ran_after_filter") + assert_equal %w( clean_up ), @controller.instance_variable_get("@ran_after_action") end - def test_conditional_skipping_of_filters_when_parent_filter_is_also_conditional + def test_conditional_skipping_of_actions_when_parent_action_is_also_conditional test_process(ChildOfConditionalParentController) assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), assigns['ran_filter'] test_process(ChildOfConditionalParentController, 'another_action') assert_nil assigns['ran_filter'] end - def test_condition_skipping_of_filters_when_siblings_also_have_conditions + def test_condition_skipping_of_actions_when_siblings_also_have_conditions test_process(ChildOfConditionalParentController) assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), assigns['ran_filter'] test_process(AnotherChildOfConditionalParentController) @@ -808,7 +808,7 @@ class FilterTest < ActionController::TestCase assert_nil assigns['ran_filter'] end - def test_a_rescuing_around_filter + def test_a_rescuing_around_action response = nil assert_nothing_raised do response = test_process(RescuedController) @@ -818,7 +818,7 @@ class FilterTest < ActionController::TestCase assert_equal("I rescued this: #<FilterTest::ErrorToRescue: Something made the bad noise.>", response.body) end - def test_filters_obey_only_and_except_for_implicit_actions + def test_actions_obey_only_and_except_for_implicit_actions test_process(ImplicitActionsController, 'show') assert_equal 'Except', assigns(:except) assert_nil assigns(:only) @@ -852,7 +852,7 @@ class PostsController < ActionController::Base include AroundExceptions end - module_eval %w(raises_before raises_after raises_both no_raise no_filter).map { |action| "def #{action}; default_action end" }.join("\n") + module_eval %w(raises_before raises_after raises_both no_raise no_action).map { |action| "def #{action}; default_action end" }.join("\n") private def default_action @@ -861,9 +861,9 @@ class PostsController < ActionController::Base end class ControllerWithSymbolAsFilter < PostsController - around_filter :raise_before, :only => :raises_before - around_filter :raise_after, :only => :raises_after - around_filter :without_exception, :only => :no_raise + around_action :raise_before, :only => :raises_before + around_action :raise_after, :only => :raises_after + around_action :without_exception, :only => :no_raise private def raise_before @@ -895,7 +895,7 @@ class ControllerWithFilterClass < PostsController end end - around_filter YieldingFilter, :only => :raises_after + around_action YieldingFilter, :only => :raises_after end class ControllerWithFilterInstance < PostsController @@ -906,11 +906,11 @@ class ControllerWithFilterInstance < PostsController end end - around_filter YieldingFilter.new, :only => :raises_after + around_action YieldingFilter.new, :only => :raises_after end class ControllerWithProcFilter < PostsController - around_filter(:only => :no_raise) do |c,b| + around_action(:only => :no_raise) do |c,b| c.instance_variable_set(:"@before", true) b.call c.instance_variable_set(:"@after", true) @@ -918,14 +918,14 @@ class ControllerWithProcFilter < PostsController end class ControllerWithNestedFilters < ControllerWithSymbolAsFilter - around_filter :raise_before, :raise_after, :without_exception, :only => :raises_both + around_action :raise_before, :raise_after, :without_exception, :only => :raises_both end class ControllerWithAllTypesOfFilters < PostsController - before_filter :before - around_filter :around - after_filter :after - around_filter :around_again + before_action :before + around_action :around + after_action :after + around_action :around_again private def before @@ -951,8 +951,8 @@ class ControllerWithAllTypesOfFilters < PostsController end class ControllerWithTwoLessFilters < ControllerWithAllTypesOfFilters - skip_filter :around_again - skip_filter :after + skip_action_callback :around_again + skip_action_callback :after end class YieldingAroundFiltersTest < ActionController::TestCase @@ -963,7 +963,7 @@ class YieldingAroundFiltersTest < ActionController::TestCase assert_nothing_raised { test_process(controller,'no_raise') } assert_nothing_raised { test_process(controller,'raises_before') } assert_nothing_raised { test_process(controller,'raises_after') } - assert_nothing_raised { test_process(controller,'no_filter') } + assert_nothing_raised { test_process(controller,'no_action') } end def test_with_symbol @@ -992,7 +992,7 @@ class YieldingAroundFiltersTest < ActionController::TestCase assert assigns['after'] end - def test_nested_filters + def test_nested_actions controller = ControllerWithNestedFilters assert_nothing_raised do begin @@ -1008,31 +1008,31 @@ class YieldingAroundFiltersTest < ActionController::TestCase end end - def test_filter_order_with_all_filter_types + def test_action_order_with_all_action_types test_process(ControllerWithAllTypesOfFilters,'no_raise') assert_equal 'before around (before yield) around_again (before yield) around_again (after yield) after around (after yield)', assigns['ran_filter'].join(' ') end - def test_filter_order_with_skip_filter_method + def test_action_order_with_skip_action_method test_process(ControllerWithTwoLessFilters,'no_raise') assert_equal 'before around (before yield) around (after yield)', assigns['ran_filter'].join(' ') end - def test_first_filter_in_multiple_before_filter_chain_halts + def test_first_action_in_multiple_before_action_chain_halts controller = ::FilterTest::TestMultipleFiltersController.new response = test_process(controller, 'fail_1') assert_equal ' ', response.body assert_equal 1, controller.instance_variable_get(:@try) end - def test_second_filter_in_multiple_before_filter_chain_halts + def test_second_action_in_multiple_before_action_chain_halts controller = ::FilterTest::TestMultipleFiltersController.new response = test_process(controller, 'fail_2') assert_equal ' ', response.body assert_equal 2, controller.instance_variable_get(:@try) end - def test_last_filter_in_multiple_before_filter_chain_halts + def test_last_action_in_multiple_before_action_chain_halts controller = ::FilterTest::TestMultipleFiltersController.new response = test_process(controller, 'fail_3') assert_equal ' ', response.body diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb index 3655b90e32..00d4612ac9 100644 --- a/actionpack/test/controller/force_ssl_test.rb +++ b/actionpack/test/controller/force_ssl_test.rb @@ -93,8 +93,6 @@ class RedirectToSSL < ForceSSLController end class ForceSSLControllerLevelTest < ActionController::TestCase - tests ForceSSLControllerLevel - def test_banana_redirects_to_https get :banana assert_response 301 @@ -115,8 +113,6 @@ class ForceSSLControllerLevelTest < ActionController::TestCase end class ForceSSLCustomOptionsTest < ActionController::TestCase - tests ForceSSLCustomOptions - def setup @request.env['HTTP_HOST'] = 'www.example.com:80' end @@ -189,8 +185,6 @@ class ForceSSLCustomOptionsTest < ActionController::TestCase end class ForceSSLOnlyActionTest < ActionController::TestCase - tests ForceSSLOnlyAction - def test_banana_not_redirects_to_https get :banana assert_response 200 @@ -204,8 +198,6 @@ class ForceSSLOnlyActionTest < ActionController::TestCase end class ForceSSLExceptActionTest < ActionController::TestCase - tests ForceSSLExceptAction - def test_banana_not_redirects_to_https get :banana assert_response 200 @@ -219,8 +211,6 @@ class ForceSSLExceptActionTest < ActionController::TestCase end class ForceSSLIfConditionTest < ActionController::TestCase - tests ForceSSLIfCondition - def test_banana_not_redirects_to_https get :banana assert_response 200 @@ -234,8 +224,6 @@ class ForceSSLIfConditionTest < ActionController::TestCase end class ForceSSLFlashTest < ActionController::TestCase - tests ForceSSLFlash - def test_cheeseburger_redirects_to_https get :set_flash assert_response 302 @@ -315,7 +303,6 @@ class ForceSSLOptionalSegmentsTest < ActionController::TestCase end class RedirectToSSLTest < ActionController::TestCase - tests RedirectToSSL def test_banana_redirects_to_https_if_not_https get :banana assert_response 301 @@ -334,4 +321,4 @@ class RedirectToSSLTest < ActionController::TestCase assert_response 200 assert_equal 'ihaz', response.body end -end
\ No newline at end of file +end diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb index 90548d4294..9052fc6962 100644 --- a/actionpack/test/controller/http_basic_authentication_test.rb +++ b/actionpack/test/controller/http_basic_authentication_test.rb @@ -129,6 +129,13 @@ class HttpBasicAuthenticationTest < ActionController::TestCase assert_response :unauthorized end + test "authentication request with wrong scheme" do + header = 'Bearer ' + encode_credentials('David', 'Goliath').split(' ', 2)[1] + @request.env['HTTP_AUTHORIZATION'] = header + get :search + assert_response :unauthorized + end + private def encode_credentials(username, password) diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb index 86b94652ce..8c6c8a0aa7 100644 --- a/actionpack/test/controller/http_token_authentication_test.rb +++ b/actionpack/test/controller/http_token_authentication_test.rb @@ -132,13 +132,50 @@ class HttpTokenAuthenticationTest < ActionController::TestCase assert_equal(expected, actual) end - private + test "token_and_options returns empty string with empty token" do + token = '' + actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token)).first + expected = token + assert_equal(expected, actual) + end - def sample_request(token) - @sample_request ||= OpenStruct.new authorization: %{Token token="#{token}"} + test "token_and_options returns correct token with nounce option" do + token = "rcHu+HzSFw89Ypyhn/896A=" + nonce_hash = {nonce: "123abc"} + actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token, nonce_hash)) + expected_token = token + expected_nonce = {"nonce" => nonce_hash[:nonce]} + assert_equal(expected_token, actual.first) + assert_equal(expected_nonce, actual.last) end - def encode_credentials(token, options = {}) - ActionController::HttpAuthentication::Token.encode_credentials(token, options) + test "token_and_options returns nil with no value after the equal sign" do + actual = ActionController::HttpAuthentication::Token.token_and_options(malformed_request).first + expected = nil + assert_equal(expected, actual) + end + + test "raw_params returns a tuple of two key value pair strings" do + auth = sample_request("rcHu+HzSFw89Ypyhn/896A=").authorization.to_s + actual = ActionController::HttpAuthentication::Token.raw_params(auth) + expected = ["token=\"rcHu+HzSFw89Ypyhn/896A=\"", "nonce=\"def\""] + assert_equal(expected, actual) end + + private + + def sample_request(token, options = {nonce: "def"}) + authorization = options.inject([%{Token token="#{token}"}]) do |arr, (k, v)| + arr << "#{k}=\"#{v}\"" + end.join(", ") + @sample_request ||= OpenStruct.new authorization: authorization + end + + def malformed_request + @malformed_request ||= OpenStruct.new authorization: %{Token token=} + end + + def encode_credentials(token, options = {}) + ActionController::HttpAuthentication::Token.encode_credentials(token, options) + end end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index e851cc6a63..78cce3aa64 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'controller/fake_controllers' require 'action_view/vendor/html-scanner' +require 'rails/engine' class SessionTest < ActiveSupport::TestCase StubApp = lambda { |env| @@ -374,6 +375,10 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest follow_redirect! assert_response :success assert_equal "/get", path + + get '/moved' + assert_response :redirect + assert_redirected_to '/method' end end @@ -511,6 +516,8 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end set.draw do + get 'moved' => redirect('/method') + match ':action', :to => controller, :via => [:get, :post], :as => :action get 'get/:action', :to => controller, :as => :get_action end @@ -589,7 +596,7 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest @routes ||= ActionDispatch::Routing::RouteSet.new end - class MountedApp + class MountedApp < Rails::Engine def self.routes @routes ||= ActionDispatch::Routing::RouteSet.new end @@ -769,3 +776,34 @@ class UrlOptionsIntegrationTest < ActionDispatch::IntegrationTest assert_equal "/foo/1/edit", url_for(:action => 'edit', :only_path => true) end end + +class HeadWithStatusActionIntegrationTest < ActionDispatch::IntegrationTest + class FooController < ActionController::Base + def status + head :ok + 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 + get "/foo/status" => 'head_with_status_action_integration_test/foo#status' + end + + test "get /foo/status with head result does not cause stack overflow error" do + assert_nothing_raised do + get '/foo/status' + end + assert_response :ok + end +end diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb index 947f64176b..0500b7c789 100644 --- a/actionpack/test/controller/live_stream_test.rb +++ b/actionpack/test/controller/live_stream_test.rb @@ -39,6 +39,13 @@ module ActionController ensure sse.close end + + def sse_with_multiple_line_message + sse = SSE.new(response.stream) + sse.write("first line.\nsecond line.") + ensure + sse.close + end end tests SSETestController @@ -87,6 +94,15 @@ module ActionController assert_match(/data: {\"name\":\"Ryan\"}/, second_response) assert_match(/id: 2/, second_response) end + + def test_sse_with_multiple_line_message + get :sse_with_multiple_line_message + + wait_for_response_stream_close + first_response, second_response = response.body.split("\n") + assert_match(/data: first line/, first_response) + assert_match(/data: second line/, second_response) + end end class LiveStreamTest < ActionController::TestCase @@ -186,6 +202,39 @@ module ActionController response.stream.write '' response.stream.write params[:widget][:didnt_check_for_nil] end + + def overfill_buffer_and_die + # Write until the buffer is full. It doesn't expose that + # information directly, so we must hard-code its size: + 10.times do + response.stream.write '.' + end + # .. plus one more, because the #each frees up a slot: + response.stream.write '.' + + latch.release + + # This write will block, and eventually raise + response.stream.write 'x' + + 20.times do + response.stream.write '.' + end + end + + def ignore_client_disconnect + response.stream.ignore_disconnect = true + + response.stream.write '' # commit + + # These writes will be ignored + 15.times do + response.stream.write 'x' + end + + logger.info 'Work complete' + latch.release + end end tests TestController @@ -248,6 +297,62 @@ module ActionController assert t.join(3), 'timeout expired before the thread terminated' end + def test_abort_with_full_buffer + @controller.latch = ActiveSupport::Concurrency::Latch.new + + @request.parameters[:format] = 'plain' + @controller.request = @request + @controller.response = @response + + got_error = ActiveSupport::Concurrency::Latch.new + @response.stream.on_error do + ActionController::Base.logger.warn 'Error while streaming' + got_error.release + end + + t = Thread.new(@response) { |resp| + resp.await_commit + _, _, body = resp.to_a + body.each do |part| + @controller.latch.await + body.close + break + end + } + + capture_log_output do |output| + @controller.process :overfill_buffer_and_die + t.join + got_error.await + assert_match 'Error while streaming', output.rewind && output.read + end + end + + def test_ignore_client_disconnect + @controller.latch = ActiveSupport::Concurrency::Latch.new + + @controller.request = @request + @controller.response = @response + + t = Thread.new(@response) { |resp| + resp.await_commit + _, _, body = resp.to_a + body.each do |part| + body.close + break + end + } + + capture_log_output do |output| + @controller.process :ignore_client_disconnect + t.join + Timeout.timeout(3) do + @controller.latch.await + end + assert_match 'Work complete', output.rewind && output.read + end + end + def test_thread_locals_get_copied @controller.tc = self Thread.current[:originating_thread] = Thread.current.object_id diff --git a/actionpack/test/controller/localized_templates_test.rb b/actionpack/test/controller/localized_templates_test.rb index c95ef8a0c7..27871ef351 100644 --- a/actionpack/test/controller/localized_templates_test.rb +++ b/actionpack/test/controller/localized_templates_test.rb @@ -8,22 +8,24 @@ end class LocalizedTemplatesTest < ActionController::TestCase tests LocalizedController + setup do + @old_locale = I18n.locale + end + + teardown do + I18n.locale = @old_locale + end + def test_localized_template_is_used - old_locale = I18n.locale I18n.locale = :de get :hello_world assert_equal "Gutten Tag", @response.body - ensure - I18n.locale = old_locale end def test_default_locale_template_is_used_when_locale_is_missing - old_locale = I18n.locale I18n.locale = :dk get :hello_world assert_equal "Hello World", @response.body - ensure - I18n.locale = old_locale end def test_use_fallback_locales @@ -36,13 +38,9 @@ class LocalizedTemplatesTest < ActionController::TestCase end def test_localized_template_has_correct_header_with_no_format_in_template_name - old_locale = I18n.locale I18n.locale = :it - get :hello_world assert_equal "Ciao Mondo", @response.body assert_equal "text/html", @response.content_type - ensure - I18n.locale = old_locale end end diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 18037b3d2f..49be7caf38 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -85,7 +85,7 @@ class ACLogSubscriberTest < ActionController::TestCase @old_logger = ActionController::Base.logger - @cache_path = File.expand_path('../temp/test_cache', File.dirname(__FILE__)) + @cache_path = File.join Dir.tmpdir, Dir::Tmpname.make_tmpname('tmp', 'cache') @controller.cache_store = :file_store, @cache_path ActionController::LogSubscriber.attach_to :action_controller end diff --git a/actionpack/test/controller/mime/accept_format_test.rb b/actionpack/test/controller/mime/accept_format_test.rb index c03c7edeb8..811c507af2 100644 --- a/actionpack/test/controller/mime/accept_format_test.rb +++ b/actionpack/test/controller/mime/accept_format_test.rb @@ -9,8 +9,6 @@ class StarStarMimeController < ActionController::Base end class StarStarMimeControllerTest < ActionController::TestCase - tests StarStarMimeController - def test_javascript_with_format @request.accept = "text/javascript" get :index, :format => 'js' diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb index ce6d135d92..1bc7ad3015 100644 --- a/actionpack/test/controller/mime/respond_to_test.rb +++ b/actionpack/test/controller/mime/respond_to_test.rb @@ -128,6 +128,12 @@ class RespondToController < ActionController::Base end end + def json_with_callback + respond_to do |type| + type.json { render :json => 'JS', :callback => 'alert' } + end + end + def iphone_with_html_response_type request.format = :iphone if request.env["HTTP_ACCEPT"] == "text/iphone" @@ -258,8 +264,6 @@ class RespondToController < ActionController::Base end class RespondToControllerTest < ActionController::TestCase - tests RespondToController - def setup super @request.host = "www.example.com" @@ -513,6 +517,13 @@ class RespondToControllerTest < ActionController::TestCase assert_equal '<html><div id="html">HTML for all_types_with_layout</div></html>', @response.body end + def test_json_with_callback_sets_javascript_content_type + @request.accept = 'application/json' + get :json_with_callback + assert_equal '/**/alert(JS)', @response.body + assert_equal 'text/javascript', @response.content_type + end + def test_xhr xhr :get, :js_or_html assert_equal 'JS', @response.body diff --git a/actionpack/test/controller/mime/respond_with_test.rb b/actionpack/test/controller/mime/respond_with_test.rb index a70592fa1b..115f3b2f41 100644 --- a/actionpack/test/controller/mime/respond_with_test.rb +++ b/actionpack/test/controller/mime/respond_with_test.rb @@ -2,6 +2,10 @@ require 'abstract_unit' require 'controller/fake_models' class RespondWithController < ActionController::Base + class CustomerWithJson < Customer + def to_json; super; end + end + respond_to :html, :json, :touch respond_to :xml, :except => :using_resource_with_block respond_to :js, :only => [ :using_resource_with_block, :using_resource, 'using_hash_resource' ] @@ -38,6 +42,10 @@ class RespondWithController < ActionController::Base respond_with(resource, :location => "http://test.host/", :status => :created) end + def using_resource_with_json + respond_with(CustomerWithJson.new("david", request.delete? ? nil : 13)) + end + def using_invalid_resource_with_template respond_with(resource) end @@ -138,8 +146,6 @@ class EmptyRespondWithController < ActionController::Base end class RespondWithControllerTest < ActionController::TestCase - tests RespondWithController - def setup super @request.host = "www.example.com" @@ -382,9 +388,8 @@ class RespondWithControllerTest < ActionController::TestCase end 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 + put :using_resource_with_json assert_equal "application/json", @response.content_type assert_equal 204, @response.status assert_equal "", @response.body @@ -433,10 +438,9 @@ class RespondWithControllerTest < ActionController::TestCase end 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 + delete :using_resource_with_json assert_equal "application/json", @response.content_type assert_equal 204, @response.status assert_equal "", @response.body @@ -645,6 +649,8 @@ class RespondWithControllerTest < ActionController::TestCase get :index, format: 'csv' assert_equal Mime::CSV, @response.content_type assert_equal "c,s,v", @response.body + ensure + ActionController::Renderers.remove :csv end def test_raises_missing_renderer_if_an_api_behavior_with_no_renderer @@ -654,6 +660,23 @@ class RespondWithControllerTest < ActionController::TestCase end end + def test_removing_renderers + ActionController::Renderers.add :csv do |obj, options| + send_data obj.to_csv, type: Mime::CSV + end + @controller = CsvRespondWithController.new + @request.accept = "text/csv" + get :index, format: 'csv' + assert_equal Mime::CSV, @response.content_type + + ActionController::Renderers.remove :csv + assert_raise ActionController::MissingRenderer do + get :index, format: 'csv' + end + ensure + ActionController::Renderers.remove :csv + end + def test_error_is_raised_if_no_respond_to_is_declared_and_respond_with_is_called @controller = EmptyRespondWithController.new @request.accept = "*/*" diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index 7396c850ad..246ba099af 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -2,6 +2,8 @@ require "abstract_unit" module BareMetalTest class BareController < ActionController::Metal + include ActionController::RackDelegation + def index self.response_body = "Hello world" end @@ -81,8 +83,8 @@ module BareMetalTest 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 + test "head :switching_protocols (101) does not return a content-type header" do + headers = HeadController.action(:switching_protocols).call(Rack::MockRequest.env_for("/")).second assert_nil headers['Content-Type'] assert_nil headers['Content-Length'] end diff --git a/actionpack/test/controller/new_base/render_body_test.rb b/actionpack/test/controller/new_base/render_body_test.rb index fad848349a..f4a3db8b41 100644 --- a/actionpack/test/controller/new_base/render_body_test.rb +++ b/actionpack/test/controller/new_base/render_body_test.rb @@ -111,17 +111,17 @@ module RenderBody assert_status 404 end - test "rendering body with nil returns an empty body padded for Safari" do + test "rendering body with nil returns an empty body" do get "/render_body/with_layout/with_nil" - assert_body " " + assert_body "" assert_status 200 end - test "Rendering body with nil and custom status code returns an empty body padded for Safari and the status" do + test "Rendering body with nil and custom status code returns an empty body and the status" do get "/render_body/with_layout/with_nil_and_status" - assert_body " " + assert_body "" assert_status 403 end diff --git a/actionpack/test/controller/new_base/render_html_test.rb b/actionpack/test/controller/new_base/render_html_test.rb index bfe0271df7..fe11501eeb 100644 --- a/actionpack/test/controller/new_base/render_html_test.rb +++ b/actionpack/test/controller/new_base/render_html_test.rb @@ -114,17 +114,17 @@ module RenderHtml assert_status 404 end - test "rendering text with nil returns an empty body padded for Safari" do + test "rendering text with nil returns an empty body" do get "/render_html/with_layout/with_nil" - assert_body " " + assert_body "" assert_status 200 end - test "Rendering text with nil and custom status code returns an empty body padded for Safari and the status" do + test "Rendering text with nil and custom status code returns an empty body and the status" do get "/render_html/with_layout/with_nil_and_status" - assert_body " " + assert_body "" assert_status 403 end diff --git a/actionpack/test/controller/new_base/render_implicit_action_test.rb b/actionpack/test/controller/new_base/render_implicit_action_test.rb index 1e2191d417..5b4885f7e0 100644 --- a/actionpack/test/controller/new_base/render_implicit_action_test.rb +++ b/actionpack/test/controller/new_base/render_implicit_action_test.rb @@ -6,7 +6,7 @@ module RenderImplicitAction "render_implicit_action/simple/hello_world.html.erb" => "Hello world!", "render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated!", "render_implicit_action/simple/not_implemented.html.erb" => "Not Implemented" - )] + ), ActionView::FileSystemResolver.new(File.expand_path('../../../controller', __FILE__))] def hello_world() end end @@ -33,10 +33,25 @@ module RenderImplicitAction assert_status 200 end + test "render does not traverse the file system" do + assert_raises(AbstractController::ActionNotFound) do + action_name = %w(.. .. fixtures shared).join(File::SEPARATOR) + SimpleController.action(action_name).call(Rack::MockRequest.env_for("/")) + end + end + test "available_action? returns true for implicit actions" do assert SimpleController.new.available_action?(:hello_world) assert SimpleController.new.available_action?(:"hyphen-ated") assert SimpleController.new.available_action?(:not_implemented) end + + test "available_action? does not allow File::SEPARATOR on the name" do + action_name = %w(evil .. .. path).join(File::SEPARATOR) + assert_equal false, SimpleController.new.available_action?(action_name.to_sym) + + action_name = %w(evil path).join(File::SEPARATOR) + assert_equal false, SimpleController.new.available_action?(action_name.to_sym) + end end end diff --git a/actionpack/test/controller/new_base/render_plain_test.rb b/actionpack/test/controller/new_base/render_plain_test.rb index dba2e9f13e..0e36d36b50 100644 --- a/actionpack/test/controller/new_base/render_plain_test.rb +++ b/actionpack/test/controller/new_base/render_plain_test.rb @@ -106,17 +106,17 @@ module RenderPlain assert_status 404 end - test "rendering text with nil returns an empty body padded for Safari" do + test "rendering text with nil returns an empty body" do get "/render_plain/with_layout/with_nil" - assert_body " " + assert_body "" assert_status 200 end - test "Rendering text with nil and custom status code returns an empty body padded for Safari and the status" do + test "Rendering text with nil and custom status code returns an empty body and the status" do get "/render_plain/with_layout/with_nil_and_status" - assert_body " " + assert_body "" assert_status 403 end diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index b7a9cf92f2..e87811776a 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -9,7 +9,7 @@ module RenderTemplate "locals.html.erb" => "The secret is <%= secret %>", "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>' %> in a html template", + "with_implicit_raw.html.erb" => "Hello <%== '<strong>this is also raw</strong>' %> in an html template", "with_implicit_raw.text.erb" => "Hello <%== '<strong>this is also raw</strong>' %> in a text template", "test/with_json.html.erb" => "<%= render :template => 'test/with_json', :formats => [:json] %>", "test/with_json.json.erb" => "<%= render :template => 'test/final', :formats => [:json] %>", @@ -114,7 +114,7 @@ module RenderTemplate get :with_implicit_raw - assert_body "Hello <strong>this is also raw</strong> in a html template" + assert_body "Hello <strong>this is also raw</strong> in an html template" assert_status 200 get :with_implicit_raw, format: 'text' diff --git a/actionpack/test/controller/new_base/render_text_test.rb b/actionpack/test/controller/new_base/render_text_test.rb index abb81d7e71..10bad57cd6 100644 --- a/actionpack/test/controller/new_base/render_text_test.rb +++ b/actionpack/test/controller/new_base/render_text_test.rb @@ -106,17 +106,17 @@ module RenderText assert_status 404 end - test "rendering text with nil returns an empty body padded for Safari" do + test "rendering text with nil returns an empty body" do get "/render_text/with_layout/with_nil" - assert_body " " + assert_body "" assert_status 200 end - test "Rendering text with nil and custom status code returns an empty body padded for Safari and the status" do + test "Rendering text with nil and custom status code returns an empty body and the status" do get "/render_text/with_layout/with_nil_and_status" - assert_body " " + assert_body "" assert_status 403 end diff --git a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb new file mode 100644 index 0000000000..059f310d49 --- /dev/null +++ b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb @@ -0,0 +1,29 @@ +require 'abstract_unit' +require 'action_controller/metal/strong_parameters' + +class AlwaysPermittedParametersTest < ActiveSupport::TestCase + def setup + ActionController::Parameters.action_on_unpermitted_parameters = :raise + ActionController::Parameters.always_permitted_parameters = %w( controller action format ) + end + + def teardown + ActionController::Parameters.action_on_unpermitted_parameters = false + ActionController::Parameters.always_permitted_parameters = %w( controller action ) + end + + test "shows deprecations warning on NEVER_UNPERMITTED_PARAMS" do + assert_deprecated do + ActionController::Parameters::NEVER_UNPERMITTED_PARAMS + end + end + + test "permits parameters that are whitelisted" do + params = ActionController::Parameters.new({ + book: { pages: 65 }, + format: "json" + }) + permitted = params.permit book: [:pages] + assert permitted.permitted? + end +end diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb index 33a91d72d9..aa894ffa17 100644 --- a/actionpack/test/controller/parameters/parameters_permit_test.rb +++ b/actionpack/test/controller/parameters/parameters_permit_test.rb @@ -167,9 +167,26 @@ class ParametersPermitTest < ActiveSupport::TestCase end end + # Strong params has an optimization to avoid looping every time you read + # a key whose value is an array and building a new object. We check that + # optimization here. test 'arrays are converted at most once' do params = ActionController::Parameters.new(foo: [{}]) - assert params[:foo].equal?(params[:foo]) + assert_same params[:foo], params[:foo] + end + + # Strong params has an internal cache to avoid duplicated loops in the most + # common usage pattern. See the docs of the method `converted_arrays`. + # + # This test checks that if we push a hash to an array (in-place modification) + # the cache does not get fooled, the hash is still wrapped as strong params, + # and not permitted. + test 'mutated arrays are detected' do + params = ActionController::Parameters.new(users: [{id: 1}]) + + permitted = params.permit(users: [:id]) + permitted[:users] << {injected: 1} + assert_not permitted[:users].last.permitted? end test "fetch doesnt raise ParameterMissing exception if there is a default" do diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index 11ccb6cf3b..645ecae220 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -337,14 +337,26 @@ class IrregularInflectionParamsWrapperTest < ActionController::TestCase tests ParamswrappernewsController def test_uses_model_attribute_names_with_irregular_inflection - ActiveSupport::Inflector.inflections do |inflect| - inflect.irregular 'paramswrappernews_item', 'paramswrappernews' - end + with_dup do + 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' }}) + 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 + + private + + def with_dup + original = ActiveSupport::Inflector::Inflections.instance_variable_get(:@__instance__)[:en] + ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: original.dup) + yield + ensure + ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: original) + end end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 4331333b98..103ca9c776 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -90,6 +90,10 @@ class RedirectController < ActionController::Base redirect_to nil end + def redirect_to_params + redirect_to ActionController::Parameters.new(status: 200, protocol: 'javascript', f: '%0Aeval(name)') + end + def redirect_to_with_block redirect_to proc { "http://www.rubyonrails.org/" } end @@ -281,6 +285,12 @@ class RedirectTest < ActionController::TestCase end end + def test_redirect_to_params + assert_raise(ActionController::ActionControllerError) do + get :redirect_to_params + end + end + def test_redirect_to_with_block get :redirect_to_with_block assert_response :redirect diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index de8d1cbd9b..ada978aa11 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -101,7 +101,7 @@ class RenderJsonTest < ActionController::TestCase def test_render_json_with_callback xhr :get, :render_json_hello_world_with_callback - assert_equal 'alert({"hello":"world"})', @response.body + assert_equal '/**/alert({"hello":"world"})', @response.body assert_equal 'text/javascript', @response.content_type end diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb index b5e74e373d..af50e11261 100644 --- a/actionpack/test/controller/render_other_test.rb +++ b/actionpack/test/controller/render_other_test.rb @@ -1,9 +1,5 @@ require 'abstract_unit' -ActionController.add_renderer :simon do |says, options| - self.content_type = Mime::TEXT - self.response_body = "Simon says: #{says}" -end class RenderOtherTest < ActionController::TestCase class TestController < ActionController::Base @@ -15,7 +11,14 @@ class RenderOtherTest < ActionController::TestCase tests TestController def test_using_custom_render_option + ActionController.add_renderer :simon do |says, options| + self.content_type = Mime::TEXT + self.response_body = "Simon says: #{says}" + end + get :render_simon_says assert_equal "Simon says: foo", @response.body + ensure + ActionController.remove_renderer :simon end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 26806fb03f..9926130c02 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -242,6 +242,8 @@ class MetalTestController < ActionController::Metal include AbstractController::Rendering include ActionView::Rendering include ActionController::Rendering + include ActionController::RackDelegation + def accessing_logger_in_template render :inline => "<%= logger.class %>" @@ -387,10 +389,6 @@ end class EtagRenderTest < ActionController::TestCase tests TestControllerWithExtraEtags - def setup - super - end - def test_multiple_etags @request.if_none_match = etag(["123", 'ab', :cde, [:f]]) get :fresh diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 5ab5141966..2a5aad9c0e 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -127,11 +127,12 @@ module RequestForgeryProtectionTests @token = "cf50faa3fe97702ca1ae" SecureRandom.stubs(:base64).returns(@token) + @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token ActionController::Base.request_forgery_protection_token = :custom_authenticity_token end def teardown - ActionController::Base.request_forgery_protection_token = nil + ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token end def test_should_render_form_with_token_tag @@ -376,11 +377,12 @@ class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController include RequestForgeryProtectionTests setup do + @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token ActionController::Base.request_forgery_protection_token = :custom_authenticity_token end teardown do - ActionController::Base.request_forgery_protection_token = nil + ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token end test 'should emit a csrf-param meta tag and a csrf-token meta tag' do @@ -462,16 +464,38 @@ end class CustomAuthenticityParamControllerTest < ActionController::TestCase def setup super - ActionController::Base.request_forgery_protection_token = :custom_token_name + @old_logger = ActionController::Base.logger + @logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new + @token = "foobar" + @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token + ActionController::Base.request_forgery_protection_token = @token end def teardown - ActionController::Base.request_forgery_protection_token = :authenticity_token + ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token super end - def test_should_allow_custom_token - post :index, :custom_token_name => 'foobar' - assert_response :ok + def test_should_not_warn_if_form_authenticity_param_matches_form_authenticity_token + ActionController::Base.logger = @logger + SecureRandom.stubs(:base64).returns(@token) + + begin + post :index, :custom_token_name => 'foobar' + assert_equal 0, @logger.logged(:warn).size + ensure + ActionController::Base.logger = @old_logger + end + end + + def test_should_warn_if_form_authenticity_param_does_not_match_form_authenticity_token + ActionController::Base.logger = @logger + + begin + post :index, :custom_token_name => 'bazqux' + assert_equal 1, @logger.logged(:warn).size + ensure + ActionController::Base.logger = @old_logger + end end end diff --git a/actionpack/test/controller/required_params_test.rb b/actionpack/test/controller/required_params_test.rb index 25d0337212..6803dbbb62 100644 --- a/actionpack/test/controller/required_params_test.rb +++ b/actionpack/test/controller/required_params_test.rb @@ -24,10 +24,26 @@ class ActionControllerRequiredParamsTest < ActionController::TestCase post :create, { book: { name: "Mjallo!" } } assert_response :ok end + + test "required parameters with false value will not raise" do + post :create, { book: { name: false } } + assert_response :ok + end end class ParametersRequireTest < ActiveSupport::TestCase - test "required parameters must be present not merely not nil" do + + test "required parameters should accept and return false value" do + assert_equal(false, ActionController::Parameters.new(person: false).require(:person)) + end + + test "required parameters must not be nil" do + assert_raises(ActionController::ParameterMissing) do + ActionController::Parameters.new(person: nil).require(:person) + end + end + + test "required parameters must not be empty" do assert_raises(ActionController::ParameterMissing) do ActionController::Parameters.new(person: {}).require(:person) end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index df453a0251..c18914cc8e 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -77,17 +77,18 @@ class LegacyRouteSetTests < ActiveSupport::TestCase include ActionDispatch::RoutingVerbs attr_reader :rs + attr_accessor :controller alias :routes :rs def setup - @rs = ::ActionDispatch::Routing::RouteSet.new + @rs = make_set @response = nil end def test_symbols_with_dashes rs.draw do get '/:artist/:song-omg', :to => lambda { |env| - resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters [200, {}, [resp]] } end @@ -99,7 +100,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_id_with_dash rs.draw do get '/journey/:id', :to => lambda { |env| - resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters [200, {}, [resp]] } end @@ -111,7 +112,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_dash_with_custom_regexp rs.draw do get '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env| - resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters [200, {}, [resp]] } end @@ -124,7 +125,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_pre_dash rs.draw do get '/:artist/omg-:song', :to => lambda { |env| - resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters [200, {}, [resp]] } end @@ -136,7 +137,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_pre_dash_with_custom_regexp rs.draw do get '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env| - resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] + resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters [200, {}, [resp]] } end @@ -243,6 +244,32 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal 'clients', get(URI('http://clients.example.org/')) end + def test_scoped_lambda + scope_called = false + rs.draw do + scope '/foo', :constraints => lambda { |req| scope_called = true } do + get '/', :to => lambda { |env| [200, {}, %w{default}] } + end + end + + assert_equal 'default', get(URI('http://www.example.org/foo/')) + assert scope_called, "scope constraint should be called" + end + + def test_scoped_lambda_with_get_lambda + inner_called = false + + rs.draw do + scope '/foo', :constraints => lambda { |req| flunk "should not be called" } do + get '/', :constraints => lambda { |req| inner_called = true }, + :to => lambda { |env| [200, {}, %w{default}] } + end + end + + assert_equal 'default', get(URI('http://www.example.org/foo/')) + assert inner_called, "inner constraint should be called" + end + def test_empty_string_match rs.draw do get '/:username', :constraints => { :username => /[^\/]+/ }, @@ -291,11 +318,16 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal '/admin/user/show/10', url_for(rs, { :controller => 'admin/user', :action => 'show', :id => 10 }) - assert_equal '/admin/user/show', url_for(rs, { :action => 'show' }, { :controller => 'admin/user', :action => 'list', :id => '10' }) - assert_equal '/admin/user/list/10', url_for(rs, {}, { :controller => 'admin/user', :action => 'list', :id => '10' }) + get URI('http://test.host/admin/user/list/10') + + assert_equal({ :controller => 'admin/user', :action => 'list', :id => '10' }, + controller.request.path_parameters) - assert_equal '/admin/stuff', url_for(rs, { :controller => 'stuff' }, { :controller => 'admin/user', :action => 'list', :id => '10' }) - assert_equal '/stuff', url_for(rs, { :controller => '/stuff' }, { :controller => 'admin/user', :action => 'list', :id => '10' }) + assert_equal '/admin/user/show', controller.url_for({ :action => 'show', :only_path => true }) + assert_equal '/admin/user/list/10', controller.url_for({:only_path => true}) + + assert_equal '/admin/stuff', controller.url_for({ :controller => 'stuff', :only_path => true }) + assert_equal '/stuff', controller.url_for({ :controller => '/stuff', :only_path => true }) end def test_ignores_leading_slash @@ -419,14 +451,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase get 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com' end routes = setup_for_named_route - routes.expects(:url_for).with({ - :host => 'foo.com', - :only_path => false, - :controller => 'content', - :action => 'show_page', - :use_route => 'pages' - }).once - routes.send(:pages_url) + assert_equal "http://foo.com/page", routes.pages_url end def setup_for_named_route(options = {}) @@ -499,9 +524,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_changing_controller rs.draw { get ':controller/:action/:id' } + get URI('http://test.host/admin/user/index/10') + assert_equal '/admin/stuff/show/10', - url_for(rs, {:controller => 'stuff', :action => 'show', :id => 10}, - {:controller => 'admin/user', :action => 'index'}) + controller.url_for({:controller => 'stuff', :action => 'show', :id => 10, :only_path => true}) end def test_paths_escaped @@ -560,8 +586,12 @@ class LegacyRouteSetTests < ActiveSupport::TestCase get '*path' => 'content#show_file' end + get URI('http://test.host/pages/boo') + assert_equal({:controller=>"content", :action=>"show_file", :path=>"pages/boo"}, + controller.request.path_parameters) + assert_equal '/pages/boo', - url_for(rs, {}, { :controller => 'content', :action => 'show_file', :path => %w(pages boo) }) + controller.url_for(:only_path => true) end def test_backwards @@ -570,7 +600,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase get ':controller(/:action(/:id))' end - assert_equal '/page/20', url_for(rs, { :id => 20 }, { :controller => 'pages', :action => 'show' }) + get URI('http://test.host/pages/show') + assert_equal '/page/20', controller.url_for({ :id => 20, :only_path => true }) assert_equal '/page/20', url_for(rs, { :controller => 'pages', :id => 20, :action => 'show' }) assert_equal '/pages/boo', url_for(rs, { :controller => 'pages', :action => 'boo' }) end @@ -611,7 +642,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_action_expiry rs.draw { get ':controller(/:action(/:id))' } - assert_equal '/content', url_for(rs, { :controller => 'content' }, { :controller => 'content', :action => 'show' }) + get URI('http://test.host/content/show') + assert_equal '/content', controller.url_for(:controller => 'content', :only_path => true) end def test_requirement_should_prevent_optional_id @@ -654,14 +686,18 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal '/pages/2005/6/12', url_for(rs, { :controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12 }) + get URI('http://test.host/pages/2005/6/12') + assert_equal({ :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }, + controller.request.path_parameters) + assert_equal '/pages/2005/6/4', - url_for(rs, { :day => 4 }, { :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }) + controller.url_for({ :day => 4, :only_path => true }) assert_equal '/pages/2005/6', - url_for(rs, { :day => nil }, { :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }) + controller.url_for({ :day => nil, :only_path => true }) assert_equal '/pages/2005', - url_for(rs, { :day => nil, :month => nil }, { :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }) + controller.url_for({ :day => nil, :month => nil, :only_path => true }) end def test_root_url_generation_with_controller_and_action @@ -819,9 +855,15 @@ end class RouteSetTest < ActiveSupport::TestCase include RoutingTestHelpers + include ActionDispatch::RoutingVerbs - def set - @set ||= ROUTING::RouteSet.new + attr_reader :set + alias :routes :set + attr_accessor :controller + + def setup + super + @set = make_set end def request @@ -922,7 +964,8 @@ class RouteSetTest < ActiveSupport::TestCase get '/admin/users' => 'admin/users#index', :as => "users" end - MockController.build(set.url_helpers).new + get URI('http://test.host/people') + controller end def test_named_route_url_method @@ -1019,12 +1062,12 @@ class RouteSetTest < ActiveSupport::TestCase get '/:controller(/:action(/:id))' end - assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages')) - assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages/index')) - assert_equal({:controller => 'pages', :action => 'list'}, set.recognize_path('/pages/list')) + assert_equal({:controller => 'pages', :action => 'index'}, request_path_params('/pages')) + assert_equal({:controller => 'pages', :action => 'index'}, request_path_params('/pages/index')) + assert_equal({:controller => 'pages', :action => 'list'}, request_path_params('/pages/list')) - assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/pages/show/10')) - assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10')) + assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, request_path_params('/pages/show/10')) + assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, request_path_params('/page/10')) end def test_route_constraints_on_request_object_with_anchors_are_valid @@ -1076,9 +1119,7 @@ class RouteSetTest < ActiveSupport::TestCase get "/people" => "missing#index" end - assert_raise(ActionController::RoutingError) { - set.recognize_path("/people", :method => :get) - } + assert_raises(ActionController::RoutingError) { request_path_params '/people' } end def test_recognize_with_encoded_id_and_regex @@ -1086,8 +1127,8 @@ class RouteSetTest < ActiveSupport::TestCase get 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/ end - assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10')) - assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world')) + assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, request_path_params('/page/10')) + assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, request_path_params('/page/hello+world')) end def test_recognize_with_http_methods @@ -1100,40 +1141,40 @@ class RouteSetTest < ActiveSupport::TestCase delete "/people/:id" => "people#destroy" end - params = set.recognize_path("/people", :method => :get) + params = request_path_params("/people", :method => :get) assert_equal("index", params[:action]) - params = set.recognize_path("/people", :method => :post) + params = request_path_params("/people", :method => :post) assert_equal("create", params[:action]) - params = set.recognize_path("/people/5", :method => :put) + params = request_path_params("/people/5", :method => :put) assert_equal("update", params[:action]) - params = set.recognize_path("/people/5", :method => :patch) + params = request_path_params("/people/5", :method => :patch) assert_equal("update", params[:action]) assert_raise(ActionController::UnknownHttpMethod) { - set.recognize_path("/people", :method => :bacon) + request_path_params("/people", :method => :bacon) } - params = set.recognize_path("/people/5", :method => :get) + params = request_path_params("/people/5", :method => :get) assert_equal("show", params[:action]) assert_equal("5", params[:id]) - params = set.recognize_path("/people/5", :method => :put) + params = request_path_params("/people/5", :method => :put) assert_equal("update", params[:action]) assert_equal("5", params[:id]) - params = set.recognize_path("/people/5", :method => :patch) + params = request_path_params("/people/5", :method => :patch) assert_equal("update", params[:action]) assert_equal("5", params[:id]) - params = set.recognize_path("/people/5", :method => :delete) + params = request_path_params("/people/5", :method => :delete) assert_equal("destroy", params[:action]) assert_equal("5", params[:id]) assert_raise(ActionController::RoutingError) { - set.recognize_path("/people/5", :method => :post) + request_path_params("/people/5", :method => :post) } end @@ -1143,11 +1184,11 @@ class RouteSetTest < ActiveSupport::TestCase root :to => "people#index" end - params = set.recognize_path("/people", :method => :get) + params = request_path_params("/people", :method => :get) assert_equal("people", params[:controller]) assert_equal("index", params[:action]) - params = set.recognize_path("/", :method => :get) + params = request_path_params("/", :method => :get) assert_equal("people", params[:controller]) assert_equal("index", params[:action]) end @@ -1158,7 +1199,7 @@ class RouteSetTest < ActiveSupport::TestCase :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/ end - params = set.recognize_path("/articles/2005/11/05/a-very-interesting-article", :method => :get) + params = request_path_params("/articles/2005/11/05/a-very-interesting-article", :method => :get) assert_equal("permalink", params[:action]) assert_equal("2005", params[:year]) assert_equal("11", params[:month]) @@ -1172,7 +1213,7 @@ class RouteSetTest < ActiveSupport::TestCase get '/profile' => 'profile#index' end - set.recognize_path("/profile") rescue nil + request_path_params("/profile") rescue nil assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded" end @@ -1185,17 +1226,17 @@ class RouteSetTest < ActiveSupport::TestCase get "people/:id(.:format)" => "people#show" end - params = set.recognize_path("/people/5", :method => :get) + params = request_path_params("/people/5", :method => :get) assert_equal("show", params[:action]) assert_equal("5", params[:id]) - params = set.recognize_path("/people/5", :method => :put) + params = request_path_params("/people/5", :method => :put) assert_equal("update", params[:action]) - params = set.recognize_path("/people/5", :method => :patch) + params = request_path_params("/people/5", :method => :patch) assert_equal("update", params[:action]) - params = set.recognize_path("/people/5.png", :method => :get) + params = request_path_params("/people/5.png", :method => :get) assert_equal("show", params[:action]) assert_equal("5", params[:id]) assert_equal("png", params[:format]) @@ -1214,7 +1255,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_root_map set.draw { root :to => 'people#index' } - params = set.recognize_path("", :method => :get) + params = request_path_params("", :method => :get) assert_equal("people", params[:controller]) assert_equal("index", params[:action]) end @@ -1228,7 +1269,7 @@ class RouteSetTest < ActiveSupport::TestCase end - params = set.recognize_path("/api/inventory", :method => :get) + params = request_path_params("/api/inventory", :method => :get) assert_equal("api/products", params[:controller]) assert_equal("inventory", params[:action]) end @@ -1240,7 +1281,7 @@ class RouteSetTest < ActiveSupport::TestCase end end - params = set.recognize_path("/api", :method => :get) + params = request_path_params("/api", :method => :get) assert_equal("api/products", params[:controller]) assert_equal("index", params[:action]) end @@ -1252,7 +1293,7 @@ class RouteSetTest < ActiveSupport::TestCase end end - params = set.recognize_path("/prefix/inventory", :method => :get) + params = request_path_params("/prefix/inventory", :method => :get) assert_equal("api/products", params[:controller]) assert_equal("inventory", params[:action]) end @@ -1264,38 +1305,36 @@ class RouteSetTest < ActiveSupport::TestCase end end - params = set.recognize_path("/inventory", :method => :get) + params = request_path_params("/inventory", :method => :get) assert_equal("api/products", params[:controller]) assert_equal("inventory", params[:action]) end - def test_generate_changes_controller_module - set.draw { get ':controller/:action/:id' } - current = { :controller => "bling/bloop", :action => "bap", :id => 9 } - - assert_equal "/foo/bar/baz/7", - url_for(set, { :controller => "foo/bar", :action => "baz", :id => 7 }, current) - end - def test_id_is_sticky_when_it_ought_to_be + @set = make_set false + set.draw do get ':controller/:id/:action' end - url = url_for(set, { :action => "destroy" }, { :controller => "people", :action => "show", :id => "7" }) - assert_equal "/people/7/destroy", url + get URI('http://test.host/people/7/show') + + assert_equal "/people/7/destroy", controller.url_for(:action => 'destroy', :only_path => true) end def test_use_static_path_when_possible + @set = make_set false + set.draw do get 'about' => "welcome#about" get ':controller/:action/:id' end - url = url_for(set, { :controller => "welcome", :action => "about" }, - { :controller => "welcome", :action => "get", :id => "7" }) + get URI('http://test.host/welcom/get/7') - assert_equal "/about", url + assert_equal "/about", controller.url_for(:controller => 'welcome', + :action => 'about', + :only_path => true) end def test_generate @@ -1330,38 +1369,51 @@ class RouteSetTest < ActiveSupport::TestCase end def test_named_routes_are_never_relative_to_modules + @set = make_set false + set.draw do 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' }) + assert_equal({ :controller => 'connection/manage', + :action => 'index', }, request_path_params('/connection/manage')) + + url = controller.url_for({ :controller => "connection", :only_path => true }) assert_equal "/connection/connection", url - url = url_for(set, { :use_route => :family_connection, :controller => "connection" }, { :controller => 'connection/manage' }) + url = controller.url_for({ :use_route => :family_connection, + :controller => "connection", :only_path => true }) assert_equal "/connection", url end def test_action_left_off_when_id_is_recalled + @set = make_set false + set.draw do get ':controller(/:action(/:id))' end - assert_equal '/books', url_for(set, - {:controller => 'books', :action => 'index'}, - {:controller => 'books', :action => 'show', :id => '10'} - ) + + get URI('http://test.host/books/show/10') + + assert_equal '/books', controller.url_for(:controller => 'books', + :only_path => true, + :action => 'index') end def test_query_params_will_be_shown_when_recalled + @set = make_set false + set.draw do get 'show_weblog/:parameter' => 'weblog#show' get ':controller(/:action(/:id))' end - assert_equal '/weblog/edit?parameter=1', url_for(set, - {:action => 'edit', :parameter => 1}, - {:controller => 'weblog', :action => 'show', :parameter => 1} - ) + + get URI('http://test.host/weblog/show/1') + + assert_equal '/weblog/edit?parameter=1', controller.url_for( + {:action => 'edit', :parameter => 1, :only_path => true}) end def test_format_is_not_inherit @@ -1369,22 +1421,30 @@ class RouteSetTest < ActiveSupport::TestCase get '/posts(.:format)' => 'posts#index' end - assert_equal '/posts', url_for(set, - {:controller => 'posts'}, - {:controller => 'posts', :action => 'index', :format => 'xml'} - ) + get URI('http://test.host/posts.xml') + assert_equal({:controller => 'posts', :action => 'index', :format => 'xml'}, + controller.request.path_parameters) - assert_equal '/posts.xml', url_for(set, - {:controller => 'posts', :format => 'xml'}, - {:controller => 'posts', :action => 'index', :format => 'xml'} - ) + assert_equal '/posts', controller.url_for( + {:controller => 'posts', :only_path => true}) + + assert_equal '/posts.xml', controller.url_for( + {:controller => 'posts', :format => 'xml', :only_path => true}) end def test_expiry_determination_should_consider_values_with_to_param + @set = make_set false + 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' }) + + get URI('http://test.host/projects/1/weblog/show') + + assert_equal( + { :controller => 'weblog', :action => 'show', :project_id => '1' }, + controller.request.path_parameters) + + assert_equal '/projects/1/weblog/show', + controller.url_for({ :action => 'show', :project_id => 1, :only_path => true }) end def test_named_route_in_nested_resource @@ -1587,7 +1647,6 @@ class RouteSetTest < ActiveSupport::TestCase end def test_slashes_are_implied - @set = nil set.draw { get("/:controller(/:action(/:id))") } assert_equal '/content', url_for(set, { :controller => 'content', :action => 'index' }) @@ -1685,7 +1744,43 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal '/ibocorp', url_for(set, { :controller => 'ibocorp', :action => "show", :page => 1 }) end + include ActionDispatch::RoutingVerbs + + class TestSet < ROUTING::RouteSet + def initialize(block) + @block = block + super() + end + + class Dispatcher < ROUTING::RouteSet::Dispatcher + def initialize(defaults, set, block) + super(defaults) + @block = block + @set = set + end + + def controller_reference(controller_param) + block = @block + set = @set + Class.new(ActionController::Base) { + include set.url_helpers + define_method(:process) { |name| block.call(self) } + def to_a; [200, {}, []]; end + } + end + end + + def dispatcher defaults + TestSet::Dispatcher.new defaults, self, @block + end + end + + alias :routes :set + def test_generate_with_optional_params_recalls_last_request + controller = nil + @set = TestSet.new ->(c) { controller = c } + set.draw do get "blog/", :controller => "blog", :action => "index" @@ -1700,23 +1795,29 @@ class RouteSetTest < ActiveSupport::TestCase get "*anything", :controller => "blog", :action => "unknown_request" end - assert_equal({:controller => "blog", :action => "index"}, set.recognize_path("/blog")) - assert_equal({:controller => "blog", :action => "show", :id => "123"}, set.recognize_path("/blog/show/123")) - assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :day => nil, :month => nil }, set.recognize_path("/blog/2004")) - assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12", :day => nil }, set.recognize_path("/blog/2004/12")) - assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12", :day => "25"}, set.recognize_path("/blog/2004/12/25")) - assert_equal({:controller => "articles", :action => "edit", :id => "123"}, set.recognize_path("/blog/articles/edit/123")) - assert_equal({:controller => "articles", :action => "show_stats"}, set.recognize_path("/blog/articles/show_stats")) - assert_equal({:controller => "blog", :action => "unknown_request", :anything => "blog/wibble"}, set.recognize_path("/blog/wibble")) - assert_equal({:controller => "blog", :action => "unknown_request", :anything => "junk"}, set.recognize_path("/junk")) + recognize_path = ->(path) { + get(URI("http://example.org" + path)) + controller.request.path_parameters + } - last_request = set.recognize_path("/blog/2006/07/28").freeze - assert_equal({:controller => "blog", :action => "show_date", :year => "2006", :month => "07", :day => "28"}, last_request) - assert_equal("/blog/2006/07/25", url_for(set, { :day => 25 }, last_request)) - assert_equal("/blog/2005", url_for(set, { :year => 2005 }, last_request)) - assert_equal("/blog/show/123", url_for(set, { :action => "show" , :id => 123 }, last_request)) - assert_equal("/blog/2006", url_for(set, { :year => 2006 }, last_request)) - assert_equal("/blog/2006", url_for(set, { :year => 2006, :month => nil }, last_request)) + assert_equal({:controller => "blog", :action => "index"}, recognize_path.("/blog")) + assert_equal({:controller => "blog", :action => "show", :id => "123"}, recognize_path.("/blog/show/123")) + assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :day => nil, :month => nil }, recognize_path.("/blog/2004")) + assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12", :day => nil }, recognize_path.("/blog/2004/12")) + assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12", :day => "25"}, recognize_path.("/blog/2004/12/25")) + assert_equal({:controller => "articles", :action => "edit", :id => "123"}, recognize_path.("/blog/articles/edit/123")) + assert_equal({:controller => "articles", :action => "show_stats"}, recognize_path.("/blog/articles/show_stats")) + assert_equal({:controller => "blog", :action => "unknown_request", :anything => "blog/wibble"}, recognize_path.("/blog/wibble")) + assert_equal({:controller => "blog", :action => "unknown_request", :anything => "junk"}, recognize_path.("/junk")) + + get URI('http://example.org/blog/2006/07/28') + + assert_equal({:controller => "blog", :action => "show_date", :year => "2006", :month => "07", :day => "28"}, controller.request.path_parameters) + assert_equal("/blog/2006/07/25", controller.url_for({ :day => 25, :only_path => true })) + assert_equal("/blog/2005", controller.url_for({ :year => 2005, :only_path => true })) + assert_equal("/blog/show/123", controller.url_for({ :action => "show" , :id => 123, :only_path => true })) + assert_equal("/blog/2006", controller.url_for({ :year => 2006, :only_path => true })) + assert_equal("/blog/2006", controller.url_for({ :year => 2006, :month => nil, :only_path => true })) end private @@ -1789,6 +1890,9 @@ class RackMountIntegrationTests < ActiveSupport::TestCase root :to => "news#index" } + attr_reader :routes + attr_reader :controller + def setup @routes = ActionDispatch::Routing::RouteSet.new @routes.draw(&Mapping) diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index 4df2f8b98d..c002cf4d8f 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -9,6 +9,7 @@ end class SendFileController < ActionController::Base include TestFileUtils + include ActionController::Testing layout "layouts/standard" # to make sure layouts don't interfere attr_writer :options @@ -30,11 +31,8 @@ class SendFileWithActionControllerLive < SendFileController end class SendFileTest < ActionController::TestCase - tests SendFileController include TestFileUtils - Mime::Type.register "image/png", :png unless defined? Mime::PNG - def setup @controller = SendFileController.new @request = ActionController::TestRequest.new @@ -201,8 +199,6 @@ class SendFileTest < ActionController::TestCase end end - tests SendFileWithActionControllerLive - def test_send_file_with_action_controller_live @controller = SendFileWithActionControllerLive.new @controller.options = { :content_type => "application/x-ruby" } diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index ff23b22040..f7eba1ef43 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -32,7 +32,7 @@ module ShowExceptions 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| + ['127.0.0.1', '127.0.0.127', '127.12.1.1', '::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) diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index fbc10baf21..3b3b15c061 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -164,7 +164,7 @@ XML end class DefaultUrlOptionsCachingController < ActionController::Base - before_filter { @dynamic_opt = 'opt' } + before_action { @dynamic_opt = 'opt' } def test_url_options_reset render text: url_for(params) @@ -662,7 +662,7 @@ XML def test_id_converted_to_string get :test_params, :id => 20, :foo => Object.new - assert_kind_of String, @request.path_parameters['id'] + assert_kind_of String, @request.path_parameters[:id] end def test_array_path_parameter_handled_properly @@ -673,17 +673,17 @@ XML end get :test_params, :path => ['hello', 'world'] - assert_equal ['hello', 'world'], @request.path_parameters['path'] - assert_equal 'hello/world', @request.path_parameters['path'].to_param + assert_equal ['hello', 'world'], @request.path_parameters[:path] + assert_equal 'hello/world', @request.path_parameters[:path].to_param 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 + # All elements of path_parameters should use Symbol keys @request.path_parameters.keys.each do |key| - assert_kind_of String, key + assert_kind_of Symbol, key end end @@ -737,12 +737,12 @@ XML assert_equal "baz", @request.filtered_parameters[:foo] end - def test_symbolized_path_params_reset_after_request + def test_path_params_reset_after_request get :test_params, :id => "foo" - assert_equal "foo", @request.symbolized_path_parameters[:id] + assert_equal "foo", @request.path_parameters[:id] @request.recycle! get :test_params - assert_nil @request.symbolized_path_parameters[:id] + assert_nil @request.path_parameters[:id] end def test_request_protocol_is_reset_after_request diff --git a/actionpack/test/controller/url_for_integration_test.rb b/actionpack/test/controller/url_for_integration_test.rb index 6c2311e7a5..24a09222b1 100644 --- a/actionpack/test/controller/url_for_integration_test.rb +++ b/actionpack/test/controller/url_for_integration_test.rb @@ -6,6 +6,7 @@ require 'active_support/core_ext/object/with_options' module ActionPack class URLForIntegrationTest < ActiveSupport::TestCase include RoutingTestHelpers + include ActionDispatch::RoutingVerbs Model = Struct.new(:to_param) @@ -61,8 +62,11 @@ module ActionPack root :to => "news#index" } + attr_reader :routes + attr_accessor :controller + def setup - @routes = ActionDispatch::Routing::RouteSet.new + @routes = make_set false @routes.draw(&Mapping) end @@ -70,9 +74,9 @@ module ActionPack ['/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/users',[ { :action => 'index' }, { :controller => 'admin/users', :action => 'index' }, '/admin/users']], + ['/admin/users',[ { :controller => 'users', :action => 'index' }, { :controller => 'admin/accounts', :action => 'show', :id => '1' }, '/admin/accounts/show/1']], + ['/people',[ { :controller => '/people', :action => 'index' }, {:controller=>"admin/accounts", :action=>"foo", :id=>"bar"}, '/admin/accounts/foo/bar']], ['/admin/posts',[ { :controller => 'admin/posts' }]], ['/admin/posts/new',[ { :controller => 'admin/posts', :action => 'new' }]], @@ -86,11 +90,11 @@ module ActionPack ['/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',[ { :action => 'index' }, { :controller => 'people', :action => 'index' }, '/people']], + ['/people',[ { :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }, '/people/show/1']], + ['/people',[ { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }, '/people/show/1']], + ['/people',[ {}, { :controller => 'people', :action => 'index' }, '/people']], + ['/people/1',[ { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'show', :id => '1' }, '/people/show/1']], ['/people/new',[ { :use_route => 'new_person' }]], ['/people/new',[ { :controller => 'people', :action => 'new' }]], ['/people/1',[ { :use_route => 'person', :id => '1' }]], @@ -98,11 +102,11 @@ module ActionPack ['/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',[ { :action => 'show', :id => '1' }, { :controller => 'people', :action => 'index' }, '/people']], + ['/people/1',[ { :action => 'show', :id => 1 }, { :controller => 'people', :action => 'show', :id => '1' }, '/people/show/1']], + ['/people',[ { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }, '/people/show/1']], + ['/people/1',[ {}, { :controller => 'people', :action => 'show', :id => '1' }, '/people/show/1']], + ['/people/1',[ { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'index', :id => '1' }, '/people/index/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' }]], @@ -118,16 +122,15 @@ module ActionPack ['/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',[ { :controller => 'project', :action => 'index'}, {:project_id => '1', :controller => 'project', :action => 'index' }, '/projects/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' }]], + ['/projects/1',[ { :use_route => 'project', :controller => 'project', :action => 'index' }, { :controller => 'project', :action => 'index', :project_id => '1' }, '/projects/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' }]], + ['/clients',[ { :controller => 'projects', :action => 'index' }, { :project_id => '1', :controller => 'project', :action => 'index' }, '/projects/1']], - ['/comment/20',[ { :id => 20 }, { :controller => 'comments', :action => 'show' }]], + ['/comment/20',[ { :id => 20 }, { :controller => 'comments', :action => 'show' }, '/comments/show']], ['/comment/20',[ { :controller => 'comments', :id => 20, :action => 'show' }]], ['/comments/boo',[ { :controller => 'comments', :action => 'boo' }]], @@ -144,24 +147,21 @@ module ActionPack ['/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' }]], + ['/notes/print',[ {}, { :controller => 'notes', :action => 'print' }, '/notes/print']], + + ['/notes/index/1',[ { :controller => 'notes' }, { :controller => 'notes', :action => 'index', :id => '1' }, '/notes/index/1']], + ['/notes/index/1',[ { :controller => 'notes' }, { :controller => 'notes', :id => '1', :action => 'index' }, '/notes/index/1']], + ['/notes/index/1',[ { :action => 'index' }, { :controller => 'notes', :id => '1', :action => 'index' }, '/notes/index/1']], + ['/notes/index/1',[ {}, { :controller => 'notes', :id => '1', :action => 'index' }, '/notes/index/1']], + ['/notes/show/1',[ {}, { :controller => 'notes', :action => 'show', :id => '1' }, '/notes/show/1']], + ['/posts',[ { :controller => 'posts' }, { :controller => 'notes', :action => 'show', :id => '1' }, '/notes/show/1']], + ['/notes/list',[ { :action => 'list' }, { :controller => 'notes', :action => 'show', :id => '1' }, '/notes/show/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/create',[ { :action => 'create' }, {:day=>nil, :month=>nil, :controller=>"posts", :action=>"show_date"}, '/blog']], ['/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 }]], @@ -169,9 +169,20 @@ module ActionPack ['/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 + if params.length > 1 + hash, path_params, route = *params + hash[:only_path] = true + + define_method("test_#{url.gsub(/\W/, '_')}_#{i}") do + get URI('http://test.host' + route.to_s) + assert_equal path_params, controller.request.path_parameters + assert_equal url, controller.url_for(hash), params.inspect + end + else + define_method("test_#{url.gsub(/\W/, '_')}_#{i}") do + assert_equal url, url_for(@routes, params.first), params.inspect + end + end end end end diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index a8035e5bd7..9f086af664 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -11,6 +11,26 @@ module AbstractController W.default_url_options.clear end + def test_nested_optional + klass = Class.new { + include ActionDispatch::Routing::RouteSet.new.tap { |r| + r.draw { + get "/foo/(:bar/(:baz))/:zot", :as => 'fun', + :controller => :articles, + :action => :index + } + }.url_helpers + self.default_url_options[:host] = 'example.com' + } + + path = klass.new.fun_path({:controller => :articles, + :baz => "baz", + :zot => "zot", + :only_path => true }) + # :bar key isn't provided + assert_equal '/foo/zot', path + end + def add_host! W.default_url_options[:host] = 'www.basecamphq.com' end @@ -75,7 +95,7 @@ module AbstractController end def test_subdomain_may_be_object - model = mock(:to_param => 'api') + model = Class.new { def self.to_param; 'api'; end } add_host! assert_equal('http://api.basecamphq.com/c/a/i', W.new.url_for(:subdomain => model, :controller => 'c', :action => 'a', :id => 'i') @@ -169,6 +189,18 @@ module AbstractController ) end + def test_without_protocol_and_with_port + add_host! + add_port! + + assert_equal('//www.basecamphq.com:3000/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => '//') + ) + assert_equal('//www.basecamphq.com:3000/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => false) + ) + end + def test_trailing_slash add_host! options = {:controller => 'foo', :trailing_slash => true, :action => 'bar', :id => '33'} @@ -255,12 +287,12 @@ module AbstractController # We need to create a new class in order to install the new named route. kls = Class.new { include set.url_helpers } controller = kls.new - assert controller.respond_to?(:home_url) + assert_respond_to controller, :home_url assert_equal '/brave/new/world', - controller.send(:url_for, :controller => 'brave', :action => 'new', :id => 'world', :only_path => true) + controller.url_for(:controller => 'brave', :action => 'new', :id => 'world', :only_path => true) - assert_equal("/home/sweet/home/alabama", controller.send(:home_url, :user => 'alabama', :host => 'unused', :only_path => true)) - assert_equal("/home/sweet/home/alabama", controller.send(:home_path, 'alabama')) + assert_equal("/home/sweet/home/alabama", controller.home_path(:user => 'alabama', :host => 'unused', :only_path => true)) + assert_equal("/home/sweet/home/alabama", controller.home_path('alabama')) end end diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index 8660deb634..24526fb00e 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -10,6 +10,8 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest @closed = false end + # We're obliged to implement this (even though it doesn't actually + # get called here) to properly comply with the Rack SPEC def each end diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index 9e37b96951..e2b38c23bc 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -55,6 +55,8 @@ class HeaderTest < ActiveSupport::TestCase test "key?" do assert @headers.key?("CONTENT_TYPE") assert @headers.include?("CONTENT_TYPE") + assert @headers.key?("Content-Type") + assert @headers.include?("Content-Type") end test "fetch with block" do diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb index 58457b0c28..3e554a9cf6 100644 --- a/actionpack/test/dispatch/mapper_test.rb +++ b/actionpack/test/dispatch/mapper_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module ActionDispatch module Routing class MapperTest < ActiveSupport::TestCase - class FakeSet + class FakeSet < ActionDispatch::Routing::RouteSet attr_reader :routes alias :set :routes @@ -38,7 +38,7 @@ module ActionDispatch def test_mapping_requirements options = { :controller => 'foo', :action => 'bar', :via => :get } - m = Mapper::Mapping.new FakeSet.new, {}, '/store/:name(*rest)', options + m = Mapper::Mapping.build({}, FakeSet.new, '/store/:name(*rest)', options) _, _, requirements, _ = m.to_route assert_equal(/.+?/, requirements[:rest]) end @@ -72,7 +72,7 @@ module ActionDispatch mapper = Mapper.new fakeset 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] + assert_equal(/.+?/, fakeset.requirements.first[:path]) end def test_map_wildcard_with_multiple_wildcard @@ -80,7 +80,7 @@ module ActionDispatch mapper = Mapper.new fakeset 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[:foo]) assert_equal(/.+?/, fakeset.requirements.first[:bar]) end diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 981cf2426e..d29cc8473e 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -1,8 +1,6 @@ require 'abstract_unit' class MimeTypeTest < ActiveSupport::TestCase - Mime::Type.register "image/png", :png unless defined? Mime::PNG - Mime::Type.register "application/pdf", :pdf unless defined? Mime::PDF test "parse single" do Mime::LOOKUP.keys.each do |mime_type| diff --git a/actionpack/test/dispatch/mount_test.rb b/actionpack/test/dispatch/mount_test.rb index cdf00d84fb..d5a4d8ee11 100644 --- a/actionpack/test/dispatch/mount_test.rb +++ b/actionpack/test/dispatch/mount_test.rb @@ -1,12 +1,18 @@ require 'abstract_unit' +require 'rails/engine' class TestRoutingMount < ActionDispatch::IntegrationTest Router = ActionDispatch::Routing::RouteSet.new - class FakeEngine + class AppWithRoutes < Rails::Engine def self.routes @routes ||= ActionDispatch::Routing::RouteSet.new end + end + + # Test for mounting apps that respond to routes, but aren't Rails-like apps. + class SinatraLikeApp + def self.routes; Object.new; end def self.call(env) [200, {"Content-Type" => "text/html"}, ["OK"]] @@ -21,20 +27,23 @@ class TestRoutingMount < ActionDispatch::IntegrationTest mount SprocketsApp, :at => "/sprockets" mount SprocketsApp => "/shorthand" - mount FakeEngine, :at => "/fakeengine", :as => :fake - mount FakeEngine, :at => "/getfake", :via => :get + mount SinatraLikeApp, :at => "/fakeengine", :as => :fake + mount SinatraLikeApp, :at => "/getfake", :via => :get scope "/its_a" do mount SprocketsApp, :at => "/sprocket" end resources :users do - mount FakeEngine, :at => "/fakeengine", :as => :fake_mounted_at_resource + mount AppWithRoutes, :at => "/fakeengine", :as => :fake_mounted_at_resource end + + mount SprocketsApp, :at => "/", :via => :get end + APP = RoutedRackApp.new Router def app - Router + APP end def test_app_name_is_properly_generated_when_engine_is_mounted_in_resources @@ -44,6 +53,11 @@ class TestRoutingMount < ActionDispatch::IntegrationTest "A named route should be defined with a parent's prefix" end + def test_mounting_at_root_path + get "/omg" + assert_equal " -- /omg", response.body + end + def test_mounting_sets_script_name get "/sprockets/omg" assert_equal "/sprockets -- /omg", response.body diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 08501d19c0..c6e4eefa7a 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'rack/test' +require 'rails/engine' module TestGenerationPrefix class Post @@ -15,12 +16,15 @@ module TestGenerationPrefix ActiveModel::Name.new(klass) end + + def to_model; self; end + def persisted?; true; end end class WithMountedEngine < ActionDispatch::IntegrationTest include Rack::Test::Methods - class BlogEngine + class BlogEngine < Rails::Engine def self.routes @routes ||= begin routes = ActionDispatch::Routing::RouteSet.new diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb index ce9ccfcee8..62e8197e20 100644 --- a/actionpack/test/dispatch/reloader_test.rb +++ b/actionpack/test/dispatch/reloader_test.rb @@ -3,6 +3,11 @@ require 'abstract_unit' class ReloaderTest < ActiveSupport::TestCase Reloader = ActionDispatch::Reloader + teardown do + Reloader.reset_callbacks :prepare + Reloader.reset_callbacks :cleanup + end + def test_prepare_callbacks a = b = c = nil Reloader.to_prepare { |*args| a = b = c = 1 } diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 2a2f92b5b3..926472163e 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -8,7 +8,11 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest end def parse - self.class.last_request_parameters = request.request_parameters + self.class.last_request_parameters = begin + request.request_parameters + rescue EOFError + {} + end self.class.last_parameters = request.parameters head :ok end @@ -145,7 +149,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest test "does not raise EOFError on GET request with multipart content-type" do with_routing do |set| set.draw do - get ':action', to: 'multipart_params_parsing_test/test' + get ':action', controller: 'multipart_params_parsing_test/test' end headers = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x" } get "/parse", {}, headers @@ -174,7 +178,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - post ':action', :to => 'multipart_params_parsing_test/test' + post ':action', :controller => '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 d82493140f..4e99c26e03 100644 --- a/actionpack/test/dispatch/request/query_string_parsing_test.rb +++ b/actionpack/test/dispatch/request/query_string_parsing_test.rb @@ -105,6 +105,7 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest end test "perform_deep_munge" do + old_perform_deep_munge = ActionDispatch::Request::Utils.perform_deep_munge ActionDispatch::Request::Utils.perform_deep_munge = false begin assert_parses({"action" => nil}, "action") @@ -115,7 +116,7 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest assert_parses({"action" => {"foo" => [{"bar" => nil}]}}, "action[foo][][bar]") assert_parses({"action" => ['1',nil]}, "action[]=1&action[]") ensure - ActionDispatch::Request::Utils.perform_deep_munge = true + ActionDispatch::Request::Utils.perform_deep_munge = old_perform_deep_munge 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 9a77454f30..1de05cbf09 100644 --- a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb @@ -130,10 +130,7 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest end test "ambiguous params returns a bad request" do - with_routing do |set| - set.draw do - post ':action', to: ::UrlEncodedParamsParsingTest::TestController - end + with_test_routing do post "/parse", "foo[]=bar&foo[4]=bar" assert_response :bad_request end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 6e21b4a258..6737609567 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -152,9 +152,12 @@ class RequestIP < BaseRequestTest 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::' + 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::, fc01::, fdff' assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'FE00::, FDFF::' + assert_equal 'FE00::', request.remote_ip + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address' assert_equal nil, request.remote_ip end @@ -525,6 +528,13 @@ class RequestCGI < BaseRequestTest end end +class LocalhostTest < BaseRequestTest + test "IPs that match localhost" do + request = stub_request("REMOTE_IP" => "127.1.1.1", "REMOTE_ADDR" => "127.1.1.1") + assert request.local? + end +end + class RequestCookie < BaseRequestTest test "cookie syntax resilience" do request = stub_request("HTTP_COOKIE" => "_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes") @@ -629,12 +639,14 @@ class RequestProtocol < BaseRequestTest end class RequestMethod < BaseRequestTest - test "request methods" do - [:post, :get, :patch, :put, :delete].each do |method| - request = stub_request('REQUEST_METHOD' => method.to_s.upcase) + test "method returns environment's request method when it has not been + overriden by middleware".squish do + + ActionDispatch::Request::HTTP_METHODS.each do |method| + request = stub_request('REQUEST_METHOD' => method) - assert_equal method.to_s.upcase, request.method - assert_equal method, request.method_symbol + assert_equal method, request.method + assert_equal method.underscore.to_sym, request.method_symbol end end @@ -644,28 +656,18 @@ class RequestMethod < BaseRequestTest end end - test "allow method hacking on post" do - %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 + test "method returns original value of environment request method on POST" do + request = stub_request('rack.methodoverride.original_method' => 'POST') + assert_equal 'POST', request.method end - test "invalid method hacking on post raises exception" do + test "method raises exception on invalid HTTP method" do assert_raise(ActionController::UnknownHttpMethod) do - stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').request_method + stub_request('rack.methodoverride.original_method' => '_RANDOM_METHOD').method end - end - test "restrict method hacking" do - [:get, :patch, :put, :delete].each do |method| - request = stub_request( - 'action_dispatch.request.request_parameters' => { :_method => 'put' }, - 'REQUEST_METHOD' => method.to_s.upcase - ) - - assert_equal method.to_s.upcase, request.method + assert_raise(ActionController::UnknownHttpMethod) do + stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').method end end @@ -795,6 +797,12 @@ class RequestFormat < BaseRequestTest assert_not request.format.json? end + test "format does not throw exceptions when malformed parameters" do + request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2") + assert request.formats + assert request.format.html? + end + test "formats with xhr request" do request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" request.expects(:parameters).at_least_once.returns({}) @@ -802,6 +810,7 @@ class RequestFormat < BaseRequestTest end test "ignore_accept_header" do + old_ignore_accept_header = ActionDispatch::Request.ignore_accept_header ActionDispatch::Request.ignore_accept_header = true begin @@ -831,7 +840,7 @@ class RequestFormat < BaseRequestTest request.expects(:parameters).at_least_once.returns({:format => :json}) assert_equal [ Mime::JSON ], request.formats ensure - ActionDispatch::Request.ignore_accept_header = false + ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header end end end @@ -889,15 +898,15 @@ class RequestParameters < BaseRequestTest assert_equal({"bar" => 2}, request.query_parameters) end - test "parameters still accessible after rack parse error" do + test "parameters not accessible after rack parse error" do request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2") - assert_raises(ActionController::BadRequest) do - # rack will raise a TypeError when parsing this query string - request.parameters + 2.times do + assert_raises(ActionController::BadRequest) do + # rack will raise a TypeError when parsing this query string + request.parameters + end end - - assert_equal({}, request.parameters) end test "we have access to the original exception" do @@ -1062,7 +1071,7 @@ class RequestEtag < BaseRequestTest end end -class RequestVarient < BaseRequestTest +class RequestVariant < BaseRequestTest test "setting variant" do request = stub_request diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 959a3bc5cd..187b9a2420 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -178,6 +178,7 @@ class ResponseTest < ActiveSupport::TestCase end test "read x_frame_options, x_content_type_options and x_xss_protection" do + original_default_headers = ActionDispatch::Response.default_headers begin ActionDispatch::Response.default_headers = { 'X-Frame-Options' => 'DENY', @@ -193,11 +194,12 @@ class ResponseTest < ActiveSupport::TestCase assert_equal('nosniff', resp.headers['X-Content-Type-Options']) assert_equal('1;', resp.headers['X-XSS-Protection']) ensure - ActionDispatch::Response.default_headers = nil + ActionDispatch::Response.default_headers = original_default_headers end end test "read custom default_header" do + original_default_headers = ActionDispatch::Response.default_headers begin ActionDispatch::Response.default_headers = { 'X-XX-XXXX' => 'Here is my phone number' @@ -209,7 +211,7 @@ class ResponseTest < ActiveSupport::TestCase assert_equal('Here is my phone number', resp.headers['X-XX-XXXX']) ensure - ActionDispatch::Response.default_headers = nil + ActionDispatch::Response.default_headers = original_default_headers end end diff --git a/actionpack/test/dispatch/routing/concerns_test.rb b/actionpack/test/dispatch/routing/concerns_test.rb index 9f37701656..7ef513b0c8 100644 --- a/actionpack/test/dispatch/routing/concerns_test.rb +++ b/actionpack/test/dispatch/routing/concerns_test.rb @@ -36,7 +36,8 @@ class RoutingConcernsTest < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = RoutedRackApp.new Routes + def app; APP end def test_accessing_concern_from_resources get "/posts/1/comments" diff --git a/actionpack/test/dispatch/routing/route_set_test.rb b/actionpack/test/dispatch/routing/route_set_test.rb index 0e488d2b88..c465d56bde 100644 --- a/actionpack/test/dispatch/routing/route_set_test.rb +++ b/actionpack/test/dispatch/routing/route_set_test.rb @@ -81,10 +81,6 @@ module ActionDispatch end private - def clear! - @set.clear! - end - def draw(&block) @set.draw(&block) end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index b22a56bb27..269c7b4159 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -99,6 +99,16 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_namespace_without_controller_segment + draw do + namespace :admin do + get 'hello/:controllers/:action' + end + end + get '/admin/hello/foo/new' + assert_equal 'foo', @request.params["controllers"] + end + def test_session_singleton_resource draw do resource :session do @@ -351,8 +361,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest draw do controller(:global) do get 'global/hide_notice' - get 'global/export', :to => :export, :as => :export_request - get '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ } + get 'global/export', :action => :export, :as => :export_request + get '/export/:id/:file', :action => :export, :as => :export_download, :constraints => { :file => /.*/ } get 'global/:action' end end @@ -720,8 +730,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest draw do resources :replies do member do - put :answer, :to => :mark_as_answer - delete :answer, :to => :unmark_as_answer + put :answer, :action => :mark_as_answer + delete :answer, :action => :unmark_as_answer end end end @@ -1178,7 +1188,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest controller :articles do scope '/articles', :as => 'article' do scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do - get '/:id', :to => :with_id, :as => "" + get '/:id', :action => :with_id, :as => "" end end end @@ -1425,7 +1435,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_scoped_controller_with_namespace_and_action draw do namespace :account do - get ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback + get ':action/callback', :action => /twitter|github/, :controller => "callbacks", :as => :callback end end @@ -1482,7 +1492,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_normalize_namespaced_matches draw do namespace :account do - get 'description', :to => :description, :as => "description" + get 'description', :action => :description, :as => "description" end end @@ -1723,7 +1733,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "whatever/:controller(/:action(/:id))" end - get 'whatever/foo/bar' + get '/whatever/foo/bar' assert_equal 'foo#bar', @response.body assert_equal 'http://www.example.com/whatever/foo/bar/1', @@ -1735,10 +1745,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "whatever/:controller(/:action(/:id))", :id => /\d+/ end - get 'whatever/foo/bar/show' + get '/whatever/foo/bar/show' assert_equal 'foo/bar#show', @response.body - get 'whatever/foo/bar/show/1' + get '/whatever/foo/bar/show/1' assert_equal 'foo/bar#show', @response.body assert_equal 'http://www.example.com/whatever/foo/bar/show', @@ -2012,6 +2022,28 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/blogs/1/posts/2/comments/new', new_blog_post_comment_path(:blog_id => 1, :post_id => 2) end + def test_direct_children_of_shallow_resources + draw do + resources :blogs do + resources :posts, shallow: true do + resources :comments + end + end + end + + post '/posts/1/comments' + assert_equal 'comments#create', @response.body + assert_equal '/posts/1/comments', post_comments_path('1') + + get '/posts/2/comments/new' + assert_equal 'comments#new', @response.body + assert_equal '/posts/2/comments/new', new_post_comment_path('2') + + get '/posts/1/comments' + assert_equal 'comments#index', @response.body + assert_equal '/posts/1/comments', post_comments_path('1') + end + def test_shallow_nested_resources_within_scope draw do scope '/hello' do @@ -2144,7 +2176,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end resources :invoices do get "outstanding" => "invoices#outstanding", :on => :collection - get "overdue", :to => :overdue, :on => :collection + get "overdue", :action => :overdue, :on => :collection get "print" => "invoices#print", :as => :print, :on => :member post "preview" => "invoices#preview", :as => :preview, :on => :new end @@ -2232,6 +2264,22 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/api/1.0/users/first.last.xml', api_user_path(:version => '1.0', :id => 'first.last', :format => :xml) end + def test_match_without_via + assert_raises(ArgumentError) do + draw do + match '/foo/bar', :to => 'files#show' + end + end + end + + def test_match_with_empty_via + assert_raises(ArgumentError) do + draw do + match '/foo/bar', :to => 'files#show', :via => [] + end + end + end + def test_glob_parameter_accepts_regexp draw do get '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/ @@ -2287,12 +2335,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "(/user/:username)/photos" => "photos#index" end - get 'user/bob/photos' + 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' + get '/photos' assert_equal 'photos#index', @response.body assert_equal 'http://www.example.com/photos', url_for(:controller => "photos", :action => "index", :username => nil) @@ -2805,7 +2853,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - def test_symbolized_path_parameters_is_not_stale + def test_path_parameters_is_not_stale draw do scope '/countries/:country', :constraints => lambda { |params, req| %w(all France).include?(params[:country]) } do get '/', :to => 'countries#index' @@ -2970,7 +3018,9 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end assert_raise(ArgumentError) do - draw { controller("/feeds") { get '/feeds/:service', :to => :show } } + assert_deprecated do + draw { controller("/feeds") { get '/feeds/:service', :to => :show } } + end end assert_raise(ArgumentError) do @@ -3120,7 +3170,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/downloads/1/1.tar' assert_equal 'downloads#show', @response.body - assert_equal expected_params, @request.symbolized_path_parameters + assert_equal expected_params, @request.path_parameters assert_equal '/downloads/1/1.tar', download_path('1') assert_equal '/downloads/1/1.tar', download_path('1', '1') end @@ -3137,6 +3187,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/foo', foo_root_path end + def test_namespace_as_controller + draw do + namespace :foo do + get '/', to: '/bar#index', as: 'root' + end + end + + get '/foo' + assert_equal 'bar#index', @response.body + assert_equal '/foo', foo_root_path + end + def test_trailing_slash draw do resources :streams @@ -3217,6 +3279,58 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/admin/posts/1/comments', admin_post_comments_path('1') end + def test_mix_string_to_controller_action + draw do + get '/projects', controller: 'project_files', + action: 'index', + to: 'comments#index' + end + get '/projects' + assert_equal 'comments#index', @response.body + end + + def test_mix_string_to_controller + draw do + get '/projects', controller: 'project_files', + to: 'comments#index' + end + get '/projects' + assert_equal 'comments#index', @response.body + end + + def test_mix_string_to_action + draw do + get '/projects', action: 'index', + to: 'comments#index' + end + get '/projects' + assert_equal 'comments#index', @response.body + end + + def test_mix_symbol_to_controller_action + assert_deprecated do + draw do + get '/projects', controller: 'project_files', + action: 'index', + to: :show + end + end + get '/projects' + assert_equal 'project_files#show', @response.body + end + + def test_mix_string_to_controller_action_no_hash + assert_deprecated do + draw do + get '/projects', controller: 'project_files', + action: 'index', + to: 'show' + end + end + get '/projects' + assert_equal 'show#index', @response.body + end + def test_shallow_path_and_prefix_are_not_added_to_non_shallow_routes draw do scope shallow_path: 'projects', shallow_prefix: 'project' do @@ -3329,19 +3443,19 @@ private def draw(&block) self.class.stub_controllers do |routes| - @app = routes - @app.default_url_options = { host: 'www.example.com' } - @app.draw(&block) + routes.default_url_options = { host: 'www.example.com' } + routes.draw(&block) + @app = RoutedRackApp.new routes end end def url_for(options = {}) - @app.url_helpers.url_for(options) + @app.routes.url_helpers.url_for(options) end def method_missing(method, *args, &block) if method.to_s =~ /_(path|url)$/ - @app.url_helpers.send(method, *args, &block) + @app.routes.url_helpers.send(method, *args, &block) else super end @@ -3368,12 +3482,14 @@ end class TestAltApp < ActionDispatch::IntegrationTest class AltRequest + attr_accessor :path_parameters, :path_info, :script_name + attr_reader :env + def initialize(env) + @path_parameters = {} @env = env - end - - def path_info - "/" + @path_info = "/" + @script_name = "" end def request_method @@ -3407,8 +3523,10 @@ class TestAltApp < ActionDispatch::IntegrationTest get "/" => TestAltApp::AltApp.new end + APP = build_app AltRoutes + def app - AltRoutes + APP end def test_alt_request_without_header @@ -3435,15 +3553,16 @@ class TestAppendingRoutes < ActionDispatch::IntegrationTest def setup super s = self - @app = ActionDispatch::Routing::RouteSet.new - @app.append do + routes = ActionDispatch::Routing::RouteSet.new + routes.append do get '/hello' => s.simple_app('fail') get '/goodbye' => s.simple_app('goodbye') end - @app.draw do + routes.draw do get '/hello' => s.simple_app('hello') end + @app = self.class.build_app routes end def test_goodbye_should_be_available @@ -3472,8 +3591,38 @@ class TestNamespaceWithControllerOption < ActionDispatch::IntegrationTest end def draw(&block) - @app = ActionDispatch::Routing::RouteSet.new - @app.draw(&block) + routes = ActionDispatch::Routing::RouteSet.new + routes.draw(&block) + @app = self.class.build_app routes + end + + def test_missing_controller + ex = assert_raises(ArgumentError) { + draw do + get '/foo/bar', :action => :index + end + } + assert_match(/Missing :controller/, ex.message) + end + + def test_missing_action + ex = assert_raises(ArgumentError) { + assert_deprecated do + draw do + get '/foo/bar', :to => 'foo' + end + end + } + assert_match(/Missing :action/, ex.message) + end + + def test_missing_action_on_hash + ex = assert_raises(ArgumentError) { + draw do + get '/foo/bar', :to => 'foo#' + end + } + assert_match(/Missing :action/, ex.message) end def test_valid_controller_options_inside_namespace @@ -3492,7 +3641,7 @@ class TestNamespaceWithControllerOption < ActionDispatch::IntegrationTest resources :storage_files, :controller => 'admin/storage_files' end - get 'storage_files' + get '/storage_files' assert_equal "admin/storage_files#index", @response.body end @@ -3517,6 +3666,16 @@ class TestNamespaceWithControllerOption < ActionDispatch::IntegrationTest assert_match "'Admin::StorageFiles' is not a supported controller name", e.message end + + def test_warn_with_ruby_constant_syntax_no_colons + e = assert_raise(ArgumentError) do + draw do + resources :storage_files, :controller => 'Admin' + end + end + + assert_match "'Admin' is not a supported controller name", e.message + end end class TestDefaultScope < ActionDispatch::IntegrationTest @@ -3534,8 +3693,10 @@ class TestDefaultScope < ActionDispatch::IntegrationTest resources :posts end + APP = build_app DefaultScopeRoutes + def app - DefaultScopeRoutes + APP end include DefaultScopeRoutes.url_helpers @@ -3553,24 +3714,28 @@ class TestHttpMethods < ActionDispatch::IntegrationTest RFC3648 = %w(ORDERPATCH) RFC3744 = %w(ACL) RFC5323 = %w(SEARCH) + RFC4791 = %w(MKCALENDAR) RFC5789 = %w(PATCH) def simple_app(response) lambda { |env| [ 200, { 'Content-Type' => 'text/plain' }, [response] ] } end - setup do + attr_reader :app + + def setup s = self - @app = ActionDispatch::Routing::RouteSet.new + routes = ActionDispatch::Routing::RouteSet.new + @app = RoutedRackApp.new routes - @app.draw do - (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789).each do |method| + routes.draw do + (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789).each do |method| match '/' => s.simple_app(method), :via => method.underscore.to_sym end end end - (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789).each do |method| + (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789).each do |method| test "request method #{method.underscore} can be matched" do get '/', nil, 'REQUEST_METHOD' => method assert_equal method, @response.body @@ -3594,7 +3759,8 @@ class TestUriPathEscaping < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end test 'escapes slash in generated path segment' do assert_equal '/a%20b%2Fc+d', segment_path(:segment => 'a b/c+d') @@ -3625,7 +3791,8 @@ class TestUnicodePaths < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end test 'recognizes unicode path' do get "/#{Rack::Utils.escape("ほげ")}" @@ -3656,7 +3823,8 @@ class TestMultipleNestedController < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end test "controller option which starts with '/' from multiple nested controller" do get "/foo/bar/baz" @@ -3675,7 +3843,8 @@ class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end test 'recognizes tilde path' do get "/~user" @@ -3702,7 +3871,8 @@ class TestRedirectInterpolation < ActionDispatch::IntegrationTest end end - def app; Routes end + APP = build_app Routes + def app; APP end test "redirect escapes interpolated parameters with redirect proc" do get "/foo/1%3E" @@ -3744,7 +3914,8 @@ class TestConstraintsAccessingParameters < ActionDispatch::IntegrationTest end end - def app; Routes end + APP = build_app Routes + def app; APP end test "parameters are reset between constraint checks" do get "/bar" @@ -3764,7 +3935,8 @@ class TestGlobRoutingMapper < ActionDispatch::IntegrationTest end #include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end def test_glob_constraint get "/dummy" @@ -3796,7 +3968,8 @@ class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end test 'enabled when not mounted and default_url_options is empty' do assert Routes.url_helpers.optimize_routes_generation? @@ -3868,7 +4041,8 @@ class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest end end - def app; Routes end + APP = build_app Routes + def app; APP end include Routes.url_helpers @@ -3903,7 +4077,8 @@ class TestUrlConstraints < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end test "constraints are copied to defaults when using constraints method" do assert_equal 'http://admin.example.com/', admin_root_url @@ -3957,7 +4132,7 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest 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 "/foo(/:action(/:id))", :controller => "test_invalid_urls/foo" get "/:controller(/:action(/:id))" end @@ -3984,8 +4159,9 @@ class TestOptionalRootSegments < ActionDispatch::IntegrationTest end end + APP = build_app Routes def app - Routes + APP end include Routes.url_helpers @@ -4016,7 +4192,8 @@ class TestPortConstraints < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end def test_integer_port_constraints get 'http://www.example.com/integer' @@ -4064,7 +4241,8 @@ class TestFormatConstraints < ActionDispatch::IntegrationTest end include Routes.url_helpers - def app; Routes end + APP = build_app Routes + def app; APP end def test_string_format_constraints get 'http://www.example.com/string' @@ -4111,6 +4289,19 @@ class TestFormatConstraints < ActionDispatch::IntegrationTest end end +class TestCallableConstraintValidation < ActionDispatch::IntegrationTest + def test_constraint_with_object_not_callable + assert_raises(ArgumentError) do + ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + get '/test', to: ok, constraints: Object.new + end + end + end + end +end + class TestRouteDefaults < ActionDispatch::IntegrationTest stub_controllers do |routes| Routes = routes @@ -4120,8 +4311,9 @@ class TestRouteDefaults < ActionDispatch::IntegrationTest end end + APP = build_app Routes def app - Routes + APP end include Routes.url_helpers @@ -4149,8 +4341,9 @@ class TestRackAppRouteGeneration < ActionDispatch::IntegrationTest end end + APP = build_app Routes def app - Routes + APP end include Routes.url_helpers @@ -4175,8 +4368,9 @@ class TestRedirectRouteGeneration < ActionDispatch::IntegrationTest end end + APP = build_app Routes def app - Routes + APP end include Routes.url_helpers @@ -4199,7 +4393,8 @@ class TestUrlGenerationErrors < ActionDispatch::IntegrationTest end end - def app; Routes end + APP = build_app Routes + def app; APP end include Routes.url_helpers diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index 92544230b2..f7a06cfed4 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -49,6 +49,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_equal 'foo: "bar"', response.body end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_getting_nil_session_value @@ -57,6 +59,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_equal 'foo: nil', response.body end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_getting_session_value_after_session_reset @@ -76,6 +80,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_equal 'foo: nil', response.body, "data for this session should have been obliterated from memcached" end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_getting_from_nonexistent_session @@ -85,6 +91,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_equal 'foo: nil', response.body assert_nil cookies['_session_id'], "should only create session on write, not read" end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_setting_session_value_after_session_reset @@ -106,6 +114,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_not_equal session_id, response.body end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_getting_session_id @@ -119,6 +129,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_equal session_id, response.body, "should be able to read session id without accessing the session hash" end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_deserializes_unloaded_class @@ -133,6 +145,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success end end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_doesnt_write_session_cookie_if_session_id_is_already_exists @@ -145,6 +159,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_equal nil, headers['Set-Cookie'], "should not resend the cookie again if session_id cookie is already exists" end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end def test_prevents_session_fixation @@ -160,6 +176,8 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_response :success assert_not_equal session_id, cookies['_session_id'] end + rescue Dalli::RingError => ex + skip ex.message, ex.backtrace end rescue LoadError, RuntimeError, Dalli::DalliError $stderr.puts "Skipping MemCacheStoreTest tests. Start memcached and try again." diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index 38bd234f37..323fbc285e 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -37,7 +37,7 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest get "/", {}, {'action_dispatch.show_exceptions' => true} assert_response 500 assert_equal "500 error fixture\n", body - + get "/bad_params", {}, {'action_dispatch.show_exceptions' => true} assert_response 400 assert_equal "400 error fixture\n", body @@ -92,6 +92,7 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest exceptions_app = lambda do |env| assert_kind_of AbstractController::ActionNotFound, env["action_dispatch.exception"] assert_equal "/404", env["PATH_INFO"] + assert_equal "/not_found_original_exception", env["action_dispatch.original_path"] [404, { "Content-Type" => "text/plain" }, ["YOU FAILED BRO"]] end diff --git a/actionpack/test/dispatch/template_assertions_test.rb b/actionpack/test/dispatch/template_assertions_test.rb new file mode 100644 index 0000000000..3c393f937b --- /dev/null +++ b/actionpack/test/dispatch/template_assertions_test.rb @@ -0,0 +1,98 @@ +require 'abstract_unit' + +class AssertTemplateController < ActionController::Base + def render_with_partial + render partial: 'test/partial' + end + + def render_with_template + render 'test/hello_world' + end + + def render_with_layout + @variable_for_layout = nil + render 'test/hello_world', layout: "layouts/standard" + end + + def render_with_file + render file: 'README.rdoc' + end + + def render_nothing + head :ok + end +end + +class AssertTemplateControllerTest < ActionDispatch::IntegrationTest + def test_template_reset_between_requests + get '/assert_template/render_with_template' + assert_template 'test/hello_world' + + get '/assert_template/render_nothing' + assert_template nil + end + + def test_partial_reset_between_requests + get '/assert_template/render_with_partial' + assert_template partial: 'test/_partial' + + get '/assert_template/render_nothing' + assert_template partial: nil + end + + def test_layout_reset_between_requests + get '/assert_template/render_with_layout' + assert_template layout: 'layouts/standard' + + get '/assert_template/render_nothing' + assert_template layout: nil + end + + def test_file_reset_between_requests + get '/assert_template/render_with_file' + assert_template file: 'README.rdoc' + + get '/assert_template/render_nothing' + assert_template file: nil + end + + def test_template_reset_between_requests_when_opening_a_session + open_session do |session| + session.get '/assert_template/render_with_template' + session.assert_template 'test/hello_world' + + session.get '/assert_template/render_nothing' + session.assert_template nil + end + end + + def test_partial_reset_between_requests_when_opening_a_session + open_session do |session| + session.get '/assert_template/render_with_partial' + session.assert_template partial: 'test/_partial' + + session.get '/assert_template/render_nothing' + session.assert_template partial: nil + end + end + + def test_layout_reset_between_requests_when_opening_a_session + open_session do |session| + session.get '/assert_template/render_with_layout' + session.assert_template layout: 'layouts/standard' + + session.get '/assert_template/render_nothing' + session.assert_template layout: nil + end + end + + def test_file_reset_between_requests_when_opening_a_session + open_session do |session| + session.get '/assert_template/render_with_file' + session.assert_template file: 'README.rdoc' + + session.get '/assert_template/render_nothing' + session.assert_template file: nil + end + end +end diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index 9f6381f118..55ebbd5143 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -18,6 +18,12 @@ module ActionDispatch assert_equal "UTF-8", uf.original_filename.encoding.to_s end + def test_filename_should_always_be_in_utf_8 + uf = Http::UploadedFile.new(:filename => 'foo'.encode(Encoding::SHIFT_JIS), + :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 diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index fdea27e2d2..8f79e7bf9a 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -15,15 +15,19 @@ module TestUrlGeneration Routes.draw do get "/foo", :to => "my_route_generating#index", :as => :foo + resources :bars + mount MyRouteGeneratingController.action(:index), at: '/bar' end + APP = build_app Routes + def _routes Routes end def app - Routes + APP end test "generating URLS normally" do @@ -64,18 +68,30 @@ module TestUrlGeneration test "port is extracted from the host" do assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com:8080", protocol: "http://") + assert_equal "//www.example.com:8080/foo", foo_url(host: "www.example.com:8080", protocol: "//") + assert_equal "//www.example.com:80/foo", foo_url(host: "www.example.com:80", protocol: "//") + end + + test "port option is used" do + assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com", protocol: "http://", port: 8080) + assert_equal "//www.example.com:8080/foo", foo_url(host: "www.example.com", protocol: "//", port: 8080) + assert_equal "//www.example.com:80/foo", foo_url(host: "www.example.com", protocol: "//", port: 80) end test "port option overrides the host" do assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: 8080) + assert_equal "//www.example.com:8080/foo", foo_url(host: "www.example.com:8443", protocol: "//", port: 8080) + assert_equal "//www.example.com:80/foo", foo_url(host: "www.example.com:443", protocol: "//", port: 80) end test "port option disables the host when set to nil" do assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: nil) + assert_equal "//www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "//", port: nil) end test "port option disables the host when set to false" do assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: false) + assert_equal "//www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "//", port: false) end test "keep subdomain when key is true" do @@ -97,6 +113,22 @@ module TestUrlGeneration test "omit subdomain when key is blank" do assert_equal "http://example.com/foo", foo_url(subdomain: "") end + + test "generating URLs with trailing slashes" do + assert_equal "/bars.json", bars_path( + trailing_slash: true, + format: 'json' + ) + end + + test "generating URLS with querystring and trailing slashes" do + assert_equal "/bars.json?a=b", bars_path( + trailing_slash: true, + a: 'b', + format: 'json' + ) + end + end end diff --git a/actionpack/test/fixtures/test/_changing_priority.html.erb b/actionpack/test/fixtures/test/_changing_priority.html.erb deleted file mode 100644 index 3225efc49a..0000000000 --- a/actionpack/test/fixtures/test/_changing_priority.html.erb +++ /dev/null @@ -1 +0,0 @@ -HTML
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_changing_priority.json.erb b/actionpack/test/fixtures/test/_changing_priority.json.erb deleted file mode 100644 index 7fa41dce66..0000000000 --- a/actionpack/test/fixtures/test/_changing_priority.json.erb +++ /dev/null @@ -1 +0,0 @@ -JSON
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_counter.html.erb b/actionpack/test/fixtures/test/_counter.html.erb deleted file mode 100644 index fd245bfc70..0000000000 --- a/actionpack/test/fixtures/test/_counter.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= counter_counter %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_customer.erb b/actionpack/test/fixtures/test/_customer.erb deleted file mode 100644 index d8220afeda..0000000000 --- a/actionpack/test/fixtures/test/_customer.erb +++ /dev/null @@ -1 +0,0 @@ -Hello: <%= customer.name rescue "Anonymous" %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_customer_counter.erb b/actionpack/test/fixtures/test/_customer_counter.erb deleted file mode 100644 index 3435979dba..0000000000 --- a/actionpack/test/fixtures/test/_customer_counter.erb +++ /dev/null @@ -1 +0,0 @@ -<%= customer_counter.name %><%= customer_counter_counter %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_customer_counter_with_as.erb b/actionpack/test/fixtures/test/_customer_counter_with_as.erb deleted file mode 100644 index 1241eb604d..0000000000 --- a/actionpack/test/fixtures/test/_customer_counter_with_as.erb +++ /dev/null @@ -1 +0,0 @@ -<%= client.name %><%= client_counter %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_customer_greeting.erb b/actionpack/test/fixtures/test/_customer_greeting.erb deleted file mode 100644 index 6acbcb20c4..0000000000 --- a/actionpack/test/fixtures/test/_customer_greeting.erb +++ /dev/null @@ -1 +0,0 @@ -<%= greeting %>: <%= customer_greeting.name %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_customer_with_var.erb b/actionpack/test/fixtures/test/_customer_with_var.erb deleted file mode 100644 index 00047dd20e..0000000000 --- a/actionpack/test/fixtures/test/_customer_with_var.erb +++ /dev/null @@ -1 +0,0 @@ -<%= customer.name %> <%= customer.name %> <%= customer.name %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb b/actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb deleted file mode 100644 index 1cc8d41475..0000000000 --- a/actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb +++ /dev/null @@ -1 +0,0 @@ -Hello <%= name %> diff --git a/actionpack/test/fixtures/test/_first_json_partial.json.erb b/actionpack/test/fixtures/test/_first_json_partial.json.erb deleted file mode 100644 index 790ee896db..0000000000 --- a/actionpack/test/fixtures/test/_first_json_partial.json.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render :partial => "test/second_json_partial" %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_form.erb b/actionpack/test/fixtures/test/_form.erb deleted file mode 100644 index 01107f1cb2..0000000000 --- a/actionpack/test/fixtures/test/_form.erb +++ /dev/null @@ -1 +0,0 @@ -<%= form.label :title %> diff --git a/actionpack/test/fixtures/test/_hash_greeting.erb b/actionpack/test/fixtures/test/_hash_greeting.erb deleted file mode 100644 index fc54a36f2a..0000000000 --- a/actionpack/test/fixtures/test/_hash_greeting.erb +++ /dev/null @@ -1 +0,0 @@ -<%= greeting %>: <%= hash_greeting[:first_name] %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_hash_object.erb b/actionpack/test/fixtures/test/_hash_object.erb deleted file mode 100644 index 34a92c6a56..0000000000 --- a/actionpack/test/fixtures/test/_hash_object.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= hash_object[:first_name] %> -<%= hash_object[:first_name].reverse %> diff --git a/actionpack/test/fixtures/test/_hello.builder b/actionpack/test/fixtures/test/_hello.builder deleted file mode 100644 index ef52f632d1..0000000000 --- a/actionpack/test/fixtures/test/_hello.builder +++ /dev/null @@ -1 +0,0 @@ -xm.hello
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_json_change_priority.json.erb b/actionpack/test/fixtures/test/_json_change_priority.json.erb deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/test/_json_change_priority.json.erb +++ /dev/null diff --git a/actionpack/test/fixtures/test/_labelling_form.erb b/actionpack/test/fixtures/test/_labelling_form.erb deleted file mode 100644 index 1b95763165..0000000000 --- a/actionpack/test/fixtures/test/_labelling_form.erb +++ /dev/null @@ -1 +0,0 @@ -<%= labelling_form.label :title %> diff --git a/actionpack/test/fixtures/test/_layout_for_partial.html.erb b/actionpack/test/fixtures/test/_layout_for_partial.html.erb deleted file mode 100644 index 666efadbb6..0000000000 --- a/actionpack/test/fixtures/test/_layout_for_partial.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -Before (<%= name %>) -<%= yield %> -After
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb b/actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb deleted file mode 100644 index 3a03a64e31..0000000000 --- a/actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb +++ /dev/null @@ -1 +0,0 @@ -Inside from partial (<%= name %>)
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_partial_html_erb.html.erb b/actionpack/test/fixtures/test/_partial_html_erb.html.erb deleted file mode 100644 index 4b54875782..0000000000 --- a/actionpack/test/fixtures/test/_partial_html_erb.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= "partial.html.erb" %> diff --git a/actionpack/test/fixtures/test/_partial_name_local_variable.erb b/actionpack/test/fixtures/test/_partial_name_local_variable.erb deleted file mode 100644 index cc3a91c89f..0000000000 --- a/actionpack/test/fixtures/test/_partial_name_local_variable.erb +++ /dev/null @@ -1 +0,0 @@ -<%= partial_name_local_variable %> diff --git a/actionpack/test/fixtures/test/_partial_only.erb b/actionpack/test/fixtures/test/_partial_only.erb deleted file mode 100644 index a44b3eed40..0000000000 --- a/actionpack/test/fixtures/test/_partial_only.erb +++ /dev/null @@ -1 +0,0 @@ -only partial
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_partial_only_html.html b/actionpack/test/fixtures/test/_partial_only_html.html deleted file mode 100644 index d2d630bd40..0000000000 --- a/actionpack/test/fixtures/test/_partial_only_html.html +++ /dev/null @@ -1 +0,0 @@ -only html partial
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_partial_with_partial.erb b/actionpack/test/fixtures/test/_partial_with_partial.erb deleted file mode 100644 index ee0d5037b6..0000000000 --- a/actionpack/test/fixtures/test/_partial_with_partial.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= render 'test/partial' %> -partial with partial diff --git a/actionpack/test/fixtures/test/_person.erb b/actionpack/test/fixtures/test/_person.erb deleted file mode 100644 index b2e5688956..0000000000 --- a/actionpack/test/fixtures/test/_person.erb +++ /dev/null @@ -1,2 +0,0 @@ -Second: <%= name %> -Third: <%= @name %> diff --git a/actionpack/test/fixtures/test/_raise_indentation.html.erb b/actionpack/test/fixtures/test/_raise_indentation.html.erb deleted file mode 100644 index f9a93728fe..0000000000 --- a/actionpack/test/fixtures/test/_raise_indentation.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -<p>First paragraph</p> -<p>Second paragraph</p> -<p>Third paragraph</p> -<p>Fourth paragraph</p> -<p>Fifth paragraph</p> -<p>Sixth paragraph</p> -<p>Seventh paragraph</p> -<p>Eight paragraph</p> -<p>Ninth paragraph</p> -<p>Tenth paragraph</p> -<%= raise "error here!" %> -<p>Eleventh paragraph</p> -<p>Twelfth paragraph</p>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_second_json_partial.json.erb b/actionpack/test/fixtures/test/_second_json_partial.json.erb deleted file mode 100644 index 5ebb7f1afd..0000000000 --- a/actionpack/test/fixtures/test/_second_json_partial.json.erb +++ /dev/null @@ -1 +0,0 @@ -Third level
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/action_talk_to_layout.erb b/actionpack/test/fixtures/test/action_talk_to_layout.erb deleted file mode 100644 index 36e896daa8..0000000000 --- a/actionpack/test/fixtures/test/action_talk_to_layout.erb +++ /dev/null @@ -1,2 +0,0 @@ -<% @title = "Talking to the layout" -%> -Action was here!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/calling_partial_with_layout.html.erb b/actionpack/test/fixtures/test/calling_partial_with_layout.html.erb deleted file mode 100644 index ac44bc0d81..0000000000 --- a/actionpack/test/fixtures/test/calling_partial_with_layout.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render(:layout => "layout_for_partial", :partial => "partial_for_use_in_layout", :locals => { :name => "David" }) %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/capturing.erb b/actionpack/test/fixtures/test/capturing.erb deleted file mode 100644 index 1addaa40d9..0000000000 --- a/actionpack/test/fixtures/test/capturing.erb +++ /dev/null @@ -1,4 +0,0 @@ -<% days = capture do %> - Dreamy days -<% end %> -<%= days %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/change_priority.html.erb b/actionpack/test/fixtures/test/change_priority.html.erb deleted file mode 100644 index 5618977d05..0000000000 --- a/actionpack/test/fixtures/test/change_priority.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= render :partial => "test/json_change_priority", formats: :json %> -HTML Template, but <%= render :partial => "test/changing_priority" %> partial
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/content_for.erb b/actionpack/test/fixtures/test/content_for.erb deleted file mode 100644 index 1fb829f54c..0000000000 --- a/actionpack/test/fixtures/test/content_for.erb +++ /dev/null @@ -1 +0,0 @@ -<% content_for :title do -%>Putting stuff in the title!<% end -%>Great stuff!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/content_for_concatenated.erb b/actionpack/test/fixtures/test/content_for_concatenated.erb deleted file mode 100644 index e65f629574..0000000000 --- a/actionpack/test/fixtures/test/content_for_concatenated.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% content_for :title, "Putting stuff " - content_for :title, "in the title!" -%> -Great stuff!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/content_for_with_parameter.erb b/actionpack/test/fixtures/test/content_for_with_parameter.erb deleted file mode 100644 index aeb6f73ce0..0000000000 --- a/actionpack/test/fixtures/test/content_for_with_parameter.erb +++ /dev/null @@ -1,2 +0,0 @@ -<% content_for :title, "Putting stuff in the title!" -%> -Great stuff!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/formatted_html_erb.html.erb b/actionpack/test/fixtures/test/formatted_html_erb.html.erb deleted file mode 100644 index 1c64efabd8..0000000000 --- a/actionpack/test/fixtures/test/formatted_html_erb.html.erb +++ /dev/null @@ -1 +0,0 @@ -formatted html erb
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/greeting.html.erb b/actionpack/test/fixtures/test/greeting.html.erb deleted file mode 100644 index 62fb0293f0..0000000000 --- a/actionpack/test/fixtures/test/greeting.html.erb +++ /dev/null @@ -1 +0,0 @@ -<p>This is grand!</p> diff --git a/actionpack/test/fixtures/test/greeting.xml.erb b/actionpack/test/fixtures/test/greeting.xml.erb deleted file mode 100644 index 62fb0293f0..0000000000 --- a/actionpack/test/fixtures/test/greeting.xml.erb +++ /dev/null @@ -1 +0,0 @@ -<p>This is grand!</p> diff --git a/actionpack/test/fixtures/test/hello,world.erb b/actionpack/test/fixtures/test/hello,world.erb deleted file mode 100644 index bc8fa5e0ca..0000000000 --- a/actionpack/test/fixtures/test/hello,world.erb +++ /dev/null @@ -1 +0,0 @@ -Hello w*rld!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hello.builder b/actionpack/test/fixtures/test/hello.builder deleted file mode 100644 index a471553941..0000000000 --- a/actionpack/test/fixtures/test/hello.builder +++ /dev/null @@ -1,4 +0,0 @@ -xml.html do - xml.p "Hello #{@name}" - xml << render(:file => "test/greeting") -end
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hello_world_container.builder b/actionpack/test/fixtures/test/hello_world_container.builder deleted file mode 100644 index e48d75c405..0000000000 --- a/actionpack/test/fixtures/test/hello_world_container.builder +++ /dev/null @@ -1,3 +0,0 @@ -xml.test do - render :partial => 'hello', :locals => { :xm => xml } -end
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hello_world_from_rxml.builder b/actionpack/test/fixtures/test/hello_world_from_rxml.builder deleted file mode 100644 index 619a97ba96..0000000000 --- a/actionpack/test/fixtures/test/hello_world_from_rxml.builder +++ /dev/null @@ -1,3 +0,0 @@ -xml.html do - xml.p "Hello" -end diff --git a/actionpack/test/fixtures/test/hello_world_with_layout_false.erb b/actionpack/test/fixtures/test/hello_world_with_layout_false.erb deleted file mode 100644 index 6769dd60bd..0000000000 --- a/actionpack/test/fixtures/test/hello_world_with_layout_false.erb +++ /dev/null @@ -1 +0,0 @@ -Hello world!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/html_template.html.erb b/actionpack/test/fixtures/test/html_template.html.erb deleted file mode 100644 index 1bbc2b7f09..0000000000 --- a/actionpack/test/fixtures/test/html_template.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render :partial => "test/first_json_partial", formats: :json %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hyphen-ated.erb b/actionpack/test/fixtures/test/hyphen-ated.erb deleted file mode 100644 index cd0875583a..0000000000 --- a/actionpack/test/fixtures/test/hyphen-ated.erb +++ /dev/null @@ -1 +0,0 @@ -Hello world! diff --git a/actionpack/test/fixtures/test/list.erb b/actionpack/test/fixtures/test/list.erb deleted file mode 100644 index 0a4bda58ee..0000000000 --- a/actionpack/test/fixtures/test/list.erb +++ /dev/null @@ -1 +0,0 @@ -<%= @test_unchanged = 'goodbye' %><%= render :partial => 'customer', :collection => @customers %><%= @test_unchanged %> diff --git a/actionpack/test/fixtures/test/non_erb_block_content_for.builder b/actionpack/test/fixtures/test/non_erb_block_content_for.builder deleted file mode 100644 index d539a425a4..0000000000 --- a/actionpack/test/fixtures/test/non_erb_block_content_for.builder +++ /dev/null @@ -1,4 +0,0 @@ -content_for :title do - 'Putting stuff in the title!' -end -xml << "Great stuff!" diff --git a/actionpack/test/fixtures/test/potential_conflicts.erb b/actionpack/test/fixtures/test/potential_conflicts.erb deleted file mode 100644 index a5e964e359..0000000000 --- a/actionpack/test/fixtures/test/potential_conflicts.erb +++ /dev/null @@ -1,4 +0,0 @@ -First: <%= @name %> -<%= render :partial => "person", :locals => { :name => "Stephan" } -%> -Fourth: <%= @name %> -Fifth: <%= name %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/proper_block_detection.erb b/actionpack/test/fixtures/test/proper_block_detection.erb deleted file mode 100644 index b55efbb25d..0000000000 --- a/actionpack/test/fixtures/test/proper_block_detection.erb +++ /dev/null @@ -1 +0,0 @@ -<%= @todo %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/render_file_from_template.html.erb b/actionpack/test/fixtures/test/render_file_from_template.html.erb deleted file mode 100644 index fde9f4bb64..0000000000 --- a/actionpack/test/fixtures/test/render_file_from_template.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render :file => @path %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/render_file_with_locals_and_default.erb b/actionpack/test/fixtures/test/render_file_with_locals_and_default.erb deleted file mode 100644 index 9b4900acc5..0000000000 --- a/actionpack/test/fixtures/test/render_file_with_locals_and_default.erb +++ /dev/null @@ -1 +0,0 @@ -<%= secret ||= 'one' %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb b/actionpack/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb deleted file mode 100644 index 0740b2d07c..0000000000 --- a/actionpack/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +++ /dev/null @@ -1 +0,0 @@ -Hey HTML! diff --git a/actionpack/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb b/actionpack/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb deleted file mode 100644 index 4a11845cfe..0000000000 --- a/actionpack/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +++ /dev/null @@ -1 +0,0 @@ -Hello HTML!
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/render_implicit_js_template_without_layout.js.erb b/actionpack/test/fixtures/test/render_implicit_js_template_without_layout.js.erb deleted file mode 100644 index 892ae5eca2..0000000000 --- a/actionpack/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +++ /dev/null @@ -1 +0,0 @@ -alert('hello');
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/render_partial_inside_directory.html.erb b/actionpack/test/fixtures/test/render_partial_inside_directory.html.erb deleted file mode 100644 index 1461b95186..0000000000 --- a/actionpack/test/fixtures/test/render_partial_inside_directory.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render partial: 'test/_directory/partial_with_locales', locals: {'name' => 'Jane'} %> diff --git a/actionpack/test/fixtures/test/render_to_string_test.erb b/actionpack/test/fixtures/test/render_to_string_test.erb deleted file mode 100644 index 6e267e8634..0000000000 --- a/actionpack/test/fixtures/test/render_to_string_test.erb +++ /dev/null @@ -1 +0,0 @@ -The value of foo is: ::<%= @foo %>:: diff --git a/actionpack/test/fixtures/test/render_two_partials.html.erb b/actionpack/test/fixtures/test/render_two_partials.html.erb deleted file mode 100644 index 3db6025860..0000000000 --- a/actionpack/test/fixtures/test/render_two_partials.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= render :partial => 'partial', :locals => {'first' => '1'} %> -<%= render :partial => 'partial', :locals => {'second' => '2'} %> diff --git a/actionpack/test/fixtures/test/using_layout_around_block.html.erb b/actionpack/test/fixtures/test/using_layout_around_block.html.erb deleted file mode 100644 index 3d6661df9a..0000000000 --- a/actionpack/test/fixtures/test/using_layout_around_block.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render(:layout => "layout_for_partial", :locals => { :name => "David" }) do %>Inside from block<% end %>
\ 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 deleted file mode 100644 index d84d909d64..0000000000 --- a/actionpack/test/fixtures/test/with_html_partial.html.erb +++ /dev/null @@ -1 +0,0 @@ -<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 deleted file mode 100644 index 7502364cf5..0000000000 --- a/actionpack/test/fixtures/test/with_partial.html.erb +++ /dev/null @@ -1 +0,0 @@ -<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 deleted file mode 100644 index 5f068ebf27..0000000000 --- a/actionpack/test/fixtures/test/with_partial.text.erb +++ /dev/null @@ -1 +0,0 @@ -**<%= 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 deleted file mode 100644 index e54a7cd001..0000000000 --- a/actionpack/test/fixtures/test/with_xml_template.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render :template => "test/greeting", :formats => :xml %> diff --git a/actionpack/test/journey/path/pattern_test.rb b/actionpack/test/journey/path/pattern_test.rb index ce02104181..9dfdfc23ed 100644 --- a/actionpack/test/journey/path/pattern_test.rb +++ b/actionpack/test/journey/path/pattern_test.rb @@ -18,7 +18,7 @@ module ActionDispatch '/:controller/*foo/bar' => %r{\A/(#{x})/(.+)/bar\Z}, }.each do |path, expected| define_method(:"test_to_regexp_#{path}") do - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( path, { :controller => /.+/ }, ["/", ".", "?"] @@ -41,7 +41,7 @@ module ActionDispatch '/:controller/*foo/bar' => %r{\A/(#{x})/(.+)/bar}, }.each do |path, expected| define_method(:"test_to_non_anchored_regexp_#{path}") do - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( path, { :controller => /.+/ }, ["/", ".", "?"], @@ -65,7 +65,7 @@ module ActionDispatch '/:controller/*foo/bar' => %w{ controller foo }, }.each do |path, expected| define_method(:"test_names_#{path}") do - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( path, { :controller => /.+/ }, ["/", ".", "?"] @@ -75,12 +75,8 @@ module ActionDispatch end end - def test_to_raise_exception_with_bad_expression - assert_raise(ArgumentError, "Bad expression: []") { Pattern.new [] } - end - def test_to_regexp_with_extended_group - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/:name', { :name => / #ROFL @@ -101,13 +97,13 @@ module ActionDispatch ['/:foo(/:bar)', %w{ bar }], ['/:foo(/:bar)/:lol(/:baz)', %w{ bar baz }], ].each do |pattern, list| - path = Pattern.new pattern + path = Pattern.from_string pattern assert_equal list.sort, path.optional_names.sort end end def test_to_regexp_match_non_optional - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/:name', { :name => /\d+/ }, ["/", ".", "?"] @@ -118,7 +114,7 @@ module ActionDispatch end def test_to_regexp_with_group - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/:name', { :name => /(tender|love)/ }, ["/", ".", "?"] @@ -131,7 +127,7 @@ module ActionDispatch def test_ast_sets_regular_expressions requirements = { :name => /(tender|love)/, :value => /./ } - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/:name/:value', requirements, ["/", ".", "?"] @@ -148,7 +144,7 @@ module ActionDispatch end def test_match_data_with_group - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/:name', { :name => /(tender|love)/ }, ["/", ".", "?"] @@ -160,7 +156,7 @@ module ActionDispatch end def test_match_data_with_multi_group - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/:name/:id', { :name => /t(((ender|love)))()/ }, ["/", ".", "?"] @@ -175,7 +171,7 @@ module ActionDispatch def test_star_with_custom_re z = /\d+/ - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/*foo', { :foo => z }, ["/", ".", "?"] @@ -185,7 +181,7 @@ module ActionDispatch end def test_insensitive_regexp_with_group - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( '/page/:name/aaron', { :name => /(tender|love)/i }, ["/", ".", "?"] @@ -197,7 +193,7 @@ module ActionDispatch end def test_to_regexp_with_strexp - strexp = Router::Strexp.new('/:controller', { }, ["/", ".", "?"]) + strexp = Router::Strexp.build('/:controller', { }, ["/", ".", "?"]) path = Pattern.new strexp x = %r{\A/([^/.?]+)\Z} @@ -205,20 +201,20 @@ module ActionDispatch end def test_to_regexp_defaults - path = Pattern.new '/:controller(/:action(/:id))' + path = Pattern.from_string '/:controller(/:action(/:id))' expected = %r{\A/([^/.?]+)(?:/([^/.?]+)(?:/([^/.?]+))?)?\Z} assert_equal expected, path.to_regexp end def test_failed_match - path = Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Pattern.from_string '/:controller(/:action(/:id(.:format)))' uri = 'content' assert_not path =~ uri end def test_match_controller - path = Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Pattern.from_string '/:controller(/:action(/:id(.:format)))' uri = '/content' match = path =~ uri @@ -230,7 +226,7 @@ module ActionDispatch end def test_match_controller_action - path = Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Pattern.from_string '/:controller(/:action(/:id(.:format)))' uri = '/content/list' match = path =~ uri @@ -242,7 +238,7 @@ module ActionDispatch end def test_match_controller_action_id - path = Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Pattern.from_string '/:controller(/:action(/:id(.:format)))' uri = '/content/list/10' match = path =~ uri @@ -254,7 +250,7 @@ module ActionDispatch end def test_match_literal - path = Path::Pattern.new "/books(/:action(.:format))" + path = Path::Pattern.from_string "/books(/:action(.:format))" uri = '/books' match = path =~ uri @@ -264,7 +260,7 @@ module ActionDispatch end def test_match_literal_with_action - path = Path::Pattern.new "/books(/:action(.:format))" + path = Path::Pattern.from_string "/books(/:action(.:format))" uri = '/books/list' match = path =~ uri @@ -274,7 +270,7 @@ module ActionDispatch end def test_match_literal_with_action_and_format - path = Path::Pattern.new "/books(/:action(.:format))" + path = Path::Pattern.from_string "/books(/:action(.:format))" uri = '/books/list.rss' match = path =~ uri diff --git a/actionpack/test/journey/route_test.rb b/actionpack/test/journey/route_test.rb index cbe6284714..21d867aca0 100644 --- a/actionpack/test/journey/route_test.rb +++ b/actionpack/test/journey/route_test.rb @@ -5,7 +5,7 @@ module ActionDispatch class TestRoute < ActiveSupport::TestCase def test_initialize app = Object.new - path = Path::Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Path::Pattern.from_string '/:controller(/:action(/:id(.:format)))' defaults = {} route = Route.new("name", app, path, {}, defaults) @@ -16,7 +16,7 @@ module ActionDispatch def test_route_adds_itself_as_memo app = Object.new - path = Path::Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Path::Pattern.from_string '/:controller(/:action(/:id(.:format)))' defaults = {} route = Route.new("name", app, path, {}, defaults) @@ -26,21 +26,21 @@ module ActionDispatch end def test_ip_address - path = Path::Pattern.new '/messages/:id(.:format)' + path = Path::Pattern.from_string '/messages/:id(.:format)' route = Route.new("name", nil, path, {:ip => '192.168.1.1'}, { :controller => 'foo', :action => 'bar' }) assert_equal '192.168.1.1', route.ip end def test_default_ip - path = Path::Pattern.new '/messages/:id(.:format)' + path = Path::Pattern.from_string '/messages/:id(.:format)' route = Route.new("name", nil, path, {}, { :controller => 'foo', :action => 'bar' }) assert_equal(//, route.ip) end def test_format_with_star - path = Path::Pattern.new '/:controller/*extra' + path = Path::Pattern.from_string '/:controller/*extra' route = Route.new("name", nil, path, {}, { :controller => 'foo', :action => 'bar' }) assert_equal '/foo/himom', route.format({ @@ -50,7 +50,7 @@ module ActionDispatch end def test_connects_all_match - path = Path::Pattern.new '/:controller(/:action(/:id(.:format)))' + path = Path::Pattern.from_string '/:controller(/:action(/:id(.:format)))' route = Route.new("name", nil, path, {:action => 'bar'}, { :controller => 'foo' }) assert_equal '/foo/bar/10', route.format({ @@ -61,21 +61,21 @@ module ActionDispatch end def test_extras_are_not_included_if_optional - path = Path::Pattern.new '/page/:id(/:action)' + path = Path::Pattern.from_string '/page/:id(/:action)' route = Route.new("name", nil, path, { }, { :action => 'show' }) assert_equal '/page/10', route.format({ :id => 10 }) end def test_extras_are_not_included_if_optional_with_parameter - path = Path::Pattern.new '(/sections/:section)/pages/:id' + path = Path::Pattern.from_string '(/sections/:section)/pages/:id' route = Route.new("name", nil, path, { }, { :action => 'show' }) assert_equal '/pages/10', route.format({:id => 10}) end def test_extras_are_not_included_if_optional_parameter_is_nil - path = Path::Pattern.new '(/sections/:section)/pages/:id' + path = Path::Pattern.from_string '(/sections/:section)/pages/:id' route = Route.new("name", nil, path, { }, { :action => 'show' }) assert_equal '/pages/10', route.format({:id => 10, :section => nil}) @@ -85,10 +85,10 @@ module ActionDispatch constraints = {:required_defaults => [:controller, :action]} defaults = {:controller=>"pages", :action=>"show"} - path = Path::Pattern.new "/page/:id(/:action)(.:format)" + path = Path::Pattern.from_string "/page/:id(/:action)(.:format)" specific = Route.new "name", nil, path, constraints, defaults - path = Path::Pattern.new "/:controller(/:action(/:id))(.:format)" + path = Path::Pattern.from_string "/:controller(/:action(/:id))(.:format)" generic = Route.new "name", nil, path, constraints knowledge = {:id=>20, :controller=>"pages", :action=>"show"} diff --git a/actionpack/test/journey/router/strexp_test.rb b/actionpack/test/journey/router/strexp_test.rb deleted file mode 100644 index 7ccdfb7b4d..0000000000 --- a/actionpack/test/journey/router/strexp_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'abstract_unit' - -module ActionDispatch - module Journey - class Router - class TestStrexp < ActiveSupport::TestCase - def test_many_names - exp = Strexp.new( - "/:controller(/:action(/:id(.:format)))", - {:controller=>/.+?/}, - ["/", ".", "?"], - true) - - assert_equal ["controller", "action", "id", "format"], exp.names - end - - def test_names - { - "/bar(.:format)" => %w{ format }, - ":format" => %w{ format }, - ":format-" => %w{ format }, - ":format0" => %w{ format0 }, - ":format1,:format2" => %w{ format1 format2 }, - }.each do |string, expected| - exp = Strexp.new(string, {}, ["/", ".", "?"]) - assert_equal expected, exp.names - end - end - end - end - end -end diff --git a/actionpack/test/journey/router/utils_test.rb b/actionpack/test/journey/router/utils_test.rb index 584fd56a5c..9b2b85ec73 100644 --- a/actionpack/test/journey/router/utils_test.rb +++ b/actionpack/test/journey/router/utils_test.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'abstract_unit' module ActionDispatch @@ -20,6 +21,10 @@ module ActionDispatch assert_equal "a/b c+d", Utils.unescape_uri("a%2Fb%20c+d") end + def test_uri_unescape_with_utf8_string + assert_equal "Šašinková", Utils.unescape_uri("%C5%A0a%C5%A1inkov%C3%A1".force_encoding(Encoding::US_ASCII)) + end + def test_normalize_path_not_greedy assert_equal "/foo%20bar%20baz", Utils.normalize_path("/foo%20bar%20baz") end diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb index e54b64e0f3..2e7e8e1bea 100644 --- a/actionpack/test/journey/router_test.rb +++ b/actionpack/test/journey/router_test.rb @@ -4,24 +4,15 @@ require 'abstract_unit' module ActionDispatch module Journey class TestRouter < ActiveSupport::TestCase - # TODO : clean up routing tests so we don't need this hack - class StubDispatcher < Routing::RouteSet::Dispatcher; end - attr_reader :routes def setup - @app = StubDispatcher.new + @app = Routing::RouteSet::Dispatcher.new({}) @routes = Routes.new - @router = Router.new(@routes, {}) + @router = Router.new(@routes) @formatter = Formatter.new(@routes) end - def test_request_class_reader - klass = Object.new - router = Router.new(routes, :request_class => klass) - assert_equal klass, router.request_class - end - class FakeRequestFeeler < Struct.new(:env, :called) def new env self.env = env @@ -39,33 +30,33 @@ module ActionDispatch end def test_dashes - router = Router.new(routes, {}) + router = Router.new(routes) - exp = Router::Strexp.new '/foo-bar-baz', {}, ['/.?'] + exp = Router::Strexp.build '/foo-bar-baz', {}, ['/.?'] path = Path::Pattern.new exp routes.add_route nil, path, {}, {:id => nil}, {} env = rails_env 'PATH_INFO' => '/foo-bar-baz' called = false - router.recognize(env) do |r, _, params| + router.recognize(env) do |r, params| called = true end assert called end def test_unicode - router = Router.new(routes, {}) + router = Router.new(routes) #match the escaped version of /ほげ - exp = Router::Strexp.new '/%E3%81%BB%E3%81%92', {}, ['/.?'] + exp = Router::Strexp.build '/%E3%81%BB%E3%81%92', {}, ['/.?'] path = Path::Pattern.new exp routes.add_route nil, path, {}, {:id => nil}, {} env = rails_env 'PATH_INFO' => '/%E3%81%BB%E3%81%92' called = false - router.recognize(env) do |r, _, params| + router.recognize(env) do |r, params| called = true end assert called @@ -73,17 +64,17 @@ module ActionDispatch def test_request_class_and_requirements_success klass = FakeRequestFeeler.new nil - router = Router.new(routes, {:request_class => klass }) + router = Router.new(routes) requirements = { :hello => /world/ } - exp = Router::Strexp.new '/foo(/:id)', {}, ['/.?'] + exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?'] path = Path::Pattern.new exp routes.add_route nil, path, requirements, {:id => nil}, {} - env = rails_env 'PATH_INFO' => '/foo/10' - router.recognize(env) do |r, _, params| + env = rails_env({'PATH_INFO' => '/foo/10'}, klass) + router.recognize(env) do |r, params| assert_equal({:id => '10'}, params) end @@ -93,17 +84,17 @@ module ActionDispatch def test_request_class_and_requirements_fail klass = FakeRequestFeeler.new nil - router = Router.new(routes, {:request_class => klass }) + router = Router.new(routes) requirements = { :hello => /mom/ } - exp = Router::Strexp.new '/foo(/:id)', {}, ['/.?'] + exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?'] path = Path::Pattern.new exp router.routes.add_route nil, path, requirements, {:id => nil}, {} - env = rails_env 'PATH_INFO' => '/foo/10' - router.recognize(env) do |r, _, params| + env = rails_env({'PATH_INFO' => '/foo/10'}, klass) + router.recognize(env) do |r, params| flunk 'route should not be found' end @@ -111,24 +102,29 @@ module ActionDispatch assert_equal env.env, klass.env end - class CustomPathRequest < Router::NullReq + class CustomPathRequest < ActionDispatch::Request def path_info env['custom.path_info'] end + + def path_info=(x) + env['custom.path_info'] = x + end end def test_request_class_overrides_path_info - router = Router.new(routes, {:request_class => CustomPathRequest }) + router = Router.new(routes) - exp = Router::Strexp.new '/bar', {}, ['/.?'] + exp = Router::Strexp.build '/bar', {}, ['/.?'] path = Path::Pattern.new exp routes.add_route nil, path, {}, {}, {} - env = rails_env 'PATH_INFO' => '/foo', 'custom.path_info' => '/bar' + env = rails_env({'PATH_INFO' => '/foo', + 'custom.path_info' => '/bar'}, CustomPathRequest) recognized = false - router.recognize(env) do |r, _, params| + router.recognize(env) do |r, params| recognized = true end @@ -137,14 +133,14 @@ module ActionDispatch def test_regexp_first_precedence add_routes @router, [ - Router::Strexp.new("/whois/:domain", {:domain => /\w+\.[\w\.]+/}, ['/', '.', '?']), - Router::Strexp.new("/whois/:id(.:format)", {}, ['/', '.', '?']) + Router::Strexp.build("/whois/:domain", {:domain => /\w+\.[\w\.]+/}, ['/', '.', '?']), + Router::Strexp.build("/whois/:id(.:format)", {}, ['/', '.', '?']) ] env = rails_env 'PATH_INFO' => '/whois/example.com' list = [] - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| list << r end assert_equal 2, list.length @@ -156,50 +152,50 @@ module ActionDispatch def test_required_parts_verified_are_anchored add_routes @router, [ - Router::Strexp.new("/foo/:id", { :id => /\d/ }, ['/', '.', '?'], false) + Router::Strexp.build("/foo/:id", { :id => /\d/ }, ['/', '.', '?'], false) ] assert_raises(ActionController::UrlGenerationError) do - @formatter.generate(:path_info, nil, { :id => '10' }, { }) + @formatter.generate(nil, { :id => '10' }, { }) end end def test_required_parts_are_verified_when_building add_routes @router, [ - Router::Strexp.new("/foo/:id", { :id => /\d+/ }, ['/', '.', '?'], false) + Router::Strexp.build("/foo/:id", { :id => /\d+/ }, ['/', '.', '?'], false) ] - path, _ = @formatter.generate(:path_info, nil, { :id => '10' }, { }) + path, _ = @formatter.generate(nil, { :id => '10' }, { }) assert_equal '/foo/10', path assert_raises(ActionController::UrlGenerationError) do - @formatter.generate(:path_info, nil, { :id => 'aa' }, { }) + @formatter.generate(nil, { :id => 'aa' }, { }) end end def test_only_required_parts_are_verified add_routes @router, [ - Router::Strexp.new("/foo(/:id)", {:id => /\d/}, ['/', '.', '?'], false) + Router::Strexp.build("/foo(/:id)", {:id => /\d/}, ['/', '.', '?'], false) ] - path, _ = @formatter.generate(:path_info, nil, { :id => '10' }, { }) + path, _ = @formatter.generate(nil, { :id => '10' }, { }) assert_equal '/foo/10', path - path, _ = @formatter.generate(:path_info, nil, { }, { }) + path, _ = @formatter.generate(nil, { }, { }) assert_equal '/foo', path - path, _ = @formatter.generate(:path_info, nil, { :id => 'aa' }, { }) + path, _ = @formatter.generate(nil, { :id => 'aa' }, { }) assert_equal '/foo/aa', path end def test_knows_what_parts_are_missing_from_named_route route_name = "gorby_thunderhorse" - pattern = Router::Strexp.new("/foo/:id", { :id => /\d+/ }, ['/', '.', '?'], false) + pattern = Router::Strexp.build("/foo/:id", { :id => /\d+/ }, ['/', '.', '?'], false) path = Path::Pattern.new pattern @router.routes.add_route nil, path, {}, {}, route_name error = assert_raises(ActionController::UrlGenerationError) do - @formatter.generate(:path_info, route_name, { }, { }) + @formatter.generate(route_name, { }, { }) end assert_match(/missing required keys: \[:id\]/, error.message) @@ -207,42 +203,43 @@ module ActionDispatch def test_X_Cascade add_routes @router, [ "/messages(.:format)" ] - resp = @router.call({ 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/lol' }) + resp = @router.serve(rails_env({ 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/lol' })) assert_equal ['Not Found'], resp.last assert_equal 'pass', resp[1]['X-Cascade'] assert_equal 404, resp.first end def test_clear_trailing_slash_from_script_name_on_root_unanchored_routes - strexp = Router::Strexp.new("/", {}, ['/', '.', '?'], false) - path = Path::Pattern.new strexp + route_set = Routing::RouteSet.new + mapper = Routing::Mapper.new route_set + app = lambda { |env| [200, {}, ['success!']] } - @router.routes.add_route(app, path, {}, {}, {}) + mapper.get '/weblog', :to => app env = rack_env('SCRIPT_NAME' => '', 'PATH_INFO' => '/weblog') - resp = @router.call(env) + resp = route_set.call env assert_equal ['success!'], resp.last assert_equal '', env['SCRIPT_NAME'] end def test_defaults_merge_correctly - path = Path::Pattern.new '/foo(/:id)' + path = Path::Pattern.from_string '/foo(/:id)' @router.routes.add_route nil, path, {}, {:id => nil}, {} env = rails_env 'PATH_INFO' => '/foo/10' - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal({:id => '10'}, params) end env = rails_env 'PATH_INFO' => '/foo' - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal({:id => nil}, params) end end def test_recognize_with_unbound_regexp add_routes @router, [ - Router::Strexp.new("/foo", { }, ['/', '.', '?'], false) + Router::Strexp.build("/foo", { }, ['/', '.', '?'], false) ] env = rails_env 'PATH_INFO' => '/foo/bar' @@ -255,7 +252,7 @@ module ActionDispatch def test_bound_regexp_keeps_path_info add_routes @router, [ - Router::Strexp.new("/foo", { }, ['/', '.', '?'], true) + Router::Strexp.build("/foo", { }, ['/', '.', '?'], true) ] env = rails_env 'PATH_INFO' => '/foo' @@ -287,14 +284,14 @@ module ActionDispatch def test_required_part_in_recall add_routes @router, [ "/messages/:a/:b" ] - path, _ = @formatter.generate(:path_info, nil, { :a => 'a' }, { :b => 'b' }) + path, _ = @formatter.generate(nil, { :a => 'a' }, { :b => 'b' }) assert_equal "/messages/a/b", path end def test_splat_in_recall add_routes @router, [ "/*path" ] - path, _ = @formatter.generate(:path_info, nil, { }, { :path => 'b' }) + path, _ = @formatter.generate(nil, { }, { :path => 'b' }) assert_equal "/b", path end @@ -304,35 +301,35 @@ module ActionDispatch "/messages/:id(.:format)" ] - path, _ = @formatter.generate(:path_info, nil, { :id => 10 }, { :action => 'index' }) + path, _ = @formatter.generate(nil, { :id => 10 }, { :action => 'index' }) assert_equal "/messages/index/10", path end def test_nil_path_parts_are_ignored - path = Path::Pattern.new "/:controller(/:action(.:format))" + path = Path::Pattern.from_string "/:controller(/:action(.:format))" @router.routes.add_route @app, path, {}, {}, {} params = { :controller => "tasks", :format => nil } extras = { :action => 'lol' } - path, _ = @formatter.generate(:path_info, nil, params, extras) + path, _ = @formatter.generate(nil, params, extras) assert_equal '/tasks', path end def test_generate_slash params = [ [:controller, "tasks"], [:action, "show"] ] - str = Router::Strexp.new("/", Hash[params], ['/', '.', '?'], true) + str = Router::Strexp.build("/", Hash[params], ['/', '.', '?'], true) path = Path::Pattern.new str @router.routes.add_route @app, path, {}, {}, {} - path, _ = @formatter.generate(:path_info, nil, Hash[params], {}) + path, _ = @formatter.generate(nil, Hash[params], {}) assert_equal '/', path end def test_generate_calls_param_proc - path = Path::Pattern.new '/:controller(/:action)' + path = Path::Pattern.from_string '/:controller(/:action)' @router.routes.add_route @app, path, {}, {}, {} parameterized = [] @@ -340,7 +337,6 @@ module ActionDispatch [:action, "show"] ] @formatter.generate( - :path_info, nil, Hash[params], {}, @@ -350,31 +346,31 @@ module ActionDispatch end def test_generate_id - path = Path::Pattern.new '/:controller(/:action)' + path = Path::Pattern.from_string '/:controller(/:action)' @router.routes.add_route @app, path, {}, {}, {} path, params = @formatter.generate( - :path_info, nil, {:id=>1, :controller=>"tasks", :action=>"show"}, {}) + nil, {:id=>1, :controller=>"tasks", :action=>"show"}, {}) assert_equal '/tasks/show', path assert_equal({:id => 1}, params) end def test_generate_escapes - path = Path::Pattern.new '/:controller(/:action)' + path = Path::Pattern.from_string '/:controller(/:action)' @router.routes.add_route @app, path, {}, {}, {} - path, _ = @formatter.generate(:path_info, - nil, { :controller => "tasks", + path, _ = @formatter.generate(nil, + { :controller => "tasks", :action => "a/b c+d", }, {}) assert_equal '/tasks/a%2Fb%20c+d', path end def test_generate_escapes_with_namespaced_controller - path = Path::Pattern.new '/:controller(/:action)' + path = Path::Pattern.from_string '/:controller(/:action)' @router.routes.add_route @app, path, {}, {}, {} - path, _ = @formatter.generate(:path_info, + path, _ = @formatter.generate( nil, { :controller => "admin/tasks", :action => "a/b c+d", }, {}) @@ -382,10 +378,10 @@ module ActionDispatch end def test_generate_extra_params - path = Path::Pattern.new '/:controller(/:action)' + path = Path::Pattern.from_string '/:controller(/:action)' @router.routes.add_route @app, path, {}, {}, {} - path, params = @formatter.generate(:path_info, + path, params = @formatter.generate( nil, { :id => 1, :controller => "tasks", :action => "show", @@ -396,10 +392,10 @@ module ActionDispatch end def test_generate_uses_recall_if_needed - path = Path::Pattern.new '/:controller(/:action(/:id))' + path = Path::Pattern.from_string '/:controller(/:action(/:id))' @router.routes.add_route @app, path, {}, {}, {} - path, params = @formatter.generate(:path_info, + path, params = @formatter.generate( nil, {:controller =>"tasks", :id => 10}, {:action =>"index"}) @@ -408,10 +404,10 @@ module ActionDispatch end def test_generate_with_name - path = Path::Pattern.new '/:controller(/:action)' + path = Path::Pattern.from_string '/:controller(/:action)' @router.routes.add_route @app, path, {}, {}, {} - path, params = @formatter.generate(:path_info, + path, params = @formatter.generate( "tasks", {:controller=>"tasks"}, {:controller=>"tasks", :action=>"index"}) @@ -425,14 +421,14 @@ module ActionDispatch '/content/show/10' => { :controller => 'content', :action => 'show', :id => "10" }, }.each do |request_path, expected| define_method("test_recognize_#{expected.keys.map(&:to_s).join('_')}") do - path = Path::Pattern.new "/:controller(/:action(/:id))" + path = Path::Pattern.from_string "/:controller(/:action(/:id))" app = Object.new route = @router.routes.add_route(app, path, {}, {}, {}) env = rails_env 'PATH_INFO' => request_path called = false - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal route, r assert_equal(expected, params) called = true @@ -447,14 +443,14 @@ module ActionDispatch :splat => ['/segment/a/b%20c+d', { :segment => 'segment', :splat => 'a/b c+d' }] }.each do |name, (request_path, expected)| define_method("test_recognize_#{name}") do - path = Path::Pattern.new '/:segment/*splat' + path = Path::Pattern.from_string '/:segment/*splat' app = Object.new route = @router.routes.add_route(app, path, {}, {}, {}) env = rails_env 'PATH_INFO' => request_path called = false - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal route, r assert_equal(expected, params) called = true @@ -465,7 +461,7 @@ module ActionDispatch end def test_namespaced_controller - strexp = Router::Strexp.new( + strexp = Router::Strexp.build( "/:controller(/:action(/:id))", { :controller => /.+?/ }, ["/", ".", "?"] @@ -482,7 +478,7 @@ module ActionDispatch :id => '10' } - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal route, r assert_equal(expected, params) called = true @@ -491,14 +487,14 @@ module ActionDispatch end def test_recognize_literal - path = Path::Pattern.new "/books(/:action(.:format))" + path = Path::Pattern.from_string "/books(/:action(.:format))" app = Object.new route = @router.routes.add_route(app, path, {}, {:controller => 'books'}) env = rails_env 'PATH_INFO' => '/books/list.rss' expected = { :controller => 'books', :action => 'list', :format => 'rss' } called = false - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal route, r assert_equal(expected, params) called = true @@ -508,7 +504,7 @@ module ActionDispatch end def test_recognize_head_request_as_get_route - path = Path::Pattern.new "/books(/:action(.:format))" + path = Path::Pattern.from_string "/books(/:action(.:format))" app = Object.new conditions = { :request_method => 'GET' @@ -519,7 +515,7 @@ module ActionDispatch "REQUEST_METHOD" => "HEAD" called = false - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| called = true end @@ -527,7 +523,7 @@ module ActionDispatch end def test_recognize_cares_about_verbs - path = Path::Pattern.new "/books(/:action(.:format))" + path = Path::Pattern.from_string "/books(/:action(.:format))" app = Object.new conditions = { :request_method => 'GET' @@ -543,7 +539,7 @@ module ActionDispatch "REQUEST_METHOD" => "POST" called = false - @router.recognize(env) do |r, _, params| + @router.recognize(env) do |r, params| assert_equal post, r called = true end @@ -555,15 +551,17 @@ module ActionDispatch def add_routes router, paths paths.each do |path| - path = Path::Pattern.new path + if String === path + path = Path::Pattern.from_string path + else + path = Path::Pattern.new path + end router.routes.add_route @app, path, {}, {}, {} end end - RailsEnv = Struct.new(:env) - - def rails_env env - RailsEnv.new rack_env env + def rails_env env, klass = ActionDispatch::Request + klass.new env end def rack_env env diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb index 25e0321d31..a4efc82b8c 100644 --- a/actionpack/test/journey/routes_test.rb +++ b/actionpack/test/journey/routes_test.rb @@ -5,7 +5,7 @@ module ActionDispatch class TestRoutes < ActiveSupport::TestCase def test_clear routes = Routes.new - exp = Router::Strexp.new '/foo(/:id)', {}, ['/.?'] + exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?'] path = Path::Pattern.new exp requirements = { :hello => /world/ } @@ -18,7 +18,7 @@ module ActionDispatch def test_ast routes = Routes.new - path = Path::Pattern.new '/hello' + path = Path::Pattern.from_string '/hello' routes.add_route nil, path, {}, {}, {} ast = routes.ast @@ -28,7 +28,7 @@ module ActionDispatch def test_simulator_changes routes = Routes.new - path = Path::Pattern.new '/hello' + path = Path::Pattern.from_string '/hello' routes.add_route nil, path, {}, {}, {} sim = routes.simulator @@ -40,8 +40,8 @@ module ActionDispatch #def add_route app, path, conditions, defaults, name = nil routes = Routes.new - one = Path::Pattern.new '/hello' - two = Path::Pattern.new '/aaron' + one = Path::Pattern.from_string '/hello' + two = Path::Pattern.from_string '/aaron' routes.add_route nil, one, {}, {}, 'aaron' routes.add_route nil, two, {}, {}, 'aaron' |