diff options
Diffstat (limited to 'actionpack/test/controller')
69 files changed, 2867 insertions, 1659 deletions
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index f2a4503f13..899d92f815 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -5,9 +5,6 @@ class ActionPackAssertionsController < ActionController::Base def nothing() head :ok end - def hello_world() render :template => "test/hello_world"; end - def hello_repeating_in_path() render :template => "test/hello/hello"; end - def hello_xml_world() render :template => "test/hello_xml_world"; end def hello_xml_world_pdf @@ -20,8 +17,6 @@ class ActionPackAssertionsController < ActionController::Base render :template => "test/hello_xml_world" end - def partial() render :partial => 'test/partial'; end - def redirect_internal() redirect_to "/nothing"; end def redirect_to_action() redirect_to :action => "flash_me", :id => 1, :params => { "panda" => "fun" }; end @@ -48,12 +43,12 @@ class ActionPackAssertionsController < ActionController::Base def flash_me flash['hello'] = 'my name is inigo montoya...' - render :text => "Inconceivable!" + render plain: "Inconceivable!" end def flash_me_naked flash.clear - render :text => "wow!" + render plain: "wow!" end def assign_this @@ -62,40 +57,30 @@ class ActionPackAssertionsController < ActionController::Base end def render_based_on_parameters - render :text => "Mr. #{params[:name]}" + render plain: "Mr. #{params[:name]}" end def render_url - render :text => "<div>#{url_for(:action => 'flash_me', :only_path => true)}</div>" + render html: "<div>#{url_for(action: 'flash_me', only_path: true)}</div>" end def render_text_with_custom_content_type - render :text => "Hello!", :content_type => Mime::RSS - end - - def render_with_layout - @variable_for_layout = nil - render "test/hello_world", :layout => "layouts/standard" - end - - def render_with_layout_and_partial - @variable_for_layout = nil - render "test/hello_world_with_partial", :layout => "layouts/standard" + render body: "Hello!", content_type: Mime[:rss] end def session_stuffing session['xmas'] = 'turkey' - render :text => "ho ho ho" + render plain: "ho ho ho" end def raise_exception_on_get raise "get" if request.get? - render :text => "request method: #{request.env['REQUEST_METHOD']}" + render plain: "request method: #{request.env['REQUEST_METHOD']}" end def raise_exception_on_post raise "post" if request.post? - render :text => "request method: #{request.env['REQUEST_METHOD']}" + render plain: "request method: #{request.env['REQUEST_METHOD']}" end def render_file_absolute_path @@ -116,14 +101,14 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base end def show - render :text => "Boom", :status => 500 + render plain: "Boom", status: 500 end end module Admin class InnerModuleController < ActionController::Base def index - render :nothing => true + head :ok end def redirect_to_index @@ -304,14 +289,6 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase assert session.empty? end - def test_render_template_action - process :nothing - assert_template nil - - process :hello_world - assert_template 'hello_world' - end - def test_redirection_location process :redirect_internal assert_equal 'http://test.host/nothing', @response.redirect_url @@ -341,7 +318,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_missing_response_code process :response404 - assert @response.missing? + assert @response.not_found? end def test_client_error_response_code @@ -369,16 +346,18 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_successful_response_code process :nothing - assert @response.success? + assert @response.successful? end def test_response_object process :nothing - assert_kind_of ActionController::TestResponse, @response + assert_kind_of ActionDispatch::TestResponse, @response end def test_render_based_on_parameters - process :render_based_on_parameters, "GET", "name" => "David" + process :render_based_on_parameters, + method: "GET", + params: { name: "David" } assert_equal "Mr. David", @response.body end @@ -453,185 +432,6 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase end end -class AssertTemplateTest < ActionController::TestCase - tests ActionPackAssertionsController - - def test_with_invalid_hash_keys_raises_argument_error - assert_raise(ArgumentError) do - assert_template foo: "bar" - end - end - - def test_with_partial - get :partial - assert_template :partial => '_partial' - end - - def test_file_with_absolute_path_success - get :render_file_absolute_path - assert_template :file => File.expand_path('../../../README.rdoc', __FILE__) - end - - def test_file_with_relative_path_success - get :render_file_relative_path - assert_template :file => 'README.rdoc' - end - - def test_with_file_failure - get :render_file_absolute_path - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template :file => 'test/hello_world' - end - - get :render_file_absolute_path - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template file: nil - end - end - - def test_with_nil_passes_when_no_template_rendered - get :nothing - assert_template nil - end - - def test_with_nil_fails_when_template_rendered - get :hello_world - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template nil - end - end - - def test_with_empty_string_fails_when_template_rendered - get :hello_world - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template "" - end - end - - def test_with_empty_string_fails_when_no_template_rendered - get :nothing - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template "" - end - end - - def test_passes_with_correct_string - get :hello_world - assert_template 'hello_world' - assert_template 'test/hello_world' - end - - def test_passes_with_correct_symbol - get :hello_world - assert_template :hello_world - end - - def test_fails_with_incorrect_string - get :hello_world - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template 'hello_planet' - end - end - - def test_fails_with_incorrect_string_that_matches - get :hello_world - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template 'est/he' - end - end - - def test_fails_with_repeated_name_in_path - get :hello_repeating_in_path - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template 'test/hello' - end - end - - def test_fails_with_incorrect_symbol - get :hello_world - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template :hello_planet - end - end - - def test_fails_with_incorrect_symbol_that_matches - get :hello_world - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template :"est/he" - end - end - - def test_fails_with_wrong_layout - get :render_with_layout - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template :layout => "application" - end - end - - def test_fails_expecting_no_layout - get :render_with_layout - assert_raise(ActiveSupport::TestCase::Assertion) do - assert_template :layout => nil - end - end - - def test_passes_with_correct_layout - get :render_with_layout - assert_template :layout => "layouts/standard" - end - - def test_passes_with_layout_and_partial - get :render_with_layout_and_partial - assert_template :layout => "layouts/standard" - end - - def test_passed_with_no_layout - get :hello_world - assert_template :layout => nil - end - - def test_passed_with_no_layout_false - get :hello_world - assert_template :layout => false - end - - def test_passes_with_correct_layout_without_layouts_prefix - get :render_with_layout - assert_template :layout => "standard" - end - - def test_passes_with_correct_layout_symbol - get :render_with_layout - assert_template :layout => :standard - end - - def test_assert_template_reset_between_requests - get :hello_world - assert_template 'test/hello_world' - - get :nothing - assert_template nil - - get :partial - assert_template partial: 'test/_partial' - - get :nothing - assert_template partial: nil - - get :render_with_layout - assert_template layout: 'layouts/standard' - - get :nothing - assert_template layout: nil - - get :render_file_relative_path - assert_template file: 'README.rdoc' - - get :nothing - assert_template file: nil - end -end - class ActionPackHeaderTest < ActionController::TestCase tests ActionPackAssertionsController diff --git a/actionpack/test/controller/api/conditional_get_test.rb b/actionpack/test/controller/api/conditional_get_test.rb new file mode 100644 index 0000000000..b4f1673be0 --- /dev/null +++ b/actionpack/test/controller/api/conditional_get_test.rb @@ -0,0 +1,57 @@ +require 'abstract_unit' +require 'active_support/core_ext/integer/time' +require 'active_support/core_ext/numeric/time' + +class ConditionalGetApiController < ActionController::API + before_action :handle_last_modified_and_etags, only: :two + + def one + if stale?(last_modified: Time.now.utc.beginning_of_day, etag: [:foo, 123]) + render plain: "Hi!" + end + end + + def two + render plain: "Hi!" + end + + private + + def handle_last_modified_and_etags + fresh_when(last_modified: Time.now.utc.beginning_of_day, etag: [ :foo, 123 ]) + end +end + +class ConditionalGetApiTest < ActionController::TestCase + tests ConditionalGetApiController + + def setup + @last_modified = Time.now.utc.beginning_of_day.httpdate + end + + def test_request_gets_last_modified + get :two + assert_equal @last_modified, @response.headers['Last-Modified'] + assert_response :success + end + + def test_request_obeys_last_modified + @request.if_modified_since = @last_modified + get :two + assert_response :not_modified + end + + def test_last_modified_works_with_less_than_too + @request.if_modified_since = 5.years.ago.httpdate + get :two + assert_response :success + end + + def test_request_not_modified + @request.if_modified_since = @last_modified + get :one + assert_equal 304, @response.status.to_i + assert @response.body.blank? + assert_equal @last_modified, @response.headers['Last-Modified'] + end +end diff --git a/actionpack/test/controller/api/data_streaming_test.rb b/actionpack/test/controller/api/data_streaming_test.rb new file mode 100644 index 0000000000..0e7d97d1f4 --- /dev/null +++ b/actionpack/test/controller/api/data_streaming_test.rb @@ -0,0 +1,26 @@ +require 'abstract_unit' + +module TestApiFileUtils + def file_path() File.expand_path(__FILE__) end + def file_data() @data ||= File.open(file_path, 'rb') { |f| f.read } end +end + +class DataStreamingApiController < ActionController::API + include TestApiFileUtils + + def one; end + def two + send_data(file_data, {}) + end +end + +class DataStreamingApiTest < ActionController::TestCase + include TestApiFileUtils + tests DataStreamingApiController + + def test_data + response = process('two') + assert_kind_of String, response.body + assert_equal file_data, response.body + end +end diff --git a/actionpack/test/controller/api/force_ssl_test.rb b/actionpack/test/controller/api/force_ssl_test.rb new file mode 100644 index 0000000000..8578340d82 --- /dev/null +++ b/actionpack/test/controller/api/force_ssl_test.rb @@ -0,0 +1,20 @@ +require 'abstract_unit' + +class ForceSSLApiController < ActionController::API + force_ssl + + def one; end + def two + head :ok + end +end + +class ForceSSLApiTest < ActionController::TestCase + tests ForceSSLApiController + + def test_redirects_to_https + get :two + assert_response 301 + assert_equal "https://test.host/force_ssl_api/two", redirect_to_url + end +end diff --git a/actionpack/test/controller/api/implicit_render_test.rb b/actionpack/test/controller/api/implicit_render_test.rb new file mode 100644 index 0000000000..26f9cd8f78 --- /dev/null +++ b/actionpack/test/controller/api/implicit_render_test.rb @@ -0,0 +1,15 @@ +require 'abstract_unit' + +class ImplicitRenderAPITestController < ActionController::API + def empty_action + end +end + +class ImplicitRenderAPITest < ActionController::TestCase + tests ImplicitRenderAPITestController + + def test_implicit_no_content_response + get :empty_action + assert_response :no_content + end +end diff --git a/actionpack/test/controller/api/params_wrapper_test.rb b/actionpack/test/controller/api/params_wrapper_test.rb new file mode 100644 index 0000000000..53b3a0c3cc --- /dev/null +++ b/actionpack/test/controller/api/params_wrapper_test.rb @@ -0,0 +1,26 @@ +require 'abstract_unit' + +class ParamsWrapperForApiTest < ActionController::TestCase + class UsersController < ActionController::API + attr_accessor :last_parameters + + wrap_parameters :person, format: [:json] + + def test + self.last_parameters = params.except(:controller, :action).to_unsafe_h + head :ok + end + end + + class Person; end + + tests UsersController + + def test_specify_wrapper_name + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, params: { 'username' => 'sikachu' } + + expected = { 'username' => 'sikachu', 'person' => { 'username' => 'sikachu' }} + assert_equal expected, @controller.last_parameters + end +end diff --git a/actionpack/test/controller/api/redirect_to_test.rb b/actionpack/test/controller/api/redirect_to_test.rb new file mode 100644 index 0000000000..18877c4b3a --- /dev/null +++ b/actionpack/test/controller/api/redirect_to_test.rb @@ -0,0 +1,19 @@ +require 'abstract_unit' + +class RedirectToApiController < ActionController::API + def one + redirect_to action: "two" + end + + def two; end +end + +class RedirectToApiTest < ActionController::TestCase + tests RedirectToApiController + + def test_redirect_to + get :one + assert_response :redirect + assert_equal "http://test.host/redirect_to_api/two", redirect_to_url + end +end diff --git a/actionpack/test/controller/api/renderers_test.rb b/actionpack/test/controller/api/renderers_test.rb new file mode 100644 index 0000000000..9405538833 --- /dev/null +++ b/actionpack/test/controller/api/renderers_test.rb @@ -0,0 +1,38 @@ +require 'abstract_unit' +require 'active_support/core_ext/hash/conversions' + +class RenderersApiController < ActionController::API + class Model + def to_json(options = {}) + { a: 'b' }.to_json(options) + end + + def to_xml(options = {}) + { a: 'b' }.to_xml(options) + end + end + + def one + render json: Model.new + end + + def two + render xml: Model.new + end +end + +class RenderersApiTest < ActionController::TestCase + tests RenderersApiController + + def test_render_json + get :one + assert_response :success + assert_equal({ a: 'b' }.to_json, @response.body) + end + + def test_render_xml + get :two + assert_response :success + assert_equal({ a: 'b' }.to_xml, @response.body) + end +end diff --git a/actionpack/test/controller/api/url_for_test.rb b/actionpack/test/controller/api/url_for_test.rb new file mode 100644 index 0000000000..0d8691a091 --- /dev/null +++ b/actionpack/test/controller/api/url_for_test.rb @@ -0,0 +1,20 @@ +require 'abstract_unit' + +class UrlForApiController < ActionController::API + def one; end + def two; end +end + +class UrlForApiTest < ActionController::TestCase + tests UrlForApiController + + def setup + super + @request.host = 'www.example.com' + end + + def test_url_for + get :one + assert_equal "http://www.example.com/url_for_api/one", @controller.url_for + end +end diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index 950788743e..fb60dbd993 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -1,31 +1,11 @@ require 'abstract_unit' require 'active_support/logger' require 'controller/fake_models' -require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late # Provide some controller to run the tests on. module Submodule class ContainedEmptyController < ActionController::Base end - - class ContainedNonEmptyController < ActionController::Base - def public_action - render :nothing => true - end - - hide_action :hidden_action - def hidden_action - raise "Noooo!" - end - - def another_hidden_action - end - hide_action :another_hidden_action - end - - class SubclassedController < ContainedNonEmptyController - hide_action :public_action # Hiding it here should not affect the superclass. - end end class EmptyController < ActionController::Base @@ -33,11 +13,7 @@ end class NonEmptyController < ActionController::Base def public_action - render :nothing => true - end - - hide_action :hidden_action - def hidden_action + head :ok end end @@ -51,6 +27,16 @@ class DefaultUrlOptionsController < ActionController::Base end end +class OptionalDefaultUrlOptionsController < ActionController::Base + def show + head :ok + end + + def default_url_options + { format: 'atom', id: 'default-id' } + end +end + class UrlOptionsController < ActionController::Base def from_view render :inline => "<%= #{params[:route]} %>" @@ -67,7 +53,7 @@ end class ActionMissingController < ActionController::Base def action_missing(action) - render :text => "Response for #{action}" + render plain: "Response for #{action}" end end @@ -107,11 +93,10 @@ end class ControllerInstanceTests < ActiveSupport::TestCase def setup @empty = EmptyController.new + @empty.set_request!(ActionDispatch::Request.new({})) + @empty.set_response!(EmptyController.make_response!(@empty.request)) @contained = Submodule::ContainedEmptyController.new - @empty_controllers = [@empty, @contained, Submodule::SubclassedController.new] - - @non_empty_controllers = [NonEmptyController.new, - Submodule::ContainedNonEmptyController.new] + @empty_controllers = [@empty, @contained] end def test_performed? @@ -124,10 +109,6 @@ class ControllerInstanceTests < ActiveSupport::TestCase @empty_controllers.each do |c| assert_equal Set.new, c.class.action_methods, "#{c.controller_path} should be empty!" end - - @non_empty_controllers.each do |c| - assert_equal Set.new(%w(public_action)), c.class.action_methods, "#{c.controller_path} should not be empty!" - end end def test_temporary_anonymous_controllers @@ -148,8 +129,6 @@ class PerformActionTest < ActionController::TestCase # a more accurate simulation of what happens in "real life". @controller.logger = ActiveSupport::Logger.new(nil) - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new @request.host = "www.nextangle.com" end @@ -161,12 +140,6 @@ class PerformActionTest < ActionController::TestCase assert_equal "The action 'non_existent' could not be found for EmptyController", exception.message end - def test_get_on_hidden_should_fail - use_controller NonEmptyController - assert_raise(AbstractController::ActionNotFound) { get :hidden_action } - assert_raise(AbstractController::ActionNotFound) { get :another_hidden_action } - end - def test_action_missing_should_work use_controller ActionMissingController get :arbitrary_action @@ -205,7 +178,7 @@ class UrlOptionsTest < ActionController::TestCase get ':controller/:action' end - get :from_view, :route => "from_view_url" + get :from_view, params: { route: "from_view_url" } assert_equal 'http://www.override.com/from_view', @response.body assert_equal 'http://www.override.com/from_view', @controller.send(:from_view_url) @@ -239,7 +212,7 @@ class DefaultUrlOptionsTest < ActionController::TestCase get ':controller/:action' end - get :from_view, :route => "from_view_url" + get :from_view, params: { route: "from_view_url" } assert_equal 'http://www.override.com/from_view?locale=en', @response.body assert_equal 'http://www.override.com/from_view?locale=en', @controller.send(:from_view_url) @@ -256,7 +229,7 @@ class DefaultUrlOptionsTest < ActionController::TestCase get ':controller/:action' end - get :from_view, :route => "description_path(1)" + get :from_view, params: { route: "description_path(1)" } assert_equal '/en/descriptions/1', @response.body assert_equal '/en/descriptions', @controller.send(:descriptions_path) @@ -271,7 +244,18 @@ class DefaultUrlOptionsTest < ActionController::TestCase assert_equal '/en/descriptions/1.xml', @controller.send(:description_path, 1, :format => "xml") end end +end +class OptionalDefaultUrlOptionsControllerTest < ActionController::TestCase + def test_default_url_options_override_missing_positional_arguments + with_routing do |set| + set.draw do + get "/things/:id(.:format)" => 'things#show', :as => :thing + end + assert_equal '/things/1.atom', thing_path('1') + assert_equal '/things/default-id.atom', thing_path + end + end end class EmptyUrlOptionsTest < ActionController::TestCase diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index c0e6a2ebd1..bc0ffd3eaa 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -1,5 +1,6 @@ require 'fileutils' require 'abstract_unit' +require 'lib/controller/fake_models' CACHE_DIR = 'test_cache' # Don't change '/../temp/' cavalierly or you might hose something you don't want hosed @@ -21,8 +22,6 @@ class FragmentCachingMetalTest < ActionController::TestCase @controller.perform_caching = true @controller.cache_store = @store @params = { controller: 'posts', action: 'index' } - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new @controller.params = @params @controller.request = @request @controller.response = @response @@ -51,8 +50,6 @@ class FragmentCachingTest < ActionController::TestCase @controller.perform_caching = true @controller.cache_store = @store @params = {:controller => 'posts', :action => 'index'} - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new @controller.params = @params @controller.request = @request @controller.response = @response @@ -165,6 +162,8 @@ class FunctionalCachingController < CachingController end def formatted_fragment_cached_with_variant + request.variant = :phone if params[:v] == "phone" + respond_to do |format| format.html.phone format.html @@ -182,8 +181,6 @@ class FunctionalFragmentCachingTest < ActionController::TestCase @controller = FunctionalCachingController.new @controller.perform_caching = true @controller.cache_store = @store - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new end def test_fragment_caching @@ -210,7 +207,7 @@ CACHED end def test_skipping_fragment_cache_digesting - get :fragment_cached_without_digest, :format => "html" + get :fragment_cached_without_digest, format: "html" assert_response :success expected_body = "<body>\n<p>ERB</p>\n</body>\n" @@ -244,7 +241,7 @@ CACHED end def test_html_formatted_fragment_caching - get :formatted_fragment_cached, :format => "html" + get :formatted_fragment_cached, format: "html" assert_response :success expected_body = "<body>\n<p>ERB</p>\n</body>\n" @@ -255,7 +252,7 @@ CACHED end def test_xml_formatted_fragment_caching - get :formatted_fragment_cached, :format => "xml" + get :formatted_fragment_cached, format: "xml" assert_response :success expected_body = "<body>\n <p>Builder</p>\n</body>\n" @@ -267,9 +264,7 @@ CACHED def test_fragment_caching_with_variant - @request.variant = :phone - - get :formatted_fragment_cached_with_variant, :format => "html" + get :formatted_fragment_cached_with_variant, format: "html", params: { v: :phone } assert_response :success expected_body = "<body>\n<p>PHONE</p>\n</body>\n" @@ -304,30 +299,42 @@ class CacheHelperOutputBufferTest < ActionController::TestCase def test_output_buffer output_buffer = ActionView::OutputBuffer.new controller = MockController.new - cache_helper = Object.new + cache_helper = Class.new do + def self.controller; end; + def self.output_buffer; end; + def self.output_buffer=; end; + end cache_helper.extend(ActionView::Helpers::CacheHelper) - cache_helper.expects(:controller).returns(controller).at_least(0) - cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0) - # if the output_buffer is changed, the new one should be html_safe and of the same type - cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0) - assert_nothing_raised do - cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + cache_helper.stub :controller, controller do + cache_helper.stub :output_buffer, output_buffer do + assert_called_with cache_helper, :output_buffer=, [output_buffer.class.new(output_buffer)] do + assert_nothing_raised do + cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + end + end + end end end def test_safe_buffer output_buffer = ActiveSupport::SafeBuffer.new controller = MockController.new - cache_helper = Object.new + cache_helper = Class.new do + def self.controller; end; + def self.output_buffer; end; + def self.output_buffer=; end; + end cache_helper.extend(ActionView::Helpers::CacheHelper) - cache_helper.expects(:controller).returns(controller).at_least(0) - cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0) - # if the output_buffer is changed, the new one should be html_safe and of the same type - cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0) - assert_nothing_raised do - cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + cache_helper.stub :controller, controller do + cache_helper.stub :output_buffer, output_buffer do + assert_called_with cache_helper, :output_buffer=, [output_buffer.class.new(output_buffer)] do + assert_nothing_raised do + cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + end + end + end end end end @@ -349,3 +356,66 @@ class ViewCacheDependencyTest < ActionController::TestCase assert_equal %w(trombone flute), HasDependenciesController.new.view_cache_dependencies end end + +class CollectionCacheController < ActionController::Base + attr_accessor :partial_rendered_times + + def index + @customers = [Customer.new('david', params[:id] || 1)] + end + + def index_ordered + @customers = [Customer.new('david', 1), Customer.new('david', 2), Customer.new('david', 3)] + render 'index' + end + + def index_explicit_render + @customers = [Customer.new('david', 1)] + render partial: 'customers/customer', collection: @customers + end + + def index_with_comment + @customers = [Customer.new('david', 1)] + render partial: 'customers/commented_customer', collection: @customers, as: :customer + end +end + +class AutomaticCollectionCacheTest < ActionController::TestCase + def setup + super + @controller = CollectionCacheController.new + @controller.perform_caching = true + @controller.partial_rendered_times = 0 + @controller.cache_store = ActiveSupport::Cache::MemoryStore.new + ActionView::PartialRenderer.collection_cache = @controller.cache_store + end + + def test_collection_fetches_cached_views + get :index + assert_equal 1, @controller.partial_rendered_times + + get :index + assert_equal 1, @controller.partial_rendered_times + end + + def test_preserves_order_when_reading_from_cache_plus_rendering + get :index, params: { id: 2 } + get :index_ordered + + assert_select ':root', "david, 1\n david, 2\n david, 3" + end + + def test_explicit_render_call_with_options + get :index_explicit_render + + assert_select ':root', "david, 1" + end + + def test_caching_works_with_beginning_comment + get :index_with_comment + assert_equal 1, @controller.partial_rendered_times + + get :index_with_comment + assert_equal 1, @controller.partial_rendered_times + end +end diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index 89667df3a4..c02607b55e 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -3,30 +3,30 @@ require 'abstract_unit' class OldContentTypeController < ActionController::Base # :ported: def render_content_type_from_body - response.content_type = Mime::RSS - render :text => "hello world!" + response.content_type = Mime[:rss] + render body: "hello world!" end # :ported: def render_defaults - render :text => "hello world!" + render body: "hello world!" end # :ported: def render_content_type_from_render - render :text => "hello world!", :content_type => Mime::RSS + render body: "hello world!", :content_type => Mime[:rss] end # :ported: def render_charset_from_body response.charset = "utf-16" - render :text => "hello world!" + render body: "hello world!" end # :ported: def render_nil_charset_from_body response.charset = nil - render :text => "hello world!" + render body: "hello world!" end def render_default_for_erb @@ -36,16 +36,16 @@ class OldContentTypeController < ActionController::Base end def render_change_for_builder - response.content_type = Mime::HTML + response.content_type = Mime[:html] render :action => "render_default_for_builder" end def render_default_content_types_for_respond_to respond_to do |format| - format.html { render :text => "hello world!" } - format.xml { render :action => "render_default_content_types_for_respond_to" } - format.js { render :text => "hello world!" } - format.rss { render :text => "hello world!", :content_type => Mime::XML } + format.html { render body: "hello world!" } + format.xml { render action: "render_default_content_types_for_respond_to" } + format.js { render body: "hello world!" } + format.rss { render body: "hello world!", content_type: Mime[:xml] } end end end @@ -64,68 +64,68 @@ class ContentTypeTest < ActionController::TestCase def test_render_defaults get :render_defaults assert_equal "utf-8", @response.charset - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:text], @response.content_type end def test_render_changed_charset_default with_default_charset "utf-16" do get :render_defaults assert_equal "utf-16", @response.charset - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:text], @response.content_type end end # :ported: def test_content_type_from_body get :render_content_type_from_body - assert_equal Mime::RSS, @response.content_type + assert_equal Mime[:rss], @response.content_type assert_equal "utf-8", @response.charset end # :ported: def test_content_type_from_render get :render_content_type_from_render - assert_equal Mime::RSS, @response.content_type + assert_equal Mime[:rss], @response.content_type assert_equal "utf-8", @response.charset end # :ported: def test_charset_from_body get :render_charset_from_body - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:text], @response.content_type assert_equal "utf-16", @response.charset end # :ported: def test_nil_charset_from_body get :render_nil_charset_from_body - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:text], @response.content_type assert_equal "utf-8", @response.charset, @response.headers.inspect end def test_nil_default_for_erb with_default_charset nil do get :render_default_for_erb - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:html], @response.content_type assert_nil @response.charset, @response.headers.inspect end end def test_default_for_erb get :render_default_for_erb - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:html], @response.content_type assert_equal "utf-8", @response.charset end def test_default_for_builder get :render_default_for_builder - assert_equal Mime::XML, @response.content_type + assert_equal Mime[:xml], @response.content_type assert_equal "utf-8", @response.charset end def test_change_for_builder get :render_change_for_builder - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:html], @response.content_type assert_equal "utf-8", @response.charset end @@ -144,24 +144,24 @@ class AcceptBasedContentTypeTest < ActionController::TestCase tests OldContentTypeController def test_render_default_content_types_for_respond_to - @request.accept = Mime::HTML.to_s + @request.accept = Mime[:html].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::HTML, @response.content_type + assert_equal Mime[:html], @response.content_type - @request.accept = Mime::JS.to_s + @request.accept = Mime[:js].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::JS, @response.content_type + assert_equal Mime[:js], @response.content_type end def test_render_default_content_types_for_respond_to_with_template - @request.accept = Mime::XML.to_s + @request.accept = Mime[:xml].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::XML, @response.content_type + assert_equal Mime[:xml], @response.content_type end def test_render_default_content_types_for_respond_to_with_overwrite - @request.accept = Mime::RSS.to_s + @request.accept = Mime[:rss].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::XML, @response.content_type + assert_equal Mime[:xml], @response.content_type end end diff --git a/actionpack/test/controller/default_url_options_with_before_action_test.rb b/actionpack/test/controller/default_url_options_with_before_action_test.rb index 656fd0431e..12fbe0424e 100644 --- a/actionpack/test/controller/default_url_options_with_before_action_test.rb +++ b/actionpack/test/controller/default_url_options_with_before_action_test.rb @@ -1,13 +1,12 @@ require 'abstract_unit' - class ControllerWithBeforeActionAndDefaultUrlOptions < ActionController::Base before_action { I18n.locale = params[:locale] } after_action { I18n.locale = "en" } def target - render :text => "final response" + render plain: "final response" end def redirect @@ -23,7 +22,7 @@ class ControllerWithBeforeActionAndDefaultUrlOptionsTest < ActionController::Tes # This test has its roots in issue #1872 test "should redirect with correct locale :de" do - get :redirect, :locale => "de" + get :redirect, params: { locale: "de" } assert_redirected_to "/controller_with_before_action_and_default_url_options/target?locale=de" end end diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index b2b01b3fa9..08271012e9 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -10,23 +10,12 @@ class ActionController::Base def before_actions filters = _process_action_callbacks.select { |c| c.kind == :before } - filters.map! { |c| c.raw_filter } + filters.map!(&:raw_filter) end end - - def assigns(key = nil) - assigns = {} - instance_variables.each do |ivar| - next if ActionController::Base.protected_instance_variables.include?(ivar) - assigns[ivar[1..-1]] = instance_variable_get(ivar) - end - - key.nil? ? assigns : assigns[key.to_s] - end end class FilterTest < ActionController::TestCase - class TestController < ActionController::Base before_action :ensure_login after_action :clean_up @@ -51,7 +40,7 @@ class FilterTest < ActionController::TestCase before_action :ensure_login, :except => [:go_wild] def go_wild - render :text => "gobble" + render plain: "gobble" end end @@ -62,7 +51,7 @@ class FilterTest < ActionController::TestCase (1..3).each do |i| define_method "fail_#{i}" do - render :text => i.to_s + render plain: i.to_s end end @@ -225,6 +214,30 @@ class FilterTest < ActionController::TestCase skip_before_action :clean_up_tmp, if: -> { true } end + class SkipFilterUsingOnlyAndIf < ConditionalFilterController + before_action :clean_up_tmp + before_action :ensure_login + + skip_before_action :ensure_login, only: :login, if: -> { false } + skip_before_action :clean_up_tmp, only: :login, if: -> { true } + + def login + render plain: 'ok' + end + end + + class SkipFilterUsingIfAndExcept < ConditionalFilterController + before_action :clean_up_tmp + before_action :ensure_login + + skip_before_action :ensure_login, if: -> { false }, except: :login + skip_before_action :clean_up_tmp, if: -> { true }, except: :login + + def login + render plain: 'ok' + end + end + class ClassController < ConditionalFilterController before_action ConditionalClassFilter end @@ -245,11 +258,11 @@ class FilterTest < ActionController::TestCase before_action :ensure_login, :only => :index def index - render :text => 'ok' + render plain: 'ok' end def public - render :text => 'ok' + render plain: 'ok' end end @@ -259,7 +272,7 @@ class FilterTest < ActionController::TestCase before_action :ensure_login def index - render :text => 'ok' + render plain: 'ok' end private @@ -370,7 +383,7 @@ class FilterTest < ActionController::TestCase before_action(AuditFilter) def show - render :text => "hello" + render plain: "hello" end end @@ -408,11 +421,11 @@ class FilterTest < ActionController::TestCase before_action :second, :only => :foo def foo - render :text => 'foo' + render plain: 'foo' end def bar - render :text => 'bar' + render plain: 'bar' end protected @@ -429,7 +442,7 @@ class FilterTest < ActionController::TestCase before_action :choose %w(foo bar baz).each do |action| - define_method(action) { render :text => action } + define_method(action) { render plain: action } end private @@ -458,7 +471,7 @@ class FilterTest < ActionController::TestCase @ran_filter << 'between_before_all_and_after_all' end def show - render :text => 'hello' + render plain: 'hello' end end @@ -468,7 +481,7 @@ class FilterTest < ActionController::TestCase def around(controller) yield rescue ErrorToRescue => ex - controller.__send__ :render, :text => "I rescued this: #{ex.inspect}" + controller.__send__ :render, plain: "I rescued this: #{ex.inspect}" end end @@ -504,7 +517,6 @@ class FilterTest < ActionController::TestCase def non_yielding_action @filters << "it didn't yield" - @filter_return_value end def action_three @@ -528,34 +540,17 @@ class FilterTest < ActionController::TestCase end end - 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 - test_process(controller, "index") - end - end - - def test_non_yielding_around_actions_returning_false_do_not_raise + def test_non_yielding_around_actions_do_not_raise controller = NonYieldingAroundFilterController.new - controller.instance_variable_set "@filter_return_value", false assert_nothing_raised do test_process(controller, "index") end end - def test_after_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_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'] + assert_equal ["filter_one", "it didn't yield"], controller.instance_variable_get(:@filters) end def test_added_action_to_inheritance_graph @@ -572,130 +567,141 @@ class FilterTest < ActionController::TestCase def test_running_actions test_process(PrependingController) - assert_equal %w( wonderful_life ensure_login ), assigns["ran_filter"] + assert_equal %w( wonderful_life ensure_login ), + @controller.instance_variable_get(:@ran_filter) end def test_running_actions_with_proc test_process(ProcController) - assert assigns["ran_proc_action"] + assert @controller.instance_variable_get(:@ran_proc_action) end def test_running_actions_with_implicit_proc test_process(ImplicitProcController) - assert assigns["ran_proc_action"] + assert @controller.instance_variable_get(:@ran_proc_action) end def test_running_actions_with_class test_process(AuditController) - assert assigns["was_audited"] + assert @controller.instance_variable_get(:@was_audited) end def test_running_anomolous_yet_valid_condition_actions test_process(AnomolousYetValidConditionController) - assert_equal %w( ensure_login ), assigns["ran_filter"] - assert assigns["ran_class_action"] - assert assigns["ran_proc_action1"] - assert assigns["ran_proc_action2"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) + assert @controller.instance_variable_get(:@ran_class_action) + assert @controller.instance_variable_get(:@ran_proc_action1) + assert @controller.instance_variable_get(:@ran_proc_action2) test_process(AnomolousYetValidConditionController, "show_without_action") - assert_nil assigns["ran_filter"] - assert !assigns["ran_class_action"] - assert !assigns["ran_proc_action1"] - assert !assigns["ran_proc_action2"] + assert_not @controller.instance_variable_defined?(:@ran_filter) + assert_not @controller.instance_variable_defined?(:@ran_class_action) + assert_not @controller.instance_variable_defined?(:@ran_proc_action1) + assert_not @controller.instance_variable_defined?(:@ran_proc_action2) end def test_running_conditional_options test_process(ConditionalOptionsFilter) - assert_equal %w( ensure_login ), assigns["ran_filter"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) end def test_running_conditional_skip_options test_process(ConditionalOptionsSkipFilter) - assert_equal %w( ensure_login ), assigns["ran_filter"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) + end + + def test_if_is_ignored_when_used_with_only + test_process(SkipFilterUsingOnlyAndIf, 'login') + assert_not @controller.instance_variable_defined?(:@ran_filter) + end + + def test_except_is_ignored_when_used_with_if + test_process(SkipFilterUsingIfAndExcept, 'login') + assert_equal %w(ensure_login), @controller.instance_variable_get(:@ran_filter) end def test_skipping_class_actions test_process(ClassController) - assert_equal true, assigns["ran_class_action"] + assert_equal true, @controller.instance_variable_get(:@ran_class_action) skipping_class_controller = Class.new(ClassController) do skip_before_action ConditionalClassFilter end test_process(skipping_class_controller) - assert_nil assigns['ran_class_action'] + assert_not @controller.instance_variable_defined?(:@ran_class_action) end def test_running_collection_condition_actions test_process(ConditionalCollectionFilterController) - assert_equal %w( ensure_login ), assigns["ran_filter"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) test_process(ConditionalCollectionFilterController, "show_without_action") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) test_process(ConditionalCollectionFilterController, "another_action") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) end def test_running_only_condition_actions test_process(OnlyConditionSymController) - assert_equal %w( ensure_login ), assigns["ran_filter"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) test_process(OnlyConditionSymController, "show_without_action") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) test_process(OnlyConditionProcController) - assert assigns["ran_proc_action"] + assert @controller.instance_variable_get(:@ran_proc_action) test_process(OnlyConditionProcController, "show_without_action") - assert !assigns["ran_proc_action"] + assert_not @controller.instance_variable_defined?(:@ran_proc_action) test_process(OnlyConditionClassController) - assert assigns["ran_class_action"] + assert @controller.instance_variable_get(:@ran_class_action) test_process(OnlyConditionClassController, "show_without_action") - assert !assigns["ran_class_action"] + assert_not @controller.instance_variable_defined?(:@ran_class_action) end def test_running_except_condition_actions test_process(ExceptConditionSymController) - assert_equal %w( ensure_login ), assigns["ran_filter"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) test_process(ExceptConditionSymController, "show_without_action") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) test_process(ExceptConditionProcController) - assert assigns["ran_proc_action"] + assert @controller.instance_variable_get(:@ran_proc_action) test_process(ExceptConditionProcController, "show_without_action") - assert !assigns["ran_proc_action"] + assert_not @controller.instance_variable_defined?(:@ran_proc_action) test_process(ExceptConditionClassController) - assert assigns["ran_class_action"] + assert @controller.instance_variable_get(:@ran_class_action) test_process(ExceptConditionClassController, "show_without_action") - assert !assigns["ran_class_action"] + assert_not @controller.instance_variable_defined?(:@ran_class_action) end def test_running_only_condition_and_conditional_options test_process(OnlyConditionalOptionsFilter, "show") - assert_not assigns["ran_conditional_index_proc"] + assert_not @controller.instance_variable_defined?(:@ran_conditional_index_proc) end def test_running_before_and_after_condition_actions test_process(BeforeAndAfterConditionController) - assert_equal %w( ensure_login clean_up_tmp), assigns["ran_filter"] + assert_equal %w( ensure_login clean_up_tmp), @controller.instance_variable_get(:@ran_filter) test_process(BeforeAndAfterConditionController, "show_without_action") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) end def test_around_action test_process(AroundFilterController) - assert assigns["before_ran"] - assert assigns["after_ran"] + assert @controller.instance_variable_get(:@before_ran) + assert @controller.instance_variable_get(:@after_ran) end def test_before_after_class_action test_process(BeforeAfterClassFilterController) - assert assigns["before_ran"] - assert assigns["after_ran"] + assert @controller.instance_variable_get(:@before_ran) + assert @controller.instance_variable_get(:@after_ran) end def test_having_properties_in_around_action test_process(AroundFilterController) - assert_equal "before and after", assigns["execution_log"] + assert_equal "before and after", @controller.instance_variable_get(:@execution_log) end def test_prepending_and_appending_around_action @@ -708,33 +714,33 @@ class FilterTest < ActionController::TestCase def test_rendering_breaks_actioning_chain response = test_process(RenderingController) assert_equal "something else", response.body - assert !assigns["ran_action"] + assert_not @controller.instance_variable_defined?(:@ran_action) end def test_before_action_rendering_breaks_actioning_chain_for_after_action test_process(RenderingController) - assert_equal %w( before_action_rendering ), assigns["ran_filter"] - assert !assigns["ran_action"] + assert_equal %w( before_action_rendering ), @controller.instance_variable_get(:@ran_filter) + assert_not @controller.instance_variable_defined?(:@ran_action) end 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_action_redirection/target_of_redirection", redirect_to_url - assert_equal %w( before_action_redirects ), assigns["ran_filter"] + assert_equal %w( before_action_redirects ), @controller.instance_variable_get(:@ran_filter) end 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"] + assert_equal %w( before_action_rendering ), @controller.instance_variable_get(:@ran_filter) + assert_not @controller.instance_variable_defined?(:@ran_action) end 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_action_redirection_for_prepend_after_action/target_of_redirection", redirect_to_url - assert_equal %w( before_action_redirects ), assigns["ran_filter"] + assert_equal %w( before_action_redirects ), @controller.instance_variable_get(:@ran_filter) end def test_actions_with_mixed_specialization_run_in_order @@ -751,35 +757,34 @@ class FilterTest < ActionController::TestCase def test_dynamic_dispatch %w(foo bar baz).each do |action| - request = ActionController::TestRequest.new - request.query_parameters[:choose] = action - response = DynamicDispatchController.action(action).call(request.env).last + @request.query_parameters[:choose] = action + response = DynamicDispatchController.action(action).call(@request.env).last assert_equal action, response.body end end 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"] + assert_equal %w( before_all between_before_all_and_after_all after_all ), @controller.instance_variable_get(:@ran_filter) end def test_skipping_and_limiting_controller test_process(SkippingAndLimitedController, "index") - assert_equal %w( ensure_login ), assigns["ran_filter"] + assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter) test_process(SkippingAndLimitedController, "public") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) end def test_skipping_and_reordering_controller test_process(SkippingAndReorderingController, "index") - assert_equal %w( find_record ensure_login ), assigns["ran_filter"] + assert_equal %w( find_record ensure_login ), @controller.instance_variable_get(:@ran_filter) end def test_conditional_skipping_of_actions test_process(ConditionalSkippingController, "login") - assert_nil assigns["ran_filter"] + assert_not @controller.instance_variable_defined?(:@ran_filter) test_process(ConditionalSkippingController, "change_password") - assert_equal %w( ensure_login find_user ), assigns["ran_filter"] + assert_equal %w( ensure_login find_user ), @controller.instance_variable_get(:@ran_filter) test_process(ConditionalSkippingController, "login") assert !@controller.instance_variable_defined?("@ran_after_action") @@ -789,23 +794,23 @@ class FilterTest < ActionController::TestCase 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'] + assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter) test_process(ChildOfConditionalParentController, 'another_action') - assert_nil assigns['ran_filter'] + assert_not @controller.instance_variable_defined?(:@ran_filter) end 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'] + assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter) test_process(AnotherChildOfConditionalParentController) - assert_equal %w( conditional_in_parent_after ), assigns['ran_filter'] + assert_equal %w( conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter) test_process(ChildOfConditionalParentController) - assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), assigns['ran_filter'] + assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter) end def test_changing_the_requirements test_process(ChangingTheRequirementsController, "go_wild") - assert_nil assigns['ran_filter'] + assert_not @controller.instance_variable_defined?(:@ran_filter) end def test_a_rescuing_around_action @@ -814,27 +819,25 @@ class FilterTest < ActionController::TestCase response = test_process(RescuedController) end - assert response.success? + assert response.successful? assert_equal("I rescued this: #<FilterTest::ErrorToRescue: Something made the bad noise.>", response.body) end def test_actions_obey_only_and_except_for_implicit_actions test_process(ImplicitActionsController, 'show') - assert_equal 'Except', assigns(:except) - assert_nil assigns(:only) + assert_equal 'Except', @controller.instance_variable_get(:@except) + assert_not @controller.instance_variable_defined?(:@only) assert_equal 'show', response.body test_process(ImplicitActionsController, 'edit') - assert_equal 'Only', assigns(:only) - assert_nil assigns(:except) + assert_equal 'Only', @controller.instance_variable_get(:@only) + assert_not @controller.instance_variable_defined?(:@except) assert_equal 'edit', response.body end private def test_process(controller, action = "show") @controller = controller.is_a?(Class) ? controller.new : controller - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new process(action) end @@ -951,8 +954,15 @@ class ControllerWithAllTypesOfFilters < PostsController end class ControllerWithTwoLessFilters < ControllerWithAllTypesOfFilters - skip_action_callback :around_again - skip_action_callback :after + skip_around_action :around_again + skip_after_action :after +end + +class SkipFilterUsingSkipActionCallback < ControllerWithAllTypesOfFilters + ActiveSupport::Deprecation.silence do + skip_action_callback :around_again + skip_action_callback :after + end end class YieldingAroundFiltersTest < ActionController::TestCase @@ -988,8 +998,8 @@ class YieldingAroundFiltersTest < ActionController::TestCase def test_with_proc test_process(ControllerWithProcFilter,'no_raise') - assert assigns['before'] - assert assigns['after'] + assert @controller.instance_variable_get(:@before) + assert @controller.instance_variable_get(:@after) end def test_nested_actions @@ -1010,35 +1020,56 @@ class YieldingAroundFiltersTest < ActionController::TestCase 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(' ') + assert_equal 'before around (before yield) around_again (before yield) around_again (after yield) after around (after yield)', @controller.instance_variable_get(:@ran_filter).join(' ') end 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(' ') + assert_equal 'before around (before yield) around (after yield)', @controller.instance_variable_get(:@ran_filter).join(' ') end 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 '', response.body assert_equal 1, controller.instance_variable_get(:@try) end 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 '', response.body assert_equal 2, controller.instance_variable_get(:@try) end def test_last_action_in_multiple_before_action_chain_halts controller = ::FilterTest::TestMultipleFiltersController.new response = test_process(controller, 'fail_3') - assert_equal ' ', response.body + assert_equal '', response.body assert_equal 3, controller.instance_variable_get(:@try) end + def test_skipping_with_skip_action_callback + test_process(SkipFilterUsingSkipActionCallback,'no_raise') + assert_equal 'before around (before yield) around (after yield)', @controller.instance_variable_get(:@ran_filter).join(' ') + end + + def test_deprecated_skip_action_callback + assert_deprecated do + Class.new(PostsController) do + skip_action_callback :clean_up + end + end + end + + def test_deprecated_skip_filter + assert_deprecated do + Class.new(PostsController) do + skip_filter :clean_up + end + end + end + protected def test_process(controller, action = "show") @controller = controller.is_a?(Class) ? controller.new : controller diff --git a/actionpack/test/controller/flash_hash_test.rb b/actionpack/test/controller/flash_hash_test.rb index 50b36a0567..081288ef21 100644 --- a/actionpack/test/controller/flash_hash_test.rb +++ b/actionpack/test/controller/flash_hash_test.rb @@ -29,6 +29,15 @@ module ActionDispatch assert_equal 'world', @hash['hello'] end + def test_key + @hash['foo'] = 'bar' + + assert @hash.key?('foo') + assert @hash.key?(:foo) + assert_not @hash.key?('bar') + assert_not @hash.key?(:bar) + end + def test_delete @hash['foo'] = 'bar' @hash.delete 'foo' @@ -48,33 +57,36 @@ module ActionDispatch def test_to_session_value @hash['foo'] = 'bar' - assert_equal({'flashes' => {'foo' => 'bar'}, 'discard' => []}, @hash.to_session_value) - - @hash.discard('foo') - assert_equal({'flashes' => {'foo' => 'bar'}, 'discard' => %w[foo]}, @hash.to_session_value) + assert_equal({'flashes' => {'foo' => 'bar'}}, @hash.to_session_value) @hash.now['qux'] = 1 - assert_equal({'flashes' => {'foo' => 'bar', 'qux' => 1}, 'discard' => %w[foo qux]}, @hash.to_session_value) + assert_equal({'flashes' => {'foo' => 'bar'}}, @hash.to_session_value) + + @hash.discard('foo') + assert_equal(nil, @hash.to_session_value) @hash.sweep assert_equal(nil, @hash.to_session_value) end def test_from_session_value - rails_3_2_cookie = 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsAOgxAY2xvc2VkRjoNQGZsYXNoZXN7BkkiDG1lc3NhZ2UGOwBGSSIKSGVsbG8GOwBGOglAbm93MA==' + # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#<ActionDispatch::Flash::FlashHash:0x00000000000000 @used=#<Set: {"farewell"}>, @closed=false, @flashes={"greeting"=>"Hello", "farewell"=>"Goodbye"}, @now=nil>} + rails_3_2_cookie = 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsGSSINZmFyZXdlbGwGOwBUVDoMQGNsb3NlZEY6DUBmbGFzaGVzewdJIg1ncmVldGluZwY7AFRJIgpIZWxsbwY7AFRJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVDoJQG5vdzA=' session = Marshal.load(Base64.decode64(rails_3_2_cookie)) hash = Flash::FlashHash.from_session_value(session['flash']) - assert_equal({'flashes' => {'message' => 'Hello'}, 'discard' => %w[message]}, hash.to_session_value) + assert_equal({'greeting' => 'Hello'}, hash.to_hash) + assert_equal(nil, hash.to_session_value) end def test_from_session_value_on_json_serializer - decrypted_data = "{ \"session_id\":\"d98bdf6d129618fc2548c354c161cfb5\", \"flash\":{\"discard\":[], \"flashes\":{\"message\":\"hey you\"}} }" + decrypted_data = "{ \"session_id\":\"d98bdf6d129618fc2548c354c161cfb5\", \"flash\":{\"discard\":[\"farewell\"], \"flashes\":{\"greeting\":\"Hello\",\"farewell\":\"Goodbye\"}} }" session = ActionDispatch::Cookies::JsonSerializer.load(decrypted_data) hash = Flash::FlashHash.from_session_value(session['flash']) - assert_equal({'discard' => %w[message], 'flashes' => { 'message' => 'hey you'}}, hash.to_session_value) - assert_equal "hey you", hash[:message] - assert_equal "hey you", hash["message"] + assert_equal({'greeting' => 'Hello'}, hash.to_hash) + assert_equal(nil, hash.to_session_value) + assert_equal "Hello", hash[:greeting] + assert_equal "Hello", hash["greeting"] end def test_empty? diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index 3720a920d0..b063d769a4 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -57,7 +57,7 @@ class FlashTest < ActionController::TestCase def std_action @flash_copy = {}.update(flash) - render :nothing => true + head :ok end def filter_halting_action @@ -103,54 +103,55 @@ class FlashTest < ActionController::TestCase get :set_flash get :use_flash - assert_equal "hello", assigns["flash_copy"]["that"] - assert_equal "hello", assigns["flashy"] + assert_equal "hello", @controller.instance_variable_get(:@flash_copy)["that"] + assert_equal "hello", @controller.instance_variable_get(:@flashy) get :use_flash - assert_nil assigns["flash_copy"]["that"], "On second flash" + assert_nil @controller.instance_variable_get(:@flash_copy)["that"], "On second flash" end def test_keep_flash get :set_flash get :use_flash_and_keep_it - assert_equal "hello", assigns["flash_copy"]["that"] - assert_equal "hello", assigns["flashy"] + assert_equal "hello", @controller.instance_variable_get(:@flash_copy)["that"] + assert_equal "hello", @controller.instance_variable_get(:@flashy) get :use_flash - assert_equal "hello", assigns["flash_copy"]["that"], "On second flash" + assert_equal "hello", @controller.instance_variable_get(:@flash_copy)["that"], "On second flash" get :use_flash - assert_nil assigns["flash_copy"]["that"], "On third flash" + assert_nil @controller.instance_variable_get(:@flash_copy)["that"], "On third flash" end def test_flash_now get :set_flash_now - assert_equal "hello", assigns["flash_copy"]["that"] - assert_equal "bar" , assigns["flash_copy"]["foo"] - assert_equal "hello", assigns["flashy"] + assert_equal "hello", @controller.instance_variable_get(:@flash_copy)["that"] + assert_equal "bar", @controller.instance_variable_get(:@flash_copy)["foo"] + assert_equal "hello", @controller.instance_variable_get(:@flashy) get :attempt_to_use_flash_now - assert_nil assigns["flash_copy"]["that"] - assert_nil assigns["flash_copy"]["foo"] - assert_nil assigns["flashy"] + assert_nil @controller.instance_variable_get(:@flash_copy)["that"] + assert_nil @controller.instance_variable_get(:@flash_copy)["foo"] + assert_nil @controller.instance_variable_get(:@flashy) end def test_update_flash get :set_flash get :use_flash_and_update_it - assert_equal "hello", assigns["flash_copy"]["that"] - assert_equal "hello again", assigns["flash_copy"]["this"] + assert_equal "hello", @controller.instance_variable_get(:@flash_copy)["that"] + assert_equal "hello again", @controller.instance_variable_get(:@flash_copy)["this"] get :use_flash - assert_nil assigns["flash_copy"]["that"], "On second flash" - assert_equal "hello again", assigns["flash_copy"]["this"], "On second flash" + assert_nil @controller.instance_variable_get(:@flash_copy)["that"], "On second flash" + assert_equal "hello again", + @controller.instance_variable_get(:@flash_copy)["this"], "On second flash" end def test_flash_after_reset_session get :use_flash_after_reset_session - assert_equal "hello", assigns["flashy_that"] - assert_equal "good-bye", assigns["flashy_this"] - assert_nil assigns["flashy_that_reset"] + assert_equal "hello", @controller.instance_variable_get(:@flashy_that) + assert_equal "good-bye", @controller.instance_variable_get(:@flashy_this) + assert_nil @controller.instance_variable_get(:@flashy_that_reset) end def test_does_not_set_the_session_if_the_flash_is_empty @@ -160,13 +161,13 @@ class FlashTest < ActionController::TestCase def test_sweep_after_halted_action_chain get :std_action - assert_nil assigns["flash_copy"]["foo"] + assert_nil @controller.instance_variable_get(:@flash_copy)["foo"] get :filter_halting_action - assert_equal "bar", assigns["flash_copy"]["foo"] + assert_equal "bar", @controller.instance_variable_get(:@flash_copy)["foo"] get :std_action # follow redirection - assert_equal "bar", assigns["flash_copy"]["foo"] + assert_equal "bar", @controller.instance_variable_get(:@flash_copy)["foo"] get :std_action - assert_nil assigns["flash_copy"]["foo"] + assert_nil @controller.instance_variable_get(:@flash_copy)["foo"] end def test_keep_and_discard_return_values @@ -288,16 +289,16 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest def test_setting_flash_does_not_raise_in_following_requests with_test_route_set do env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } - get '/set_flash', nil, env - get '/set_flash', nil, env + get '/set_flash', env: env + get '/set_flash', env: env end end def test_setting_flash_now_does_not_raise_in_following_requests with_test_route_set do env = { 'action_dispatch.request.flash_hash' => ActionDispatch::Flash::FlashHash.new } - get '/set_flash_now', nil, env - get '/set_flash_now', nil, env + get '/set_flash_now', env: env + get '/set_flash_now', env: env end end @@ -312,9 +313,11 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest private # Overwrite get to send SessionSecret in env hash - def get(path, parameters = nil, env = {}) - env["action_dispatch.key_generator"] ||= Generator - super + def get(path, *args) + args[0] ||= {} + args[0][:env] ||= {} + args[0][:env]["action_dispatch.key_generator"] ||= Generator + super(path, *args) end def with_test_route_set @@ -326,7 +329,7 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest @app = self.class.build_app(set) do |middleware| middleware.use ActionDispatch::Session::CookieStore, :key => SessionKey middleware.use ActionDispatch::Flash - middleware.delete "ActionDispatch::ShowExceptions" + middleware.delete ActionDispatch::ShowExceptions end yield diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb index 00d4612ac9..22f1cc7c22 100644 --- a/actionpack/test/controller/force_ssl_test.rb +++ b/actionpack/test/controller/force_ssl_test.rb @@ -2,11 +2,11 @@ require 'abstract_unit' class ForceSSLController < ActionController::Base def banana - render :text => "monkey" + render plain: "monkey" end def cheeseburger - render :text => "sikachu" + render plain: "sikachu" end end @@ -26,7 +26,7 @@ class ForceSSLCustomOptions < ForceSSLController force_ssl :notice => 'Foo, Bar!', :only => :redirect_notice def force_ssl_action - render :text => action_name + render plain: action_name end alias_method :redirect_host, :force_ssl_action @@ -40,15 +40,15 @@ class ForceSSLCustomOptions < ForceSSLController alias_method :redirect_notice, :force_ssl_action def use_flash - render :text => flash[:message] + render plain: flash[:message] end def use_alert - render :text => flash[:alert] + render plain: flash[:alert] end def use_notice - render :text => flash[:notice] + render plain: flash[:notice] end end @@ -85,10 +85,10 @@ end class RedirectToSSL < ForceSSLController def banana - force_ssl_redirect || render(:text => 'monkey') + force_ssl_redirect || render(plain: 'monkey') end def cheeseburger - force_ssl_redirect('secure.cheeseburger.host') || render(:text => 'ihaz') + force_ssl_redirect('secure.cheeseburger.host') || render(plain: 'ihaz') end end @@ -100,7 +100,7 @@ class ForceSSLControllerLevelTest < ActionController::TestCase end def test_banana_redirects_to_https_with_extra_params - get :banana, :token => "secret" + get :banana, params: { token: "secret" } assert_response 301 assert_equal "https://test.host/force_ssl_controller_level/banana?token=secret", redirect_to_url end @@ -240,8 +240,8 @@ class ForceSSLFlashTest < ActionController::TestCase @request.env.delete('PATH_INFO') get :use_flash - assert_equal "hello", assigns["flash_copy"]["that"] - assert_equal "hello", assigns["flashy"] + assert_equal "hello", @controller.instance_variable_get("@flash_copy")["that"] + assert_equal "hello", @controller.instance_variable_get("@flashy") end end @@ -273,7 +273,7 @@ class ForceSSLFormatTest < ActionController::TestCase get '/foo', :to => 'force_ssl_controller_level#banana' end - get :banana, :format => :json + get :banana, format: :json assert_response 301 assert_equal 'https://test.host/foo.json', redirect_to_url end @@ -294,7 +294,7 @@ class ForceSSLOptionalSegmentsTest < ActionController::TestCase end @request.env['PATH_INFO'] = '/en/foo' - get :banana, :locale => 'en' + get :banana, params: { locale: 'en' } assert_equal 'en', @controller.params[:locale] assert_response 301 assert_equal 'https://test.host/en/foo', redirect_to_url @@ -315,7 +315,7 @@ class RedirectToSSLTest < ActionController::TestCase assert_equal "https://secure.cheeseburger.host/redirect_to_ssl/cheeseburger", redirect_to_url end - def test_banana_does_not_redirect_if_already_https + def test_cheeseburgers_does_not_redirect_if_already_https request.env['HTTPS'] = 'on' get :cheeseburger assert_response 200 diff --git a/actionpack/test/controller/form_builder_test.rb b/actionpack/test/controller/form_builder_test.rb new file mode 100644 index 0000000000..99eeaf9ab6 --- /dev/null +++ b/actionpack/test/controller/form_builder_test.rb @@ -0,0 +1,17 @@ +require 'abstract_unit' + +class FormBuilderController < ActionController::Base + class SpecializedFormBuilder < ActionView::Helpers::FormBuilder ; end + + default_form_builder SpecializedFormBuilder +end + +class ControllerFormBuilderTest < ActiveSupport::TestCase + setup do + @controller = FormBuilderController.new + end + + def test_default_form_builder_assigned + assert_equal FormBuilderController::SpecializedFormBuilder, @controller.default_form_builder + end +end diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 20f99f19ee..3ecfedefd1 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -29,7 +29,7 @@ module ImpressiveLibrary def useful_function() end end -ActionController::Base.send :include, ImpressiveLibrary +ActionController::Base.include(ImpressiveLibrary) class JustMeController < ActionController::Base clear_helpers @@ -60,6 +60,12 @@ class HelpersPathsController < ActionController::Base end end +class HelpersTypoController < ActionController::Base + path = File.expand_path('../../fixtures/helpers_typo', __FILE__) + $:.unshift(path) + self.helpers_path = path +end + module LocalAbcHelper def a() end def b() end @@ -67,14 +73,8 @@ module LocalAbcHelper end class HelperPathsTest < ActiveSupport::TestCase - def setup - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - end - def test_helpers_paths_priority - request = ActionController::TestRequest.new - responses = HelpersPathsController.action(:index).call(request.env) + responses = HelpersPathsController.action(:index).call(ActionController::TestRequest::DEFAULT_ENV.dup) # helpers1_pack was given as a second path, so pack1_helper should be # included as the second one @@ -82,6 +82,22 @@ class HelperPathsTest < ActiveSupport::TestCase end end +class HelpersTypoControllerTest < ActiveSupport::TestCase + def setup + @autoload_paths = ActiveSupport::Dependencies.autoload_paths + ActiveSupport::Dependencies.autoload_paths = Array(HelpersTypoController.helpers_path) + end + + def test_helper_typo_error_message + e = assert_raise(NameError) { HelpersTypoController.helper 'admin/users' } + assert_equal "Couldn't find Admin::UsersHelper, expected it to be defined in helpers/admin/users_helper.rb", e.message + end + + def teardown + ActiveSupport::Dependencies.autoload_paths = @autoload_paths + end +end + class HelperTest < ActiveSupport::TestCase class TestController < ActionController::Base attr_accessor :delegate_attr @@ -119,8 +135,7 @@ class HelperTest < ActiveSupport::TestCase end def call_controller(klass, action) - request = ActionController::TestRequest.new - klass.action(action).call(request.env) + klass.action(action).call(ActionController::TestRequest::DEFAULT_ENV.dup) end def test_helper_for_nested_controller @@ -136,7 +151,7 @@ class HelperTest < ActiveSupport::TestCase assert_equal "test: baz", call_controller(Fun::PdfController, "test").last.body # # request = ActionController::TestRequest.new - # response = ActionController::TestResponse.new + # response = ActionDispatch::TestResponse.new # request.action = 'test' # # assert_equal 'test: baz', Fun::PdfController.process(request, response).body @@ -201,10 +216,10 @@ class HelperTest < ActiveSupport::TestCase # fun/pdf_helper.rb assert methods.include?(:foobar) end - + def test_helper_proxy_config AllHelpersController.config.my_var = 'smth' - + assert_equal 'smth', AllHelpersController.helpers.config.my_var end @@ -227,7 +242,7 @@ class HelperTest < ActiveSupport::TestCase end -class IsolatedHelpersTest < ActiveSupport::TestCase +class IsolatedHelpersTest < ActionController::TestCase class A < ActionController::Base def index render :inline => '<%= shout %>' @@ -251,13 +266,11 @@ class IsolatedHelpersTest < ActiveSupport::TestCase end def call_controller(klass, action) - request = ActionController::TestRequest.new - klass.action(action).call(request.env) + klass.action(action).call(@request.env) end def setup - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new + super @request.action = 'index' end diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb index 9052fc6962..0a5e5402b9 100644 --- a/actionpack/test/controller/http_basic_authentication_test.rb +++ b/actionpack/test/controller/http_basic_authentication_test.rb @@ -9,19 +9,19 @@ class HttpBasicAuthenticationTest < ActionController::TestCase http_basic_authenticate_with :name => "David", :password => "Goliath", :only => :search def index - render :text => "Hello Secret" + render plain: "Hello Secret" end def display - render :text => 'Definitely Maybe' + render plain: 'Definitely Maybe' if @logged_in end def show - render :text => 'Only for loooooong credentials' + render plain: 'Only for loooooong credentials' end def search - render :text => 'All inline' + render plain: 'All inline' end private @@ -36,7 +36,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase if authenticate_with_http_basic { |username, password| username == 'pretty' && password == 'please' } @logged_in = true else - request_http_basic_authentication("SuperSecret") + request_http_basic_authentication("SuperSecret", "Authentication Failed\n") end end @@ -83,6 +83,13 @@ class HttpBasicAuthenticationTest < ActionController::TestCase assert_response :unauthorized assert_equal "HTTP Basic: Access denied.\n", @response.body, "Authentication didn't fail for request header #{header} and long credentials" end + + test "unsuccessful authentication with #{header.downcase} and no credentials" do + get :show + + assert_response :unauthorized + assert_equal "HTTP Basic: Access denied.\n", @response.body, "Authentication didn't fail for request header #{header} and no credentials" + end end def test_encode_credentials_has_no_newline @@ -93,11 +100,19 @@ class HttpBasicAuthenticationTest < ActionController::TestCase assert_no_match(/\n/, result) end + test "succesful authentication with uppercase authorization scheme" do + @request.env['HTTP_AUTHORIZATION'] = "BASIC #{::Base64.encode64("lifo:world")}" + get :index + + assert_response :success + assert_equal 'Hello Secret', @response.body, 'Authentication failed when authorization scheme BASIC' + end + test "authentication request without credential" do get :display assert_response :unauthorized - assert_equal "HTTP Basic: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Basic realm="SuperSecret"', @response.headers['WWW-Authenticate'] end @@ -106,7 +121,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase get :display assert_response :unauthorized - assert_equal "HTTP Basic: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Basic realm="SuperSecret"', @response.headers['WWW-Authenticate'] end @@ -115,7 +130,6 @@ class HttpBasicAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index 52a0bc9aa3..f06912bd5a 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -10,11 +10,11 @@ class HttpDigestAuthenticationTest < ActionController::TestCase 'dhh' => ::Digest::MD5::hexdigest(["dhh","SuperSecret","secret"].join(":"))} def index - render :text => "Hello Secret" + render plain: "Hello Secret" end def display - render :text => 'Definitely Maybe' + render plain: 'Definitely Maybe' if @logged_in end private @@ -124,7 +124,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -134,7 +133,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -144,7 +142,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -156,7 +153,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -167,7 +163,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -180,7 +175,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -191,7 +185,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -201,7 +194,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase put :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end @@ -244,7 +236,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase get :display assert_response :success - assert assigns(:logged_in) assert_equal 'Definitely Maybe', @response.body end diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb index 8c6c8a0aa7..9c5a01c318 100644 --- a/actionpack/test/controller/http_token_authentication_test.rb +++ b/actionpack/test/controller/http_token_authentication_test.rb @@ -7,15 +7,15 @@ class HttpTokenAuthenticationTest < ActionController::TestCase before_action :authenticate_long_credentials, only: :show def index - render :text => "Hello Secret" + render plain: "Hello Secret" end def display - render :text => 'Definitely Maybe' + render plain: 'Definitely Maybe' end def show - render :text => 'Only for loooooong credentials' + render plain: 'Only for loooooong credentials' end private @@ -30,7 +30,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase if authenticate_with_http_token { |token, options| token == '"quote" pretty' && options[:algorithm] == 'test' } @logged_in = true else - request_http_token_authentication("SuperSecret") + request_http_token_authentication("SuperSecret", "Authentication Failed\n") end end @@ -80,18 +80,25 @@ class HttpTokenAuthenticationTest < ActionController::TestCase end test "authentication request with badly formatted header" do - @request.env['HTTP_AUTHORIZATION'] = "Token foobar" + @request.env['HTTP_AUTHORIZATION'] = 'Token token$"lifo"' get :index assert_response :unauthorized assert_equal "HTTP Token: Access denied.\n", @response.body, "Authentication header was not properly parsed" end + test "successful authentication request with Bearer instead of Token" do + @request.env['HTTP_AUTHORIZATION'] = 'Bearer lifo' + get :index + + assert_response :success + end + test "authentication request without credential" do get :display assert_response :unauthorized - assert_equal "HTTP Token: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Token realm="SuperSecret"', @response.headers['WWW-Authenticate'] end @@ -100,7 +107,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase get :display assert_response :unauthorized - assert_equal "HTTP Token: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Token realm="SuperSecret"', @response.headers['WWW-Authenticate'] end @@ -162,17 +169,36 @@ class HttpTokenAuthenticationTest < ActionController::TestCase assert_equal(expected, actual) end + test "token_and_options returns right token when token key is not specified in header" do + token = "rcHu+HzSFw89Ypyhn/896A=" + + actual = ActionController::HttpAuthentication::Token.token_and_options( + sample_request_without_token_key(token) + ).first + + expected = token + 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 + mock_authorization_request(authorization) end def malformed_request - @malformed_request ||= OpenStruct.new authorization: %{Token token=} + mock_authorization_request(%{Token token=}) + end + + def sample_request_without_token_key(token) + mock_authorization_request(%{Token #{token}}) + end + + def mock_authorization_request(authorization) + OpenStruct.new(authorization: authorization) end def encode_credentials(token, options = {}) diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 99b53e6fd2..d0a1d1285f 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -26,180 +26,341 @@ class SessionTest < ActiveSupport::TestCase end def test_follow_redirect_raises_when_no_redirect - @session.stubs(:redirect?).returns(false) - assert_raise(RuntimeError) { @session.follow_redirect! } + @session.stub :redirect?, false do + assert_raise(RuntimeError) { @session.follow_redirect! } + end end def test_request_via_redirect_uses_given_method path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"} - @session.expects(:process).with(:put, path, args, headers) - @session.stubs(:redirect?).returns(false) - @session.request_via_redirect(:put, path, args, headers) + assert_called_with @session, :process, [:put, path, params: args, headers: headers] do + @session.stub :redirect?, false do + @session.request_via_redirect(:put, path, params: args, headers: headers) + end + end + end + + def test_deprecated_request_via_redirect_uses_given_method + path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" } + assert_called_with @session, :process, [:put, path, params: args, headers: headers] do + @session.stub :redirect?, false do + assert_deprecated { @session.request_via_redirect(:put, path, args, headers) } + end + end end def test_request_via_redirect_follows_redirects path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"} - @session.stubs(:redirect?).returns(true, true, false) - @session.expects(:follow_redirect!).times(2) - @session.request_via_redirect(:get, path, args, headers) + value_series = [true, true, false] + assert_called @session, :follow_redirect!, times: 2 do + @session.stub :redirect?, ->{ value_series.shift } do + @session.request_via_redirect(:get, path, params: args, headers: headers) + end + end end def test_request_via_redirect_returns_status path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"} - @session.stubs(:redirect?).returns(false) - @session.stubs(:status).returns(200) - assert_equal 200, @session.request_via_redirect(:get, path, args, headers) + @session.stub :redirect?, false do + @session.stub :status, 200 do + assert_equal 200, @session.request_via_redirect(:get, path, params: args, headers: headers) + end + end end - def test_get_via_redirect - path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } - @session.expects(:request_via_redirect).with(:get, path, args, headers) - @session.get_via_redirect(path, args, headers) + def test_deprecated_get_via_redirect + path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" } + + assert_called_with @session, :request_via_redirect, [:get, path, args, headers] do + assert_deprecated do + @session.get_via_redirect(path, args, headers) + end + end end - def test_post_via_redirect - path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } - @session.expects(:request_via_redirect).with(:post, path, args, headers) - @session.post_via_redirect(path, args, headers) + def test_deprecated_post_via_redirect + path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" } + + assert_called_with @session, :request_via_redirect, [:post, path, args, headers] do + assert_deprecated do + @session.post_via_redirect(path, args, headers) + end + end end - def test_patch_via_redirect - path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } - @session.expects(:request_via_redirect).with(:patch, path, args, headers) - @session.patch_via_redirect(path, args, headers) + def test_deprecated_patch_via_redirect + path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" } + + assert_called_with @session, :request_via_redirect, [:patch, path, args, headers] do + assert_deprecated do + @session.patch_via_redirect(path, args, headers) + end + end end - def test_put_via_redirect - path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } - @session.expects(:request_via_redirect).with(:put, path, args, headers) - @session.put_via_redirect(path, args, headers) + def test_deprecated_put_via_redirect + path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" } + + assert_called_with @session, :request_via_redirect, [:put, path, args, headers] do + assert_deprecated do + @session.put_via_redirect(path, args, headers) + end + end end - def test_delete_via_redirect - path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } - @session.expects(:request_via_redirect).with(:delete, path, args, headers) - @session.delete_via_redirect(path, args, headers) + def test_deprecated_delete_via_redirect + path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" } + + assert_called_with @session, :request_via_redirect, [:delete, path, args, headers] do + assert_deprecated do + @session.delete_via_redirect(path, args, headers) + end + end end def test_get - path = "/index"; params = "blah"; headers = {:location => 'blah'} - @session.expects(:process).with(:get,path,params,headers) - @session.get(path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + + assert_called_with @session, :process, [:get, path, params: params, headers: headers] do + @session.get(path, params: params, headers: headers) + end + end + + def test_get_with_env_and_headers + path = "/index"; params = "blah"; headers = { location: 'blah' }; env = { 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest' } + assert_called_with @session, :process, [:get, path, params: params, headers: headers, env: env] do + @session.get(path, params: params, headers: headers, env: env) + end + end + + def test_deprecated_get + path = "/index"; params = "blah"; headers = { location: 'blah' } + + assert_called_with @session, :process, [:get, path, params: params, headers: headers] do + assert_deprecated { + @session.get(path, params, headers) + } + end end def test_post - path = "/index"; params = "blah"; headers = {:location => 'blah'} - @session.expects(:process).with(:post,path,params,headers) - @session.post(path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:post, path, params: params, headers: headers] do + assert_deprecated { + @session.post(path, params, headers) + } + end + end + + def test_deprecated_post + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:post, path, params: params, headers: headers] do + @session.post(path, params: params, headers: headers) + end end def test_patch - path = "/index"; params = "blah"; headers = {:location => 'blah'} - @session.expects(:process).with(:patch,path,params,headers) - @session.patch(path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:patch, path, params: params, headers: headers] do + @session.patch(path, params: params, headers: headers) + end + end + + def test_deprecated_patch + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:patch, path, params: params, headers: headers] do + assert_deprecated { + @session.patch(path, params, headers) + } + end end def test_put - path = "/index"; params = "blah"; headers = {:location => 'blah'} - @session.expects(:process).with(:put,path,params,headers) - @session.put(path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:put, path, params: params, headers: headers] do + @session.put(path, params: params, headers: headers) + end + end + + def test_deprecated_put + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:put, path, params: params, headers: headers] do + assert_deprecated { + @session.put(path, params, headers) + } + end end def test_delete - path = "/index"; params = "blah"; headers = {:location => 'blah'} - @session.expects(:process).with(:delete,path,params,headers) - @session.delete(path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:delete, path, params: params, headers: headers] do + assert_deprecated { + @session.delete(path,params,headers) + } + end + end + + def test_deprecated_delete + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:delete, path, params: params, headers: headers] do + @session.delete(path, params: params, headers: headers) + end end def test_head - path = "/index"; params = "blah"; headers = {:location => 'blah'} - @session.expects(:process).with(:head,path,params,headers) - @session.head(path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:head, path, params: params, headers: headers] do + @session.head(path, params: params, headers: headers) + end + end + + def deprecated_test_head + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:head, path, params: params, headers: headers] do + assert_deprecated { + @session.head(path, params, headers) + } + end end def test_xml_http_request_get - path = "/index"; params = "blah"; headers = {:location => 'blah'} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", - "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" - ) - @session.expects(:process).with(:get,path,params,headers_after_xhr) - @session.xml_http_request(:get,path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:get, path, params: params, headers: headers, xhr: true] do + @session.get(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_xml_http_request_get + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:get, path, params: params, headers: headers, xhr: true] do + @session.get(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_args_xml_http_request_get + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:get, path, params: params, headers: headers, xhr: true] do + assert_deprecated(/xml_http_request/) { + @session.xml_http_request(:get, path, params, headers) + } + end end def test_xml_http_request_post - path = "/index"; params = "blah"; headers = {:location => 'blah'} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", - "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" - ) - @session.expects(:process).with(:post,path,params,headers_after_xhr) - @session.xml_http_request(:post,path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:post, path, params: params, headers: headers, xhr: true] do + @session.post(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_xml_http_request_post + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:post, path, params: params, headers: headers, xhr: true] do + @session.post(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_args_xml_http_request_post + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:post, path, params: params, headers: headers, xhr: true] do + assert_deprecated(/xml_http_request/) { @session.xml_http_request(:post,path,params,headers) } + end end def test_xml_http_request_patch - path = "/index"; params = "blah"; headers = {:location => 'blah'} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", - "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" - ) - @session.expects(:process).with(:patch,path,params,headers_after_xhr) - @session.xml_http_request(:patch,path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:patch, path, params: params, headers: headers, xhr: true] do + @session.patch(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_xml_http_request_patch + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:patch, path, params: params, headers: headers, xhr: true] do + @session.patch(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_args_xml_http_request_patch + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:patch, path, params: params, headers: headers, xhr: true] do + assert_deprecated(/xml_http_request/) { @session.xml_http_request(:patch,path,params,headers) } + end end def test_xml_http_request_put - path = "/index"; params = "blah"; headers = {:location => 'blah'} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", - "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" - ) - @session.expects(:process).with(:put,path,params,headers_after_xhr) - @session.xml_http_request(:put,path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:put, path, params: params, headers: headers, xhr: true] do + @session.put(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_xml_http_request_put + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:put, path, params: params, headers: headers, xhr: true] do + @session.put(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_args_xml_http_request_put + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:put, path, params: params, headers: headers, xhr: true] do + assert_deprecated(/xml_http_request/) { @session.xml_http_request(:put, path, params, headers) } + end end def test_xml_http_request_delete - path = "/index"; params = "blah"; headers = {:location => 'blah'} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", - "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" - ) - @session.expects(:process).with(:delete,path,params,headers_after_xhr) - @session.xml_http_request(:delete,path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:delete, path, params: params, headers: headers, xhr: true] do + @session.delete(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_xml_http_request_delete + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:delete, path, params: params, headers: headers, xhr: true] do + assert_deprecated { @session.xml_http_request(:delete, path, params: params, headers: headers) } + end + end + + def test_deprecated_args_xml_http_request_delete + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:delete, path, params: params, headers: headers, xhr: true] do + assert_deprecated(/xml_http_request/) { @session.xml_http_request(:delete, path, params, headers) } + end end def test_xml_http_request_head - path = "/index"; params = "blah"; headers = {:location => 'blah'} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", - "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*" - ) - @session.expects(:process).with(:head,path,params,headers_after_xhr) - @session.xml_http_request(:head,path,params,headers) - end - - def test_xml_http_request_override_accept - path = "/index"; params = "blah"; headers = {:location => 'blah', "HTTP_ACCEPT" => "application/xml"} - headers_after_xhr = headers.merge( - "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest" - ) - @session.expects(:process).with(:post,path,params,headers_after_xhr) - @session.xml_http_request(:post,path,params,headers) + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:head, path, params: params, headers: headers, xhr: true] do + @session.head(path, params: params, headers: headers, xhr: true) + end + end + + def test_deprecated_xml_http_request_head + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:head, path, params: params, headers: headers, xhr: true] do + assert_deprecated(/xml_http_request/) { @session.xml_http_request(:head, path, params: params, headers: headers) } + end + end + + def test_deprecated_args_xml_http_request_head + path = "/index"; params = "blah"; headers = { location: 'blah' } + assert_called_with @session, :process, [:head, path, params: params, headers: headers, xhr: true] do + assert_deprecated { @session.xml_http_request(:head, path, params, headers) } + end end end class IntegrationTestTest < ActiveSupport::TestCase def setup @test = ::ActionDispatch::IntegrationTest.new(:app) - @test.class.stubs(:fixture_table_names).returns([]) - @session = @test.open_session end def test_opens_new_session session1 = @test.open_session { |sess| } session2 = @test.open_session # implicit session - assert_respond_to session1, :assert_template, "open_session makes assert_template available" - assert_respond_to session2, :assert_template, "open_session makes assert_template available" assert !session1.equal?(session2) end @@ -225,14 +386,8 @@ end # Tests that integration tests don't call Controller test methods for processing. # Integration tests have their own setup and teardown. class IntegrationTestUsesCorrectClass < ActionDispatch::IntegrationTest - def self.fixture_table_names - [] - end - def test_integration_methods_called reset! - @integration_session.stubs(:generic_url_rewriter) - @integration_session.stubs(:process) %w( get post head patch put delete ).each do |verb| assert_nothing_raised("'#{verb}' should use integration test methods") { __send__(verb, '/') } @@ -244,27 +399,30 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest class IntegrationController < ActionController::Base def get respond_to do |format| - format.html { render :text => "OK", :status => 200 } - format.js { render :text => "JS OK", :status => 200 } + format.html { render plain: "OK", status: 200 } + format.js { render plain: "JS OK", status: 200 } + format.xml { render :xml => "<root></root>", :status => 200 } + format.rss { render :xml => "<root></root>", :status => 200 } + format.atom { render :xml => "<root></root>", :status => 200 } end end def get_with_params - render :text => "foo: #{params[:foo]}", :status => 200 + render plain: "foo: #{params[:foo]}", status: 200 end def post - render :text => "Created", :status => 201 + render plain: "Created", status: 201 end def method - render :text => "method: #{request.method.downcase}" + render plain: "method: #{request.method.downcase}" end def cookie_monster cookies["cookie_1"] = nil cookies["cookie_3"] = "chocolate" - render :text => "Gone", :status => 410 + render plain: "Gone", status: 410 end def set_cookie @@ -273,12 +431,17 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end def get_cookie - render :text => cookies["foo"] + render plain: cookies["foo"] end def redirect redirect_to action_url('get') end + + def remove_header + response.headers.delete params[:header] + head :ok, 'c' => '3' + end end def test_get @@ -297,6 +460,24 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end end + def test_get_xml_rss_atom + %w[ application/xml application/rss+xml application/atom+xml ].each do |mime_string| + with_test_route_set do + get "/get", headers: {"HTTP_ACCEPT" => mime_string} + assert_equal 200, status + assert_equal "OK", status_message + assert_response 200 + assert_response :success + assert_response :ok + assert_equal({}, cookies.to_hash) + assert_equal "<root></root>", body + assert_equal "<root></root>", response.body + assert_instance_of Nokogiri::XML::Document, html_document + assert_equal 1, request_count + end + end + end + def test_post with_test_route_set do post '/post' @@ -383,7 +564,19 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest def test_xml_http_request_get with_test_route_set do - xhr :get, '/get' + get '/get', xhr: true + assert_equal 200, status + assert_equal "OK", status_message + assert_response 200 + assert_response :success + assert_response :ok + assert_equal "JS OK", response.body + end + end + + def test_deprecated_xml_http_request_get + with_test_route_set do + assert_deprecated { xhr :get, '/get' } assert_equal 200, status assert_equal "OK", status_message assert_response 200 @@ -395,7 +588,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest def test_request_with_bad_format with_test_route_set do - xhr :get, '/get.php' + get '/get.php', xhr: true assert_equal 406, status assert_response 406 assert_response :not_acceptable @@ -418,7 +611,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest def test_get_with_parameters with_test_route_set do - get '/get_with_params', :foo => "bar" + get '/get_with_params', params: { foo: "bar" } assert_equal '/get_with_params', request.env["PATH_INFO"] assert_equal '/get_with_params', request.path_info assert_equal 'foo=bar', request.env["QUERY_STRING"] @@ -506,7 +699,27 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end end + def test_respect_removal_of_default_headers_by_a_controller_action + with_test_route_set do + with_default_headers 'a' => '1', 'b' => '2' do + get '/remove_header', params: { header: 'a' } + end + end + + assert_not_includes @response.headers, 'a', 'Response should not include default header removed by the controller action' + assert_includes @response.headers, 'b' + assert_includes @response.headers, 'c' + end + private + def with_default_headers(headers) + original = ActionDispatch::Response.default_headers + ActionDispatch::Response.default_headers = headers + yield + ensure + ActionDispatch::Response.default_headers = original + end + def with_test_route_set with_routing do |set| controller = ::IntegrationProcessTest::IntegrationController.clone @@ -521,7 +734,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest get 'get/:action', :to => controller, :as => :get_action end - self.singleton_class.send(:include, set.url_helpers) + self.singleton_class.include(set.url_helpers) yield end @@ -565,25 +778,52 @@ class MetalIntegrationTest < ActionDispatch::IntegrationTest end def test_pass_headers - get "/success", {}, "Referer" => "http://www.example.com/foo", "Host" => "http://nohost.com" + get "/success", headers: {"Referer" => "http://www.example.com/foo", "Host" => "http://nohost.com"} assert_equal "http://nohost.com", @request.env["HTTP_HOST"] assert_equal "http://www.example.com/foo", @request.env["HTTP_REFERER"] end + def test_pass_headers_and_env + get "/success", headers: { "X-Test-Header" => "value" }, env: { "HTTP_REFERER" => "http://test.com/", "HTTP_HOST" => "http://test.com" } + + assert_equal "http://test.com", @request.env["HTTP_HOST"] + assert_equal "http://test.com/", @request.env["HTTP_REFERER"] + assert_equal "value", @request.env["HTTP_X_TEST_HEADER"] + end + def test_pass_env - get "/success", {}, "HTTP_REFERER" => "http://test.com/", "HTTP_HOST" => "http://test.com" + get "/success", env: { "HTTP_REFERER" => "http://test.com/", "HTTP_HOST" => "http://test.com" } assert_equal "http://test.com", @request.env["HTTP_HOST"] assert_equal "http://test.com/", @request.env["HTTP_REFERER"] end + def test_ignores_common_ports_in_host + get "http://test.com" + assert_equal "test.com", @request.env["HTTP_HOST"] + + get "https://test.com" + assert_equal "test.com", @request.env["HTTP_HOST"] + end + + def test_keeps_uncommon_ports_in_host + get "http://test.com:123" + assert_equal "test.com:123", @request.env["HTTP_HOST"] + + get "http://test.com:443" + assert_equal "test.com:443", @request.env["HTTP_HOST"] + + get "https://test.com:80" + assert_equal "test.com:80", @request.env["HTTP_HOST"] + end + end class ApplicationIntegrationTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base def index - render :text => "index" + render plain: "index" end end @@ -615,6 +855,8 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest get 'bar', :to => 'application_integration_test/test#index', :as => :bar mount MountedApp => '/mounted', :as => "mounted" + get 'fooz' => proc { |env| [ 200, {'X-Cascade' => 'pass'}, [ "omg" ] ] }, :anchor => false + get 'fooz', :to => 'application_integration_test/test#index' end def app @@ -631,6 +873,12 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest assert_equal '/mounted/baz', mounted.baz_path end + test "path after cascade pass" do + get '/fooz' + assert_equal 'index', response.body + assert_equal '/fooz', path + end + test "route helpers after controller access" do get '/' assert_equal '/', empty_string_path @@ -654,7 +902,7 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest test "process do not modify the env passed as argument" do env = { :SERVER_NAME => 'server', 'action_dispatch.custom' => 'custom' } old_env = env.dup - get '/foo', nil, env + get '/foo', env: env assert_equal old_env, env end end @@ -662,7 +910,7 @@ end class EnvironmentFilterIntegrationTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base def post - render :text => "Created", :status => 201 + render plain: "Created", status: 201 end end @@ -684,7 +932,7 @@ class EnvironmentFilterIntegrationTest < ActionDispatch::IntegrationTest end test "filters rack request form vars" do - post "/post", :username => 'cjolly', :password => 'secret' + post "/post", params: { username: 'cjolly', password: 'secret' } assert_equal 'cjolly', request.filtered_parameters['username'] assert_equal '[FILTERED]', request.filtered_parameters['password'] @@ -695,15 +943,15 @@ end class UrlOptionsIntegrationTest < ActionDispatch::IntegrationTest class FooController < ActionController::Base def index - render :text => "foo#index" + render plain: "foo#index" end def show - render :text => "foo#show" + render plain: "foo#show" end def edit - render :text => "foo#show" + render plain: "foo#show" end end @@ -713,7 +961,7 @@ class UrlOptionsIntegrationTest < ActionDispatch::IntegrationTest end def index - render :text => "foo#index" + render plain: "foo#index" end end @@ -806,3 +1054,75 @@ class HeadWithStatusActionIntegrationTest < ActionDispatch::IntegrationTest assert_response :ok end end + +class IntegrationWithRoutingTest < ActionDispatch::IntegrationTest + class FooController < ActionController::Base + def index + render plain: 'ok' + end + end + + def test_with_routing_resets_session + klass_namespace = self.class.name.underscore + + with_routing do |routes| + routes.draw do + namespace klass_namespace do + resources :foo, path: '/with' + end + end + + get '/integration_with_routing_test/with' + assert_response 200 + assert_equal 'ok', response.body + end + + with_routing do |routes| + routes.draw do + namespace klass_namespace do + resources :foo, path: '/routing' + end + end + + get '/integration_with_routing_test/routing' + assert_response 200 + assert_equal 'ok', response.body + end + end +end + +# to work in contexts like rspec before(:all) +class IntegrationRequestsWithoutSetup < ActionDispatch::IntegrationTest + self._setup_callbacks = [] + self._teardown_callbacks = [] + + class FooController < ActionController::Base + def ok + cookies[:key] = 'ok' + render plain: 'ok' + end + end + + def test_request + with_routing do |routes| + routes.draw { get ':action' => FooController } + get '/ok' + + assert_response 200 + assert_equal 'ok', response.body + assert_equal 'ok', cookies['key'] + end + end +end + +# to ensure that session requirements in setup are persisted in the tests +class IntegrationRequestsWithSessionSetup < ActionDispatch::IntegrationTest + setup do + cookies['user_name'] = 'david' + end + + def test_cookies_set_in_setup_are_persisted_through_the_session + get "/foo" + assert_equal({"user_name"=>"david"}, cookies.to_hash) + end +end diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb index 7fd1276e98..843dafac06 100644 --- a/actionpack/test/controller/live_stream_test.rb +++ b/actionpack/test/controller/live_stream_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'active_support/concurrency/latch' +require 'concurrent/atomic/count_down_latch' Thread.abort_on_exception = true module ActionController @@ -112,7 +112,7 @@ module ActionController class TestController < ActionController::Base include ActionController::Live - attr_accessor :latch, :tc + attr_accessor :latch, :tc, :error_latch def self.controller_path 'test' @@ -125,7 +125,7 @@ module ActionController end def render_text - render :text => 'zomg' + render plain: 'zomg' end def default_header @@ -145,7 +145,7 @@ module ActionController response.headers['Content-Type'] = 'text/event-stream' %w{ hello world }.each do |word| response.stream.write word - latch.await + latch.wait end response.stream.close end @@ -162,7 +162,7 @@ module ActionController end def with_stale - render text: 'stale' if stale?(etag: "123", template: false) + render plain: 'stale' if stale?(etag: "123", template: false) end def exception_in_view @@ -204,6 +204,12 @@ module ActionController end def overfill_buffer_and_die + logger = ActionController::Base.logger || Logger.new($stdout) + response.stream.on_error do + logger.warn 'Error while streaming' + error_latch.count_down + end + # Write until the buffer is full. It doesn't expose that # information directly, so we must hard-code its size: 10.times do @@ -212,7 +218,7 @@ module ActionController # .. plus one more, because the #each frees up a slot: response.stream.write '.' - latch.release + latch.count_down # This write will block, and eventually raise response.stream.write 'x' @@ -233,7 +239,7 @@ module ActionController end logger.info 'Work complete' - latch.release + latch.count_down end end @@ -256,98 +262,79 @@ module ActionController end def test_set_cookie - @controller = TestController.new get :set_cookie assert_equal({'hello' => 'world'}, @response.cookies) assert_equal "hello world", @response.body end - def test_set_response! - @controller.set_response!(@request) - assert_kind_of(Live::Response, @controller.response) - assert_equal @request, @controller.response.request - end - def test_write_to_stream - @controller = TestController.new get :basic_stream assert_equal "helloworld", @response.body assert_equal 'text/event-stream', @response.headers['Content-Type'] end def test_async_stream - @controller.latch = ActiveSupport::Concurrency::Latch.new + rubinius_skip "https://github.com/rubinius/rubinius/issues/2934" + + @controller.latch = Concurrent::CountDownLatch.new parts = ['hello', 'world'] - @controller.request = @request - @controller.response = @response + get :blocking_stream - t = Thread.new(@response) { |resp| + t = Thread.new(response) { |resp| resp.await_commit resp.stream.each do |part| assert_equal parts.shift, part ol = @controller.latch - @controller.latch = ActiveSupport::Concurrency::Latch.new - ol.release + @controller.latch = Concurrent::CountDownLatch.new + ol.count_down end } - @controller.process :blocking_stream - 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 - } + @controller.latch = Concurrent::CountDownLatch.new + @controller.error_latch = Concurrent::CountDownLatch.new capture_log_output do |output| - @controller.process :overfill_buffer_and_die + get :overfill_buffer_and_die, :format => 'plain' + + t = Thread.new(response) { |resp| + resp.await_commit + _, _, body = resp.to_a + body.each do + @controller.latch.wait + body.close + break + end + } + t.join - got_error.await + @controller.error_latch.wait assert_match 'Error while streaming', output.rewind && output.read end end def test_ignore_client_disconnect - @controller.latch = ActiveSupport::Concurrency::Latch.new + @controller.latch = Concurrent::CountDownLatch.new - @controller.request = @request - @controller.response = @response + capture_log_output do |output| + get :ignore_client_disconnect - t = Thread.new(@response) { |resp| - resp.await_commit - _, _, body = resp.to_a - body.each do |part| - body.close - break - end - } + t = Thread.new(response) { |resp| + resp.await_commit + _, _, body = resp.to_a + body.each do + body.close + break + end + } - capture_log_output do |output| - @controller.process :ignore_client_disconnect t.join Timeout.timeout(3) do - @controller.latch.await + @controller.latch.wait end assert_match 'Work complete', output.rewind && output.read end @@ -362,11 +349,8 @@ module ActionController end def test_live_stream_default_header - @controller.request = @request - @controller.response = @response - @controller.process :default_header - _, headers, _ = @response.prepare! - assert headers['Content-Type'] + get :default_header + assert response.headers['Content-Type'] end def test_render_text @@ -404,8 +388,14 @@ module ActionController end def test_exception_callback_when_committed + current_threads = Thread.list + capture_log_output do |output| get :exception_with_callback, format: 'text/event-stream' + + # Wait on the execution of all threads + (Thread.list - current_threads).each(&:join) + assert_equal %(data: "500 Internal Server Error"\n\n), response.body assert_match 'An exception occurred...', output.rewind && output.read assert_stream_closed @@ -435,13 +425,13 @@ module ActionController def test_stale_without_etag get :with_stale - assert_equal 200, @response.status.to_i + assert_equal 200, response.status.to_i end def test_stale_with_etag @request.if_none_match = Digest::MD5.hexdigest("123") get :with_stale - assert_equal 304, @response.status.to_i + assert_equal 304, response.status.to_i end end diff --git a/actionpack/test/controller/localized_templates_test.rb b/actionpack/test/controller/localized_templates_test.rb index 27871ef351..3576015513 100644 --- a/actionpack/test/controller/localized_templates_test.rb +++ b/actionpack/test/controller/localized_templates_test.rb @@ -19,7 +19,7 @@ class LocalizedTemplatesTest < ActionController::TestCase def test_localized_template_is_used I18n.locale = :de get :hello_world - assert_equal "Gutten Tag", @response.body + assert_equal "Guten Tag", @response.body end def test_default_locale_template_is_used_when_locale_is_missing @@ -30,11 +30,11 @@ class LocalizedTemplatesTest < ActionController::TestCase def test_use_fallback_locales I18n.locale = :"de-AT" - I18n.backend.class.send(:include, I18n::Backend::Fallbacks) + I18n.backend.class.include(I18n::Backend::Fallbacks) I18n.fallbacks[:"de-AT"] = [:de] get :hello_world - assert_equal "Gutten Tag", @response.body + assert_equal "Guten Tag", @response.body end def test_localized_template_has_correct_header_with_no_format_in_template_name diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 49be7caf38..6ae33be3c8 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -10,7 +10,7 @@ module Another end rescue_from SpecialException do - head :status => 406 + head 406 end before_action :redirector, only: :never_executed @@ -19,7 +19,7 @@ module Another end def show - render :nothing => true + head :ok end def redirector @@ -73,6 +73,16 @@ module Another def with_action_not_found raise AbstractController::ActionNotFound end + + def append_info_to_payload(payload) + super + payload[:test_key] = "test_value" + @last_payload = payload + end + + def last_payload + @last_payload + end end end @@ -130,7 +140,7 @@ class ACLogSubscriberTest < ActionController::TestCase end def test_process_action_with_parameters - get :show, :id => '10' + get :show, params: { id: '10' } wait assert_equal 3, logs.size @@ -138,8 +148,8 @@ class ACLogSubscriberTest < ActionController::TestCase end def test_multiple_process_with_parameters - get :show, :id => '10' - get :show, :id => '20' + get :show, params: { id: '10' } + get :show, params: { id: '20' } wait @@ -150,7 +160,7 @@ class ACLogSubscriberTest < ActionController::TestCase def test_process_action_with_wrapped_parameters @request.env['CONTENT_TYPE'] = 'application/json' - post :show, :id => '10', :name => 'jose' + post :show, params: { id: '10', name: 'jose' } wait assert_equal 3, logs.size @@ -160,13 +170,25 @@ class ACLogSubscriberTest < ActionController::TestCase def test_process_action_with_view_runtime get :show wait - assert_match(/\(Views: [\d.]+ms\)/, logs[1]) + assert_match(/Completed 200 OK in \d+ms/, logs[1]) + end + + def test_append_info_to_payload_is_called_even_with_exception + begin + get :with_exception + wait + rescue Exception + end + + assert_equal "test_value", @controller.last_payload[:test_key] end def test_process_action_with_filter_parameters @request.env["action_dispatch.parameter_filter"] = [:lifo, :amount] - get :show, :lifo => 'Pratik', :amount => '420', :step => '1' + get :show, params: { + lifo: 'Pratik', amount: '420', step: '1' + } wait params = logs[1] diff --git a/actionpack/test/controller/mime/accept_format_test.rb b/actionpack/test/controller/mime/accept_format_test.rb index 811c507af2..e20c08da4e 100644 --- a/actionpack/test/controller/mime/accept_format_test.rb +++ b/actionpack/test/controller/mime/accept_format_test.rb @@ -11,7 +11,7 @@ end class StarStarMimeControllerTest < ActionController::TestCase def test_javascript_with_format @request.accept = "text/javascript" - get :index, :format => 'js' + get :index, format: 'js' assert_match "function addition(a,b){ return a+b; }", @response.body end @@ -86,7 +86,7 @@ class MimeControllerLayoutsTest < ActionController::TestCase end def test_non_navigational_format_with_no_template_fallbacks_to_html_template_with_no_layout - get :index, :format => :js + get :index, format: :js assert_equal "Hello Firefox", @response.body end end diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb index 1bc7ad3015..c025c7fa00 100644 --- a/actionpack/test/controller/mime/respond_to_test.rb +++ b/actionpack/test/controller/mime/respond_to_test.rb @@ -1,45 +1,53 @@ require 'abstract_unit' +require "active_support/log_subscriber/test_helper" class RespondToController < ActionController::Base layout :set_layout + before_action { + case params[:v] + when String then request.variant = params[:v].to_sym + when Array then request.variant = params[:v].map(&:to_sym) + end + } + def html_xml_or_rss respond_to do |type| - type.html { render :text => "HTML" } - type.xml { render :text => "XML" } - type.rss { render :text => "RSS" } - type.all { render :text => "Nothing" } + type.html { render body: "HTML" } + type.xml { render body: "XML" } + type.rss { render body: "RSS" } + type.all { render body: "Nothing" } end end def js_or_html respond_to do |type| - type.html { render :text => "HTML" } - type.js { render :text => "JS" } - type.all { render :text => "Nothing" } + type.html { render body: "HTML" } + type.js { render body: "JS" } + type.all { render body: "Nothing" } end end def json_or_yaml respond_to do |type| - type.json { render :text => "JSON" } - type.yaml { render :text => "YAML" } + type.json { render body: "JSON" } + type.yaml { render body: "YAML" } end end def html_or_xml respond_to do |type| - type.html { render :text => "HTML" } - type.xml { render :text => "XML" } - type.all { render :text => "Nothing" } + type.html { render body: "HTML" } + type.xml { render body: "XML" } + type.all { render body: "Nothing" } end end def json_xml_or_html respond_to do |type| - type.json { render :text => 'JSON' } + type.json { render body: 'JSON' } type.xml { render :xml => 'XML' } - type.html { render :text => 'HTML' } + type.html { render body: 'HTML' } end end @@ -48,14 +56,14 @@ class RespondToController < ActionController::Base request.format = :xml respond_to do |type| - type.html { render :text => "HTML" } - type.xml { render :text => "XML" } + type.html { render body: "HTML" } + type.xml { render body: "XML" } end end def just_xml respond_to do |type| - type.xml { render :text => "XML" } + type.xml { render body: "XML" } end end @@ -73,52 +81,52 @@ class RespondToController < ActionController::Base def using_defaults_with_all respond_to do |type| type.html - type.all{ render text: "ALL" } + type.all { render body: "ALL" } end end def made_for_content_type respond_to do |type| - type.rss { render :text => "RSS" } - type.atom { render :text => "ATOM" } - type.all { render :text => "Nothing" } + type.rss { render body: "RSS" } + type.atom { render body: "ATOM" } + type.all { render body: "Nothing" } end end def custom_type_handling respond_to do |type| - type.html { render :text => "HTML" } - type.custom("application/crazy-xml") { render :text => "Crazy XML" } - type.all { render :text => "Nothing" } + type.html { render body: "HTML" } + type.custom("application/crazy-xml") { render body: "Crazy XML" } + type.all { render body: "Nothing" } end end def custom_constant_handling respond_to do |type| - type.html { render :text => "HTML" } - type.mobile { render :text => "Mobile" } + type.html { render body: "HTML" } + type.mobile { render body: "Mobile" } end end def custom_constant_handling_without_block respond_to do |type| - type.html { render :text => "HTML" } + type.html { render body: "HTML" } type.mobile end end def handle_any respond_to do |type| - type.html { render :text => "HTML" } - type.any(:js, :xml) { render :text => "Either JS or XML" } + type.html { render body: "HTML" } + type.any(:js, :xml) { render body: "Either JS or XML" } end end def handle_any_any respond_to do |type| - type.html { render :text => 'HTML' } - type.any { render :text => 'Whatever you ask for, I got it' } + type.html { render body: 'HTML' } + type.any { render body: 'Whatever you ask for, I got it' } end end @@ -159,15 +167,15 @@ class RespondToController < ActionController::Base request.variant = :mobile respond_to do |type| - type.html { render text: "mobile" } + type.html { render body: "mobile" } end end def multiple_variants_for_format respond_to do |type| type.html do |html| - html.tablet { render text: "tablet" } - html.phone { render text: "phone" } + html.tablet { render body: "tablet" } + html.phone { render body: "phone" } end end end @@ -175,7 +183,7 @@ class RespondToController < ActionController::Base def variant_plus_none_for_format respond_to do |format| format.html do |variant| - variant.phone { render text: "phone" } + variant.phone { render body: "phone" } variant.none end end @@ -183,9 +191,9 @@ class RespondToController < ActionController::Base def variant_inline_syntax respond_to do |format| - format.js { render text: "js" } - format.html.none { render text: "none" } - format.html.phone { render text: "phone" } + format.js { render body: "js" } + format.html.none { render body: "none" } + format.html.phone { render body: "phone" } end end @@ -200,8 +208,8 @@ class RespondToController < ActionController::Base def variant_any respond_to do |format| format.html do |variant| - variant.any(:tablet, :phablet){ render text: "any" } - variant.phone { render text: "phone" } + variant.any(:tablet, :phablet){ render body: "any" } + variant.phone { render body: "phone" } end end end @@ -209,23 +217,23 @@ class RespondToController < ActionController::Base def variant_any_any respond_to do |format| format.html do |variant| - variant.any { render text: "any" } - variant.phone { render text: "phone" } + variant.any { render body: "any" } + variant.phone { render body: "phone" } end end end def variant_inline_any respond_to do |format| - format.html.any(:tablet, :phablet){ render text: "any" } - format.html.phone { render text: "phone" } + format.html.any(:tablet, :phablet){ render body: "any" } + format.html.phone { render body: "phone" } end end def variant_inline_any_any respond_to do |format| - format.html.phone { render text: "phone" } - format.html.any { render text: "any" } + format.html.phone { render body: "phone" } + format.html.any { render body: "any" } end end @@ -238,16 +246,16 @@ class RespondToController < ActionController::Base def variant_any_with_none respond_to do |format| - format.html.any(:none, :phone){ render text: "none or phone" } + format.html.any(:none, :phone){ render body: "none or phone" } end end def format_any_variant_any respond_to do |format| - format.html { render text: "HTML" } + format.html { render body: "HTML" } format.any(:js, :xml) do |variant| - variant.phone{ render text: "phone" } - variant.any(:tablet, :phablet){ render text: "tablet" } + variant.phone{ render body: "phone" } + variant.any(:tablet, :phablet){ render body: "tablet" } end end end @@ -310,17 +318,17 @@ class RespondToControllerTest < ActionController::TestCase def test_js_or_html @request.accept = "text/javascript, text/html" - xhr :get, :js_or_html + get :js_or_html, xhr: true assert_equal 'JS', @response.body @request.accept = "text/javascript, text/html" - xhr :get, :html_or_xml + get :html_or_xml, xhr: true assert_equal 'HTML', @response.body @request.accept = "text/javascript, text/html" assert_raises(ActionController::UnknownFormat) do - xhr :get, :just_xml + get :just_xml, xhr: true end end @@ -335,13 +343,13 @@ class RespondToControllerTest < ActionController::TestCase end def test_json_or_yaml - xhr :get, :json_or_yaml + get :json_or_yaml, xhr: true assert_equal 'JSON', @response.body - get :json_or_yaml, :format => 'json' + get :json_or_yaml, format: 'json' assert_equal 'JSON', @response.body - get :json_or_yaml, :format => 'yaml' + get :json_or_yaml, format: 'yaml' assert_equal 'YAML', @response.body { 'YAML' => %w(text/yaml), @@ -357,13 +365,13 @@ class RespondToControllerTest < ActionController::TestCase def test_js_or_anything @request.accept = "text/javascript, */*" - xhr :get, :js_or_html + get :js_or_html, xhr: true assert_equal 'JS', @response.body - xhr :get, :html_or_xml + get :html_or_xml, xhr: true assert_equal 'HTML', @response.body - xhr :get, :just_xml + get :just_xml, xhr: true assert_equal 'XML', @response.body end @@ -408,14 +416,14 @@ class RespondToControllerTest < ActionController::TestCase def test_with_atom_content_type @request.accept = "" @request.env["CONTENT_TYPE"] = "application/atom+xml" - xhr :get, :made_for_content_type + get :made_for_content_type, xhr: true assert_equal "ATOM", @response.body end def test_with_rss_content_type @request.accept = "" @request.env["CONTENT_TYPE"] = "application/rss+xml" - xhr :get, :made_for_content_type + get :made_for_content_type, xhr: true assert_equal "RSS", @response.body end @@ -474,7 +482,7 @@ class RespondToControllerTest < ActionController::TestCase end def test_handle_any_any_parameter_format - get :handle_any_any, {:format=>'html'} + get :handle_any_any, format: 'html' assert_equal 'HTML', @response.body end @@ -497,7 +505,7 @@ class RespondToControllerTest < ActionController::TestCase end def test_handle_any_any_unkown_format - get :handle_any_any, { format: 'php' } + get :handle_any_any, format: 'php' assert_equal 'Whatever you ask for, I got it', @response.body end @@ -525,18 +533,18 @@ class RespondToControllerTest < ActionController::TestCase end def test_xhr - xhr :get, :js_or_html + get :js_or_html, xhr: true assert_equal 'JS', @response.body end def test_custom_constant - get :custom_constant_handling, :format => "mobile" + get :custom_constant_handling, format: "mobile" assert_equal "text/x-mobile", @response.content_type assert_equal "Mobile", @response.body end def test_custom_constant_handling_without_block - get :custom_constant_handling_without_block, :format => "mobile" + get :custom_constant_handling_without_block, format: "mobile" assert_equal "text/x-mobile", @response.content_type assert_equal "Mobile", @response.body end @@ -545,13 +553,13 @@ class RespondToControllerTest < ActionController::TestCase get :html_xml_or_rss assert_equal "HTML", @response.body - get :html_xml_or_rss, :format => "html" + get :html_xml_or_rss, format: "html" assert_equal "HTML", @response.body - get :html_xml_or_rss, :format => "xml" + get :html_xml_or_rss, format: "xml" assert_equal "XML", @response.body - get :html_xml_or_rss, :format => "rss" + get :html_xml_or_rss, format: "rss" assert_equal "RSS", @response.body end @@ -559,12 +567,12 @@ class RespondToControllerTest < ActionController::TestCase get :forced_xml assert_equal "XML", @response.body - get :forced_xml, :format => "html" + get :forced_xml, format: "html" assert_equal "XML", @response.body end def test_extension_synonyms - get :html_xml_or_rss, :format => "xhtml" + get :html_xml_or_rss, format: "xhtml" assert_equal "HTML", @response.body end @@ -579,17 +587,17 @@ class RespondToControllerTest < ActionController::TestCase end get :using_defaults - assert_equal "using_defaults - #{[:html].to_s}", @response.body + assert_equal "using_defaults - #{[:html]}", @response.body - get :using_defaults, :format => "xml" - assert_equal "using_defaults - #{[:xml].to_s}", @response.body + get :using_defaults, format: "xml" + assert_equal "using_defaults - #{[:xml]}", @response.body end def test_format_with_custom_response_type get :iphone_with_html_response_type assert_equal '<html><div id="html">Hello future from Firefox!</div></html>', @response.body - get :iphone_with_html_response_type, :format => "iphone" + get :iphone_with_html_response_type, format: "iphone" assert_equal "text/html", @response.content_type assert_equal '<html><div id="iphone">Hello iPhone future from iPhone!</div></html>', @response.body end @@ -603,40 +611,45 @@ class RespondToControllerTest < ActionController::TestCase def test_invalid_format assert_raises(ActionController::UnknownFormat) do - get :using_defaults, :format => "invalidformat" + get :using_defaults, format: "invalidformat" end end def test_invalid_variant - @request.variant = :invalid - assert_raises(ActionView::MissingTemplate) do - get :variant_with_implicit_rendering - end + logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new + old_logger, ActionController::Base.logger = ActionController::Base.logger, logger + + get :variant_with_implicit_rendering, params: { v: :invalid } + assert_response :no_content + assert_equal 1, logger.logged(:info).select{ |s| s =~ /No template found/ }.size, "Implicit head :no_content not logged" + ensure + ActionController::Base.logger = old_logger end def test_variant_not_set_regular_template_missing - assert_raises(ActionView::MissingTemplate) do - get :variant_with_implicit_rendering - end + get :variant_with_implicit_rendering + assert_response :no_content end def test_variant_with_implicit_rendering - @request.variant = :mobile - get :variant_with_implicit_rendering + get :variant_with_implicit_rendering, params: { v: :implicit } + assert_response :no_content + end + + def test_variant_with_implicit_template_rendering + get :variant_with_implicit_rendering, params: { v: :mobile } assert_equal "text/html", @response.content_type assert_equal "mobile", @response.body end def test_variant_with_format_and_custom_render - @request.variant = :phone - get :variant_with_format_and_custom_render + get :variant_with_format_and_custom_render, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "mobile", @response.body end def test_multiple_variants_for_format - @request.variant = :tablet - get :multiple_variants_for_format + get :multiple_variants_for_format, params: { v: :tablet } assert_equal "text/html", @response.content_type assert_equal "tablet", @response.body end @@ -656,32 +669,27 @@ class RespondToControllerTest < ActionController::TestCase assert_equal "text/html", @response.content_type assert_equal "none", @response.body - @request.variant = :phone - get :variant_inline_syntax + get :variant_inline_syntax, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body end def test_variant_inline_syntax_without_block - @request.variant = :phone - get :variant_inline_syntax_without_block + get :variant_inline_syntax_without_block, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body end def test_variant_any - @request.variant = :phone - get :variant_any + get :variant_any, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body - @request.variant = :tablet - get :variant_any + get :variant_any, params: { v: :tablet } assert_equal "text/html", @response.content_type assert_equal "any", @response.body - @request.variant = :phablet - get :variant_any + get :variant_any, params: { v: :phablet } assert_equal "text/html", @response.content_type assert_equal "any", @response.body end @@ -691,54 +699,45 @@ class RespondToControllerTest < ActionController::TestCase assert_equal "text/html", @response.content_type assert_equal "any", @response.body - @request.variant = :phone - get :variant_any_any + get :variant_any_any, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body - @request.variant = :yolo - get :variant_any_any + get :variant_any_any, params: { v: :yolo } assert_equal "text/html", @response.content_type assert_equal "any", @response.body end def test_variant_inline_any - @request.variant = :phone - get :variant_any + get :variant_any, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body - @request.variant = :tablet - get :variant_inline_any + get :variant_inline_any, params: { v: :tablet } assert_equal "text/html", @response.content_type assert_equal "any", @response.body - @request.variant = :phablet - get :variant_inline_any + get :variant_inline_any, params: { v: :phablet } assert_equal "text/html", @response.content_type assert_equal "any", @response.body end def test_variant_inline_any_any - @request.variant = :phone - get :variant_inline_any_any + get :variant_inline_any_any, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body - @request.variant = :yolo - get :variant_inline_any_any + get :variant_inline_any_any, params: { v: :yolo } assert_equal "text/html", @response.content_type assert_equal "any", @response.body end def test_variant_any_implicit_render - @request.variant = :tablet - get :variant_any_implicit_render + get :variant_any_implicit_render, params: { v: :tablet } assert_equal "text/html", @response.content_type assert_equal "tablet", @response.body - @request.variant = :phablet - get :variant_any_implicit_render + get :variant_any_implicit_render, params: { v: :phablet } assert_equal "text/html", @response.content_type assert_equal "phablet", @response.body end @@ -748,37 +747,53 @@ class RespondToControllerTest < ActionController::TestCase assert_equal "text/html", @response.content_type assert_equal "none or phone", @response.body - @request.variant = :phone - get :variant_any_with_none + get :variant_any_with_none, params: { v: :phone } assert_equal "text/html", @response.content_type assert_equal "none or phone", @response.body end def test_format_any_variant_any - @request.variant = :tablet - get :format_any_variant_any, format: :js + get :format_any_variant_any, format: :js, params: { v: :tablet } assert_equal "text/javascript", @response.content_type assert_equal "tablet", @response.body end def test_variant_negotiation_inline_syntax - @request.variant = [:tablet, :phone] - get :variant_inline_syntax_without_block + get :variant_inline_syntax_without_block, params: { v: [:tablet, :phone] } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body end def test_variant_negotiation_block_syntax - @request.variant = [:tablet, :phone] - get :variant_plus_none_for_format + get :variant_plus_none_for_format, params: { v: [:tablet, :phone] } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body end def test_variant_negotiation_without_block - @request.variant = [:tablet, :phone] - get :variant_inline_syntax_without_block + get :variant_inline_syntax_without_block, params: { v: [:tablet, :phone] } assert_equal "text/html", @response.content_type assert_equal "phone", @response.body end end + +class RespondToWithBlockOnDefaultRenderController < ActionController::Base + def show + default_render do + render body: 'default_render yielded' + end + end +end + +class RespondToWithBlockOnDefaultRenderControllerTest < ActionController::TestCase + def setup + super + @request.host = "www.example.com" + end + + def test_default_render_uses_block_when_no_template_exists + get :show + assert_equal "default_render yielded", @response.body + assert_equal "text/plain", @response.content_type + end +end diff --git a/actionpack/test/controller/mime/responders_test.rb b/actionpack/test/controller/mime/responders_test.rb deleted file mode 100644 index 032b4c0ab1..0000000000 --- a/actionpack/test/controller/mime/responders_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'abstract_unit' -require 'controller/fake_models' - -class ResponderTest < ActionController::TestCase - def test_class_level_respond_to - e = assert_raises(NoMethodError) do - Class.new(ActionController::Base) do - respond_to :json - end - end - - assert_includes e.message, '`responders` gem' - assert_includes e.message, '~> 2.0' - end - - def test_respond_with - klass = Class.new(ActionController::Base) do - def index - respond_with Customer.new("david", 13) - end - end - - @controller = klass.new - - e = assert_raises(NoMethodError) do - get :index - end - - assert_includes e.message, '`responders` gem' - assert_includes e.message, '~> 2.0' - end -end diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index 246ba099af..e61f4d241b 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -2,8 +2,6 @@ require "abstract_unit" module BareMetalTest class BareController < ActionController::Metal - include ActionController::RackDelegation - def index self.response_body = "Hello world" end @@ -28,9 +26,18 @@ module BareMetalTest test "response_body value is wrapped in an array when the value is a String" do controller = BareController.new + controller.set_request!(ActionDispatch::Request.new({})) + controller.set_response!(BareController.make_response!(controller.request)) controller.index assert_equal ["Hello world"], controller.response_body end + + test "connect a request to controller instance without dispatch" do + env = {} + controller = BareController.new + controller.set_request! ActionDispatch::Request.new(env) + assert controller.request + end end class HeadController < ActionController::Metal @@ -114,34 +121,40 @@ module BareMetalTest end test "head :no_content (204) does not return any content" do - content = HeadController.action(:no_content).call(Rack::MockRequest.env_for("/")).third.first + content = body(HeadController.action(:no_content).call(Rack::MockRequest.env_for("/"))) assert_empty content end test "head :reset_content (205) does not return any content" do - content = HeadController.action(:reset_content).call(Rack::MockRequest.env_for("/")).third.first + content = body(HeadController.action(:reset_content).call(Rack::MockRequest.env_for("/"))) assert_empty content end test "head :not_modified (304) does not return any content" do - content = HeadController.action(:not_modified).call(Rack::MockRequest.env_for("/")).third.first + content = body(HeadController.action(:not_modified).call(Rack::MockRequest.env_for("/"))) assert_empty content end test "head :continue (100) does not return any content" do - content = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).third.first + content = body(HeadController.action(:continue).call(Rack::MockRequest.env_for("/"))) assert_empty content end test "head :switching_protocols (101) does not return any content" do - content = HeadController.action(:switching_protocols).call(Rack::MockRequest.env_for("/")).third.first + content = body(HeadController.action(:switching_protocols).call(Rack::MockRequest.env_for("/"))) assert_empty content end test "head :processing (102) does not return any content" do - content = HeadController.action(:processing).call(Rack::MockRequest.env_for("/")).third.first + content = body(HeadController.action(:processing).call(Rack::MockRequest.env_for("/"))) assert_empty content end + + def body(rack_response) + buf = [] + rack_response[2].each { |x| buf << x } + buf.join + end end class BareControllerTest < ActionController::TestCase diff --git a/actionpack/test/controller/new_base/base_test.rb b/actionpack/test/controller/new_base/base_test.rb index 964f22eb03..0755dafe93 100644 --- a/actionpack/test/controller/new_base/base_test.rb +++ b/actionpack/test/controller/new_base/base_test.rb @@ -6,7 +6,7 @@ module Dispatching before_action :authenticate def index - render :text => "success" + render body: "success" end def modify_response_body @@ -22,7 +22,7 @@ module Dispatching end def show_actions - render :text => "actions: #{action_methods.to_a.sort.join(', ')}" + render body: "actions: #{action_methods.to_a.sort.join(', ')}" end protected @@ -51,7 +51,7 @@ module Dispatching assert_body "success" assert_status 200 - assert_content_type "text/html; charset=utf-8" + assert_content_type "text/plain; charset=utf-8" end # :api: plugin diff --git a/actionpack/test/controller/new_base/content_negotiation_test.rb b/actionpack/test/controller/new_base/content_negotiation_test.rb index 5fd5946619..c0e92b3b05 100644 --- a/actionpack/test/controller/new_base/content_negotiation_test.rb +++ b/actionpack/test/controller/new_base/content_negotiation_test.rb @@ -9,18 +9,18 @@ module ContentNegotiation )] def all - render :text => self.formats.inspect + render plain: self.formats.inspect end end class TestContentNegotiation < Rack::TestCase test "A */* Accept header will return HTML" do - get "/content_negotiation/basic/hello", {}, "HTTP_ACCEPT" => "*/*" + get "/content_negotiation/basic/hello", headers: { "HTTP_ACCEPT" => "*/*" } assert_body "Hello world */*!" end test "Not all mimes are converted to symbol" do - get "/content_negotiation/basic/all", {}, "HTTP_ACCEPT" => "text/plain, mime/another" + get "/content_negotiation/basic/all", headers: { "HTTP_ACCEPT" => "text/plain, mime/another" } assert_body '[:text, "mime/another"]' end end diff --git a/actionpack/test/controller/new_base/content_type_test.rb b/actionpack/test/controller/new_base/content_type_test.rb index 9b57641e75..a9dcdde4b8 100644 --- a/actionpack/test/controller/new_base/content_type_test.rb +++ b/actionpack/test/controller/new_base/content_type_test.rb @@ -3,16 +3,16 @@ require 'abstract_unit' module ContentType class BaseController < ActionController::Base def index - render :text => "Hello world!" + render body: "Hello world!" end def set_on_response_obj - response.content_type = Mime::RSS - render :text => "Hello world!" + response.content_type = Mime[:rss] + render body: "Hello world!" end def set_on_render - render :text => "Hello world!", :content_type => Mime::RSS + render body: "Hello world!", content_type: Mime[:rss] end end @@ -30,17 +30,17 @@ module ContentType class CharsetController < ActionController::Base def set_on_response_obj response.charset = "utf-16" - render :text => "Hello world!" + render body: "Hello world!" end def set_as_nil_on_response_obj response.charset = nil - render :text => "Hello world!" + render body: "Hello world!" end end class ExplicitContentTypeTest < Rack::TestCase - test "default response is HTML and UTF8" do + test "default response is text/plain and UTF8" do with_routing do |set| set.draw do get ':controller', :action => 'index' @@ -49,7 +49,7 @@ module ContentType get "/content_type/base" assert_body "Hello world!" - assert_header "Content-Type", "text/html; charset=utf-8" + assert_header "Content-Type", "text/plain; charset=utf-8" end end @@ -76,7 +76,7 @@ module ContentType end test "sets Content-Type as application/xml when rendering *.xml.erb" do - get "/content_type/implied/i_am_xml_erb", "format" => "xml" + get "/content_type/implied/i_am_xml_erb", params: { "format" => "xml" } assert_header "Content-Type", "application/xml; charset=utf-8" end @@ -88,7 +88,7 @@ module ContentType end test "sets Content-Type as application/xml when rendering *.xml.builder" do - get "/content_type/implied/i_am_xml_builder", "format" => "xml" + get "/content_type/implied/i_am_xml_builder", params: { "format" => "xml" } assert_header "Content-Type", "application/xml; charset=utf-8" end @@ -99,14 +99,14 @@ module ContentType get "/content_type/charset/set_on_response_obj" assert_body "Hello world!" - assert_header "Content-Type", "text/html; charset=utf-16" + assert_header "Content-Type", "text/plain; charset=utf-16" end test "setting the charset of the response as nil directly on the response object" do get "/content_type/charset/set_as_nil_on_response_obj" assert_body "Hello world!" - assert_header "Content-Type", "text/html; charset=utf-8" + assert_header "Content-Type", "text/plain; charset=utf-8" end end end diff --git a/actionpack/test/controller/new_base/metal_test.rb b/actionpack/test/controller/new_base/metal_test.rb deleted file mode 100644 index 45a6619eb4..0000000000 --- a/actionpack/test/controller/new_base/metal_test.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'abstract_unit' - -module MetalTest - class MetalMiddleware < ActionController::Middleware - def call(env) - if env["PATH_INFO"] =~ /authed/ - app.call(env) - else - [401, headers, "Not authed!"] - end - end - end - - class Endpoint - def call(env) - [200, {}, "Hello World"] - end - end - - class TestMiddleware < ActiveSupport::TestCase - include RackTestUtils - - def setup - @app = Rack::Builder.new do - use MetalTest::MetalMiddleware - run MetalTest::Endpoint.new - end.to_app - end - - test "it can call the next app by using @app" do - env = Rack::MockRequest.env_for("/authed") - response = @app.call(env) - - assert_equal "Hello World", body_to_string(response[2]) - end - - test "it can return a response using the normal AC::Metal techniques" do - env = Rack::MockRequest.env_for("/") - response = @app.call(env) - - assert_equal "Not authed!", body_to_string(response[2]) - assert_equal 401, response[0] - end - end -end diff --git a/actionpack/test/controller/new_base/middleware_test.rb b/actionpack/test/controller/new_base/middleware_test.rb index 6b7b5e10e3..85a1f351f0 100644 --- a/actionpack/test/controller/new_base/middleware_test.rb +++ b/actionpack/test/controller/new_base/middleware_test.rb @@ -75,7 +75,7 @@ module MiddlewareTest test "middleware that is 'use'd is called as part of the Rack application" do result = @app.call(env_for("/")) - assert_equal "Hello World", RackTestUtils.body_to_string(result[2]) + assert_equal ["Hello World"], [].tap { |a| result[2].each { |x| a << x } } assert_equal "Success", result[1]["Middleware-Test"] end diff --git a/actionpack/test/controller/new_base/render_action_test.rb b/actionpack/test/controller/new_base/render_action_test.rb index 475bf9d3c9..3bf1dd0ede 100644 --- a/actionpack/test/controller/new_base/render_action_test.rb +++ b/actionpack/test/controller/new_base/render_action_test.rb @@ -88,7 +88,7 @@ module RenderAction test "rendering with layout => true" do assert_raise(ArgumentError) do - get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false + get "/render_action/basic/hello_world_with_layout", headers: { "action_dispatch.show_exceptions" => false } end end @@ -108,7 +108,7 @@ module RenderAction test "rendering with layout => 'greetings'" do assert_raise(ActionView::MissingTemplate) do - get "/render_action/basic/hello_world_with_custom_layout", {}, "action_dispatch.show_exceptions" => false + get "/render_action/basic/hello_world_with_custom_layout", headers: { "action_dispatch.show_exceptions" => false } end end end diff --git a/actionpack/test/controller/new_base/render_file_test.rb b/actionpack/test/controller/new_base/render_file_test.rb index a961cbf849..0c21bb0719 100644 --- a/actionpack/test/controller/new_base/render_file_test.rb +++ b/actionpack/test/controller/new_base/render_file_test.rb @@ -13,15 +13,6 @@ module RenderFile render :file => File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_ivar') end - def without_file_key - render File.join(File.dirname(__FILE__), *%w[.. .. fixtures test hello_world]) - end - - def without_file_key_with_instance_variable - @secret = 'in the sauce' - render File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_ivar') - end - def relative_path @secret = 'in the sauce' render :file => '../../fixtures/test/render_file_with_ivar' @@ -41,11 +32,6 @@ module RenderFile path = File.join(File.dirname(__FILE__), '../../fixtures/test/render_file_with_locals') render :file => path, :locals => {:secret => 'in the sauce'} end - - def without_file_key_with_locals - path = FIXTURES.join('test/render_file_with_locals').to_s - render path, :locals => {:secret => 'in the sauce'} - end end class TestBasic < Rack::TestCase @@ -61,16 +47,6 @@ module RenderFile assert_response "The secret is in the sauce\n" end - test "rendering path without specifying the :file key" do - get :without_file_key - assert_response "Hello world!" - end - - test "rendering path without specifying the :file key with ivar" do - get :without_file_key_with_instance_variable - assert_response "The secret is in the sauce\n" - end - test "rendering a relative path" do get :relative_path assert_response "The secret is in the sauce\n" @@ -90,10 +66,5 @@ module RenderFile get :with_locals assert_response "The secret is in the sauce\n" end - - test "rendering path without specifying the :file key with locals" do - get :without_file_key_with_locals - assert_response "The secret is in the sauce\n" - end end end diff --git a/actionpack/test/controller/new_base/render_html_test.rb b/actionpack/test/controller/new_base/render_html_test.rb index fe11501eeb..e9ea57e329 100644 --- a/actionpack/test/controller/new_base/render_html_test.rb +++ b/actionpack/test/controller/new_base/render_html_test.rb @@ -179,7 +179,7 @@ module RenderHtml test "rendering from minimal controller returns response with text/html content type" do get "/render_html/minimal/index" - assert_content_type "text/html" + assert_content_type "text/html; charset=utf-8" end test "rendering from normal controller returns response with text/html content type" do diff --git a/actionpack/test/controller/new_base/render_layout_test.rb b/actionpack/test/controller/new_base/render_layout_test.rb index 4ac40ca405..7ab3777026 100644 --- a/actionpack/test/controller/new_base/render_layout_test.rb +++ b/actionpack/test/controller/new_base/render_layout_test.rb @@ -86,7 +86,7 @@ module ControllerLayouts XML_INSTRUCT = %Q(<?xml version="1.0" encoding="UTF-8"?>\n) test "if XML is selected, an HTML template is not also selected" do - get :index, :format => "xml" + get :index, params: { format: "xml" } assert_response XML_INSTRUCT end @@ -96,7 +96,7 @@ module ControllerLayouts end test "a layout for JS is ignored even if explicitly provided for HTML" do - get :explicit, { :format => "js" } + get :explicit, params: { format: "js" } assert_response "alert('foo');" end end @@ -120,7 +120,7 @@ module ControllerLayouts testing ControllerLayouts::FalseLayoutMethodController test "access false layout returned by a method/proc" do - get :index, :format => "js" + get :index, params: { format: "js" } assert_response "alert('foo');" 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 0e36d36b50..0881442bd0 100644 --- a/actionpack/test/controller/new_base/render_plain_test.rb +++ b/actionpack/test/controller/new_base/render_plain_test.rb @@ -157,7 +157,7 @@ module RenderPlain test "rendering from minimal controller returns response with text/plain content type" do get "/render_plain/minimal/index" - assert_content_type "text/plain" + assert_content_type "text/plain; charset=utf-8" end test "rendering from normal controller returns response with text/plain content type" do diff --git a/actionpack/test/controller/new_base/render_streaming_test.rb b/actionpack/test/controller/new_base/render_streaming_test.rb index 4c9126ca8c..9ea056194a 100644 --- a/actionpack/test/controller/new_base/render_streaming_test.rb +++ b/actionpack/test/controller/new_base/render_streaming_test.rb @@ -97,7 +97,7 @@ module RenderStreaming end test "do not stream on HTTP/1.0" do - get "/render_streaming/basic/hello_world", nil, "HTTP_VERSION" => "HTTP/1.0" + get "/render_streaming/basic/hello_world", headers: { "HTTP_VERSION" => "HTTP/1.0" } assert_body "Hello world, I'm here!" assert_status 200 assert_equal "22", headers["Content-Length"] diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index e87811776a..b06ce5db40 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -45,6 +45,10 @@ module RenderTemplate render :template => "locals", :locals => { :secret => 'area51' } end + def with_locals_without_key + render "locals", :locals => { :secret => 'area51' } + end + def builder_template render :template => "xml_template" end @@ -101,8 +105,13 @@ module RenderTemplate assert_response "The secret is area51" end + test "rendering a template with local variables without key" do + get :with_locals + assert_response "The secret is area51" + end + test "rendering a builder template" do - get :builder_template, "format" => "xml" + get :builder_template, params: { "format" => "xml" } assert_response "<html>\n <p>Hello</p>\n</html>\n" end @@ -117,7 +126,7 @@ module RenderTemplate assert_body "Hello <strong>this is also raw</strong> in an html template" assert_status 200 - get :with_implicit_raw, format: 'text' + get :with_implicit_raw, params: { format: 'text' } assert_body "Hello <strong>this is also raw</strong> in a text template" assert_status 200 @@ -177,21 +186,21 @@ module RenderTemplate end end - test "rendering with layout => :true" do + test "rendering with layout => true" do get "/render_template/with_layout/with_layout" assert_body "Hello from basic.html.erb, I'm here!" assert_status 200 end - test "rendering with layout => :false" do + test "rendering with layout => false" do get "/render_template/with_layout/with_layout_false" assert_body "Hello from basic.html.erb" assert_status 200 end - test "rendering with layout => :nil" do + test "rendering with layout => nil" do get "/render_template/with_layout/with_layout_nil" assert_body "Hello from basic.html.erb" diff --git a/actionpack/test/controller/new_base/render_test.rb b/actionpack/test/controller/new_base/render_test.rb index 5635e16234..963f2c2f5c 100644 --- a/actionpack/test/controller/new_base/render_test.rb +++ b/actionpack/test/controller/new_base/render_test.rb @@ -37,14 +37,14 @@ module Render private def secretz - render :text => "FAIL WHALE!" + render plain: "FAIL WHALE!" end end class DoubleRenderController < ActionController::Base def index - render :text => "hello" - render :text => "world" + render plain: "hello" + render plain: "world" end end @@ -74,7 +74,7 @@ module Render end assert_raises(AbstractController::DoubleRenderError) do - get "/render/double_render", {}, "action_dispatch.show_exceptions" => false + get "/render/double_render", headers: { "action_dispatch.show_exceptions" => false } end end end @@ -84,13 +84,13 @@ module Render # Only public methods on actual controllers are callable actions test "raises an exception when a method of Object is called" do assert_raises(AbstractController::ActionNotFound) do - get "/render/blank_render/clone", {}, "action_dispatch.show_exceptions" => false + get "/render/blank_render/clone", headers: { "action_dispatch.show_exceptions" => false } end end test "raises an exception when a private method is called" do assert_raises(AbstractController::ActionNotFound) do - get "/render/blank_render/secretz", {}, "action_dispatch.show_exceptions" => false + get "/render/blank_render/secretz", headers: { "action_dispatch.show_exceptions" => false } end end end diff --git a/actionpack/test/controller/new_base/render_text_test.rb b/actionpack/test/controller/new_base/render_text_test.rb index 10bad57cd6..048458178c 100644 --- a/actionpack/test/controller/new_base/render_text_test.rb +++ b/actionpack/test/controller/new_base/render_text_test.rb @@ -73,7 +73,10 @@ module RenderText class RenderTextTest < Rack::TestCase test "rendering text from a minimal controller" do - get "/render_text/minimal/index" + ActiveSupport::Deprecation.silence do + get "/render_text/minimal/index" + end + assert_body "Hello World!" assert_status 200 end @@ -82,7 +85,10 @@ module RenderText with_routing do |set| set.draw { get ':controller', action: 'index' } - get "/render_text/simple" + ActiveSupport::Deprecation.silence do + get "/render_text/simple" + end + assert_body "hello david" assert_status 200 end @@ -92,7 +98,9 @@ module RenderText with_routing do |set| set.draw { get ':controller', action: 'index' } - get "/render_text/with_layout" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout" + end assert_body "hello david" assert_status 200 @@ -100,59 +108,81 @@ module RenderText end test "rendering text, while also providing a custom status code" do - get "/render_text/with_layout/custom_code" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/custom_code" + end assert_body "hello world" assert_status 404 end test "rendering text with nil returns an empty body" do - get "/render_text/with_layout/with_nil" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_nil" + end assert_body "" assert_status 200 end 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" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_nil_and_status" + end assert_body "" assert_status 403 end test "rendering text with false returns the string 'false'" do - get "/render_text/with_layout/with_false" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_false" + end assert_body "false" assert_status 200 end test "rendering text with layout: true" do - get "/render_text/with_layout/with_layout_true" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_layout_true" + end assert_body "hello world, I'm here!" assert_status 200 end test "rendering text with layout: 'greetings'" do - get "/render_text/with_layout/with_custom_layout" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_custom_layout" + end assert_body "hello world, I wish thee well." assert_status 200 end test "rendering text with layout: false" do - get "/render_text/with_layout/with_layout_false" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_layout_false" + end assert_body "hello world" assert_status 200 end test "rendering text with layout: nil" do - get "/render_text/with_layout/with_layout_nil" + ActiveSupport::Deprecation.silence do + get "/render_text/with_layout/with_layout_nil" + end assert_body "hello world" assert_status 200 end + + test "rendering text displays deprecation warning" do + assert_deprecated do + get "/render_text/with_layout/with_layout_nil" + end + end end end diff --git a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb index 059f310d49..efaf8a96c3 100644 --- a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb +++ b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb @@ -14,7 +14,13 @@ class AlwaysPermittedParametersTest < ActiveSupport::TestCase test "shows deprecations warning on NEVER_UNPERMITTED_PARAMS" do assert_deprecated do - ActionController::Parameters::NEVER_UNPERMITTED_PARAMS + ActionController::Parameters::NEVER_UNPERMITTED_PARAMS + end + end + + test "returns super on missing constant other than NEVER_UNPERMITTED_PARAMS" do + ActionController::Parameters.superclass.stub :const_missing, "super" do + assert_equal "super", ActionController::Parameters::NON_EXISTING_CONSTANT end end diff --git a/actionpack/test/controller/parameters/nested_parameters_test.rb b/actionpack/test/controller/parameters/nested_parameters_test.rb index 3b1257e8d5..7151a8567c 100644 --- a/actionpack/test/controller/parameters/nested_parameters_test.rb +++ b/actionpack/test/controller/parameters/nested_parameters_test.rb @@ -136,7 +136,7 @@ class NestedParametersTest < ActiveSupport::TestCase authors_attributes: { :'0' => { name: 'William Shakespeare', age_of_death: '52' }, :'1' => { name: 'Unattributed Assistant' }, - :'2' => { name: %w(injected names)} + :'2' => { name: %w(injected names) } } } }) diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb index ba98ad7605..9f7d14e85d 100644 --- a/actionpack/test/controller/parameters/parameters_permit_test.rb +++ b/actionpack/test/controller/parameters/parameters_permit_test.rb @@ -194,6 +194,19 @@ class ParametersPermitTest < ActiveSupport::TestCase assert_equal "monkey", @params.fetch(:foo) { "monkey" } end + test "fetch doesnt raise ParameterMissing exception if there is a default that is nil" do + assert_equal nil, @params.fetch(:foo, nil) + assert_equal nil, @params.fetch(:foo) { nil } + end + + test 'KeyError in fetch block should not be covered up' do + params = ActionController::Parameters.new + e = assert_raises(KeyError) do + params.fetch(:missing_key) { {}.fetch(:also_missing) } + end + assert_match(/:also_missing$/, e.message) + end + test "not permitted is sticky beyond merges" do assert !@params.merge(a: "b").permitted? end @@ -253,7 +266,6 @@ class ParametersPermitTest < ActiveSupport::TestCase assert @params.to_h.is_a? Hash assert_not @params.to_h.is_a? ActionController::Parameters - assert_equal @params.to_hash, @params.to_h end test "to_h returns converted hash when .permit_all_parameters is set" do @@ -280,4 +292,9 @@ class ParametersPermitTest < ActiveSupport::TestCase assert_equal({ "controller" => "users", "action" => "create" }, params.to_h) end + + test "to_unsafe_h returns unfiltered params" do + assert @params.to_h.is_a? Hash + assert_not @params.to_h.is_a? ActionController::Parameters + end end diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index 645ecae220..7226beed26 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -28,8 +28,17 @@ class ParamsWrapperTest < ActionController::TestCase end end - class User; end - class Person; end + class User + def self.attribute_names + [] + end + end + + class Person + def self.attribute_names + [] + end + end tests UsersController @@ -40,7 +49,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_filtered_parameters with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_equal @request.filtered_parameters, { 'controller' => 'params_wrapper_test/users', 'action' => 'parse', 'username' => 'sikachu', 'user' => { 'username' => 'sikachu' } } end end @@ -48,7 +57,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_derived_name_from_controller with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_parameters({ 'username' => 'sikachu', 'user' => { 'username' => 'sikachu' }}) end end @@ -58,7 +67,7 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.wrap_parameters :person @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_parameters({ 'username' => 'sikachu', 'person' => { 'username' => 'sikachu' }}) end end @@ -68,7 +77,7 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.wrap_parameters Person @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_parameters({ 'username' => 'sikachu', 'person' => { 'username' => 'sikachu' }}) end end @@ -78,7 +87,7 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.wrap_parameters :include => :username @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) end end @@ -88,7 +97,7 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.wrap_parameters :exclude => :title @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) end end @@ -98,7 +107,7 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.wrap_parameters :person, :include => :username @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) end end @@ -106,7 +115,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_not_enabled_format with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/xml' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer' }) end end @@ -115,7 +124,7 @@ class ParamsWrapperTest < ActionController::TestCase with_default_wrapper_options do UsersController.wrap_parameters false @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer' }) end end @@ -125,7 +134,7 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.wrap_parameters :format => :xml @request.env['CONTENT_TYPE'] = 'application/xml' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu', 'title' => 'Developer' }}) end end @@ -133,7 +142,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_not_wrap_reserved_parameters with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'authenticity_token' => 'pwned', '_method' => 'put', 'utf8' => '☃', 'username' => 'sikachu' } + post :parse, params: { 'authenticity_token' => 'pwned', '_method' => 'put', 'utf8' => '☃', 'username' => 'sikachu' } assert_parameters({ 'authenticity_token' => 'pwned', '_method' => 'put', 'utf8' => '☃', 'username' => 'sikachu', 'user' => { 'username' => 'sikachu' }}) end end @@ -141,7 +150,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_no_double_wrap_if_key_exists with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'user' => { 'username' => 'sikachu' }} + post :parse, params: { 'user' => { 'username' => 'sikachu' }} assert_parameters({ 'user' => { 'username' => 'sikachu' }}) end end @@ -149,42 +158,37 @@ class ParamsWrapperTest < ActionController::TestCase def test_nested_params with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'person' => { 'username' => 'sikachu' }} + post :parse, params: { 'person' => { 'username' => 'sikachu' }} assert_parameters({ 'person' => { 'username' => 'sikachu' }, 'user' => {'person' => { 'username' => 'sikachu' }}}) end end def test_derived_wrapped_keys_from_matching_model - User.expects(:respond_to?).with(:attribute_names).returns(true) - User.expects(:attribute_names).twice.returns(["username"]) - - with_default_wrapper_options do - @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } - assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) + assert_called(User, :attribute_names, times: 2, returns: ["username"]) do + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) + end end end def test_derived_wrapped_keys_from_specified_model with_default_wrapper_options do - Person.expects(:respond_to?).with(:attribute_names).returns(true) - Person.expects(:attribute_names).twice.returns(["username"]) - - UsersController.wrap_parameters Person + assert_called(Person, :attribute_names, times: 2, returns: ["username"]) do + UsersController.wrap_parameters Person - @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } - assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) + end end end def test_not_wrapping_abstract_model - User.expects(:respond_to?).with(:attribute_names).returns(true) - User.expects(:attribute_names).returns([]) - with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu', 'title' => 'Developer' }}) end end @@ -192,7 +196,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_preserves_query_string_params with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - get :parse, { 'user' => { 'username' => 'nixon' } } + get :parse, params: { 'user' => { 'username' => 'nixon' } } assert_parameters( {'user' => { 'username' => 'nixon' } } ) @@ -202,7 +206,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_empty_parameter_set with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, {} + post :parse, params: {} assert_parameters( {'user' => { } } ) @@ -249,7 +253,7 @@ class NamespacedParamsWrapperTest < ActionController::TestCase def test_derived_name_from_controller with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_parameters({'username' => 'sikachu', 'user' => { 'username' => 'sikachu' }}) end end @@ -259,7 +263,7 @@ class NamespacedParamsWrapperTest < ActionController::TestCase begin with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) end ensure @@ -272,7 +276,7 @@ class NamespacedParamsWrapperTest < ActionController::TestCase begin with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + post :parse, params: { 'username' => 'sikachu', 'title' => 'Developer' } assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'title' => 'Developer' }}) end ensure @@ -299,7 +303,7 @@ class AnonymousControllerParamsWrapperTest < ActionController::TestCase def test_does_not_implicitly_wrap_params with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_parameters({ 'username' => 'sikachu' }) end end @@ -308,7 +312,7 @@ class AnonymousControllerParamsWrapperTest < ActionController::TestCase with_default_wrapper_options do @controller.class.wrap_parameters(:name => "guest") @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu' } + post :parse, params: { 'username' => 'sikachu' } assert_parameters({ 'username' => 'sikachu', 'guest' => { 'username' => 'sikachu' }}) end end @@ -344,7 +348,7 @@ class IrregularInflectionParamsWrapperTest < ActionController::TestCase with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'test_attr' => 'test_value' } + post :parse, params: { 'username' => 'sikachu', 'test_attr' => 'test_value' } assert_parameters({ 'username' => 'sikachu', 'test_attr' => 'test_value', 'paramswrappernews_item' => { 'test_attr' => 'test_value' }}) end end diff --git a/actionpack/test/controller/permitted_params_test.rb b/actionpack/test/controller/permitted_params_test.rb index f46249d712..7c753a45a5 100644 --- a/actionpack/test/controller/permitted_params_test.rb +++ b/actionpack/test/controller/permitted_params_test.rb @@ -2,11 +2,11 @@ require 'abstract_unit' class PeopleController < ActionController::Base def create - render text: params[:person].permitted? ? "permitted" : "forbidden" + render plain: params[:person].permitted? ? "permitted" : "forbidden" end def create_with_permit - render text: params[:person].permit(:name).permitted? ? "permitted" : "forbidden" + render plain: params[:person].permit(:name).permitted? ? "permitted" : "forbidden" end end @@ -14,12 +14,12 @@ class ActionControllerPermittedParamsTest < ActionController::TestCase tests PeopleController test "parameters are forbidden" do - post :create, { person: { name: "Mjallo!" } } + post :create, params: { person: { name: "Mjallo!" } } assert_equal "forbidden", response.body end test "parameters can be permitted and are then not forbidden" do - post :create_with_permit, { person: { name: "Mjallo!" } } + post :create_with_permit, params: { person: { name: "Mjallo!" } } assert_equal "permitted", response.body end end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 103ca9c776..631ff7d02a 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -1,13 +1,10 @@ require 'abstract_unit' -class WorkshopsController < ActionController::Base -end - class RedirectController < ActionController::Base # empty method not used anywhere to ensure methods like # `status` and `location` aren't called on `redirect_to` calls - def status; render :text => 'called status'; end - def location; render :text => 'called location'; end + def status; render plain: 'called status'; end + def location; render plain: 'called location'; end def simple_redirect redirect_to :action => "hello_world" @@ -53,17 +50,12 @@ class RedirectController < ActionController::Base redirect_to :controller => 'module_test/module_redirect', :action => "hello_world" end - def redirect_with_assigns - @hello = "world" - redirect_to :action => "hello_world" - end - def redirect_to_url redirect_to "http://www.rubyonrails.org/" end def redirect_to_url_with_unescaped_query_string - redirect_to "http://dev.rubyonrails.org/query?status=new" + redirect_to "http://example.com/query?status=new" end def redirect_to_url_with_complex_scheme @@ -218,12 +210,6 @@ class RedirectTest < ActionController::TestCase assert_redirected_to :controller => 'module_test/module_redirect', :action => 'hello_world' end - def test_redirect_with_assigns - get :redirect_with_assigns - assert_response :redirect - assert_equal "world", assigns["hello"] - end - def test_redirect_to_url get :redirect_to_url assert_response :redirect @@ -233,7 +219,7 @@ class RedirectTest < ActionController::TestCase def test_redirect_to_url_with_unescaped_query_string get :redirect_to_url_with_unescaped_query_string assert_response :redirect - assert_redirected_to "http://dev.rubyonrails.org/query?status=new" + assert_redirected_to "http://example.com/query?status=new" end def test_redirect_to_url_with_complex_scheme @@ -280,15 +266,17 @@ class RedirectTest < ActionController::TestCase end def test_redirect_to_nil - assert_raise(ActionController::ActionControllerError) do + error = assert_raise(ActionController::ActionControllerError) do get :redirect_to_nil end + assert_equal "Cannot redirect to nil!", error.message end def test_redirect_to_params - assert_raise(ActionController::ActionControllerError) do + error = assert_raise(ActionController::ActionControllerError) do get :redirect_to_params end + assert_equal "Cannot redirect to a parameter hash!", error.message end def test_redirect_to_with_block diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb index d550422a2f..6b661de064 100644 --- a/actionpack/test/controller/render_js_test.rb +++ b/actionpack/test/controller/render_js_test.rb @@ -22,13 +22,13 @@ class RenderJSTest < ActionController::TestCase tests TestController def test_render_vanilla_js - xhr :get, :render_vanilla_js_hello + get :render_vanilla_js_hello, xhr: true assert_equal "alert('hello')", @response.body assert_equal "text/javascript", @response.content_type end def test_should_render_js_partial - xhr :get, :show_partial, :format => 'js' + get :show_partial, format: 'js', xhr: true assert_equal 'partial js', @response.body end end diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index ada978aa11..3773900cc4 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -28,7 +28,7 @@ class RenderJsonTest < ActionController::TestCase end def render_json_render_to_string - render :text => render_to_string(:json => '[]') + render plain: render_to_string(json: '[]') end def render_json_hello_world @@ -100,13 +100,13 @@ class RenderJsonTest < ActionController::TestCase end def test_render_json_with_callback - xhr :get, :render_json_hello_world_with_callback + get :render_json_hello_world_with_callback, xhr: true assert_equal '/**/alert({"hello":"world"})', @response.body assert_equal 'text/javascript', @response.content_type end def test_render_json_with_custom_content_type - xhr :get, :render_json_with_custom_content_type + get :render_json_with_custom_content_type, xhr: true assert_equal '{"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 af50e11261..1f5215ac55 100644 --- a/actionpack/test/controller/render_other_test.rb +++ b/actionpack/test/controller/render_other_test.rb @@ -12,7 +12,7 @@ class RenderOtherTest < ActionController::TestCase def test_using_custom_render_option ActionController.add_renderer :simon do |says, options| - self.content_type = Mime::TEXT + self.content_type = Mime[:text] self.response_body = "Simon says: #{says}" end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index b036b6c08e..256ebf6a07 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'controller/fake_models' -require 'pathname' class TestControllerWithExtraEtags < ActionController::Base etag { nil } @@ -10,20 +9,25 @@ class TestControllerWithExtraEtags < ActionController::Base etag { nil } def fresh - render text: "stale" if stale?(etag: '123', template: false) + render plain: "stale" if stale?(etag: '123', template: false) end def array - render text: "stale" if stale?(etag: %w(1 2 3), template: false) + render plain: "stale" if stale?(etag: %w(1 2 3), template: false) end def with_template if stale? template: 'test/hello_world' - render text: 'stale' + render plain: 'stale' end end end +class ImplicitRenderTestController < ActionController::Base + def empty_action + end +end + class TestController < ActionController::Base protect_from_forgery @@ -58,24 +62,24 @@ class TestController < ActionController::Base end end - def conditional_hello_with_public_header - if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) - render :action => 'hello_world' + class Collection + def initialize(records) + @records = records end - end - - def conditional_hello_with_public_header_with_record - record = Struct.new(:updated_at, :cache_key).new(Time.now.utc.beginning_of_day, "foo/123") - if stale?(record, :public => true) - render :action => 'hello_world' + def maximum(attribute) + @records.max_by(&attribute).public_send(attribute) end end - def conditional_hello_with_public_header_and_expires_at - expires_in 1.minute - if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) - render :action => 'hello_world' + def conditional_hello_with_collection_of_records + ts = Time.now.utc.beginning_of_day + + record = Struct.new(:updated_at, :cache_key).new(ts, "foo/123") + old_record = Struct.new(:updated_at, :cache_key).new(ts - 1.day, "bar/123") + + if stale?(Collection.new([record, old_record])) + render action: 'hello_world' end end @@ -120,6 +124,10 @@ class TestController < ActionController::Base render :action => 'hello_world' end + def respond_with_empty_body + render nothing: true + end + def conditional_hello_with_bangs render :action => 'hello_world' end @@ -129,48 +137,12 @@ class TestController < ActionController::Base fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ]) end - def heading - head :ok + def head_with_status_hash + head status: :created end - # :ported: - def double_render - render :text => "hello" - render :text => "world" - end - - def double_redirect - redirect_to :action => "double_render" - redirect_to :action => "double_render" - end - - def render_and_redirect - render :text => "hello" - redirect_to :action => "double_render" - end - - def render_to_string_and_render - @stuff = render_to_string :text => "here is some cached stuff" - render :text => "Hi web users! #{@stuff}" - end - - def render_to_string_with_inline_and_render - render_to_string :inline => "<%= 'dlrow olleh'.reverse %>" - render :template => "test/hello_world" - end - - def rendering_with_conflicting_local_vars - @name = "David" - render :action => "potential_conflicts" - end - - def hello_world_from_rxml_using_action - render :action => "hello_world_from_rxml", :handlers => [:builder] - end - - # :deprecated: - def hello_world_from_rxml_using_template - render :template => "test/hello_world_from_rxml", :handlers => [:builder] + def head_with_hash_does_not_include_status + head warning: :deprecated end def head_created @@ -186,37 +158,51 @@ class TestController < ActionController::Base end def head_with_location_header - head :location => "/foo" + head :ok, :location => "/foo" end def head_with_location_object - head :location => Customer.new("david", 1) + head :ok, :location => Customer.new("david", 1) end def head_with_symbolic_status - head :status => params[:status].intern + head params[:status].intern end def head_with_integer_status - head :status => params[:status].to_i + head params[:status].to_i end def head_with_string_status - head :status => params[:status] + head params[:status] end def head_with_custom_header - head :x_custom_header => "something" + head :ok, :x_custom_header => "something" end def head_with_www_authenticate_header - head 'WWW-Authenticate' => 'something' + head :ok, 'WWW-Authenticate' => 'something' end def head_with_status_code_first head :forbidden, :x_custom_header => "something" end + def head_and_return + head :ok and return + raise 'should not reach this line' + end + + def head_with_no_content + # Fill in the headers with dummy data to make + # sure they get removed during the testing + response.headers["Content-Type"] = "dummy" + response.headers["Content-Length"] = 42 + + head 204 + end + private def set_variable_for_layout @@ -248,8 +234,6 @@ 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 %>" @@ -300,11 +284,18 @@ class ExpiresInRenderTest < ActionController::TestCase assert_match(/no-transform/, @response.headers["Cache-Control"]) end + def test_render_nothing_deprecated + assert_deprecated do + get :respond_with_empty_body + end + end + def test_date_header_when_expires_in time = Time.mktime(2011,10,30) - Time.stubs(:now).returns(time) - get :conditional_hello_with_expires_in - assert_equal Time.now.httpdate, @response.headers["Date"] + Time.stub :now, time do + get :conditional_hello_with_expires_in + assert_equal Time.now.httpdate, @response.headers["Date"] + end end end @@ -344,7 +335,6 @@ class LastModifiedRenderTest < ActionController::TestCase assert_equal @last_modified, @response.headers['Last-Modified'] end - def test_responds_with_last_modified_with_record get :conditional_hello_with_record assert_equal @last_modified, @response.headers['Last-Modified'] @@ -355,6 +345,7 @@ class LastModifiedRenderTest < ActionController::TestCase get :conditional_hello_with_record assert_equal 304, @response.status.to_i assert @response.body.blank? + assert_not_nil @response.etag assert_equal @last_modified, @response.headers['Last-Modified'] end @@ -373,6 +364,34 @@ class LastModifiedRenderTest < ActionController::TestCase assert_equal @last_modified, @response.headers['Last-Modified'] end + def test_responds_with_last_modified_with_collection_of_records + get :conditional_hello_with_collection_of_records + assert_equal @last_modified, @response.headers['Last-Modified'] + end + + def test_request_not_modified_with_collection_of_records + @request.if_modified_since = @last_modified + get :conditional_hello_with_collection_of_records + assert_equal 304, @response.status.to_i + assert @response.body.blank? + assert_equal @last_modified, @response.headers['Last-Modified'] + end + + def test_request_not_modified_but_etag_differs_with_collection_of_records + @request.if_modified_since = @last_modified + @request.if_none_match = "234" + get :conditional_hello_with_collection_of_records + assert_response :success + end + + def test_request_modified_with_collection_of_records + @request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT' + get :conditional_hello_with_collection_of_records + assert_equal 200, @response.status.to_i + assert @response.body.present? + assert_equal @last_modified, @response.headers['Last-Modified'] + end + def test_request_with_bang_gets_last_modified get :conditional_hello_with_bangs assert_equal @last_modified, @response.headers['Last-Modified'] @@ -455,6 +474,15 @@ class MetalRenderTest < ActionController::TestCase end end +class ImplicitRenderTest < ActionController::TestCase + tests ImplicitRenderTestController + + def test_implicit_no_content_response + get :empty_action + assert_response :no_content + end +end + class HeadRenderTest < ActionController::TestCase tests TestController @@ -468,6 +496,19 @@ class HeadRenderTest < ActionController::TestCase assert_response :created end + def test_passing_hash_to_head_as_first_parameter_deprecated + assert_deprecated do + get :head_with_status_hash + end + end + + def test_head_with_default_value_is_deprecated + assert_deprecated do + get :head_with_hash_does_not_include_status + assert_response :ok + end + end + def test_head_created_with_application_json_content_type post :head_created_with_application_json_content_type assert @response.body.blank? @@ -518,21 +559,21 @@ class HeadRenderTest < ActionController::TestCase end def test_head_with_symbolic_status - get :head_with_symbolic_status, :status => "ok" + get :head_with_symbolic_status, params: { status: "ok" } assert_equal 200, @response.status assert_response :ok - get :head_with_symbolic_status, :status => "not_found" + get :head_with_symbolic_status, params: { status: "not_found" } assert_equal 404, @response.status assert_response :not_found - get :head_with_symbolic_status, :status => "no_content" + get :head_with_symbolic_status, params: { status: "no_content" } assert_equal 204, @response.status assert !@response.headers.include?('Content-Length') assert_response :no_content Rack::Utils::SYMBOL_TO_STATUS_CODE.each do |status, code| - get :head_with_symbolic_status, :status => status.to_s + get :head_with_symbolic_status, params: { status: status.to_s } assert_equal code, @response.response_code assert_response status end @@ -540,13 +581,21 @@ class HeadRenderTest < ActionController::TestCase def test_head_with_integer_status Rack::Utils::HTTP_STATUS_CODES.each do |code, message| - get :head_with_integer_status, :status => code.to_s + get :head_with_integer_status, params: { status: code.to_s } assert_equal message, @response.message end end + def test_head_with_no_content + get :head_with_no_content + + assert_equal 204, @response.status + assert_nil @response.headers["Content-Type"] + assert_nil @response.headers["Content-Length"] + end + def test_head_with_string_status - get :head_with_string_status, :status => "404 Eat Dirt" + get :head_with_string_status, params: { status: "404 Eat Dirt" } assert_equal 404, @response.response_code assert_equal "Not Found", @response.message assert_response :not_found @@ -559,4 +608,63 @@ class HeadRenderTest < ActionController::TestCase assert_equal "something", @response.headers["X-Custom-Header"] assert_response :forbidden end + + def test_head_returns_truthy_value + assert_nothing_raised do + get :head_and_return + end + end +end + +class HttpCacheForeverTest < ActionController::TestCase + class HttpCacheForeverController < ActionController::Base + def cache_me_forever + http_cache_forever(public: params[:public], version: params[:version] || 'v1') do + render plain: 'hello' + end + end + end + + tests HttpCacheForeverController + + def test_cache_with_public + get :cache_me_forever, params: {public: true} + assert_equal "max-age=#{100.years}, public", @response.headers["Cache-Control"] + assert_not_nil @response.etag + end + + def test_cache_with_private + get :cache_me_forever + assert_equal "max-age=#{100.years}, private", @response.headers["Cache-Control"] + assert_not_nil @response.etag + assert_response :success + end + + def test_cache_response_code_with_if_modified_since + get :cache_me_forever + assert_response :success + @request.if_modified_since = @response.headers['Last-Modified'] + get :cache_me_forever + assert_response :not_modified + end + + def test_cache_response_code_with_etag + get :cache_me_forever + assert_response :success + @request.if_modified_since = @response.headers['Last-Modified'] + @request.if_none_match = @response.etag + + get :cache_me_forever + assert_response :not_modified + @request.if_modified_since = @response.headers['Last-Modified'] + @request.if_none_match = @response.etag + + get :cache_me_forever, params: {version: 'v2'} + assert_response :success + @request.if_modified_since = @response.headers['Last-Modified'] + @request.if_none_match = @response.etag + + get :cache_me_forever, params: {version: 'v2'} + assert_response :not_modified + end end diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index 4f280c4bec..f0fd7ddc5e 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -81,7 +81,7 @@ class RenderXmlTest < ActionController::TestCase end def test_should_render_formatted_xml_erb_template - get :formatted_xml_erb, :format => :xml + get :formatted_xml_erb, format: :xml assert_equal '<test>passed formatted xml erb</test>', @response.body end @@ -91,7 +91,7 @@ class RenderXmlTest < ActionController::TestCase end def test_should_use_implicit_content_type - get :implicit_content_type, :format => 'atom' - assert_equal Mime::ATOM, @response.content_type + get :implicit_content_type, format: 'atom' + assert_equal Mime[:atom], @response.content_type end end diff --git a/actionpack/test/controller/renderer_test.rb b/actionpack/test/controller/renderer_test.rb new file mode 100644 index 0000000000..16d24fa82a --- /dev/null +++ b/actionpack/test/controller/renderer_test.rb @@ -0,0 +1,94 @@ +require 'abstract_unit' + +class RendererTest < ActiveSupport::TestCase + test 'action controller base has a renderer' do + assert ActionController::Base.renderer + end + + test 'creating with a controller' do + controller = CommentsController + renderer = ActionController::Renderer.for controller + + assert_equal controller, renderer.controller + end + + test 'creating from a controller' do + controller = AccountsController + renderer = controller.renderer + + assert_equal controller, renderer.controller + end + + test 'rendering with a class renderer' do + renderer = ApplicationController.renderer + content = renderer.render template: 'ruby_template' + + assert_equal 'Hello from Ruby code', content + end + + test 'rendering with an instance renderer' do + renderer = ApplicationController.renderer.new + content = renderer.render file: 'test/hello_world' + + assert_equal 'Hello world!', content + end + + test 'rendering with a controller class' do + assert_equal 'Hello world!', ApplicationController.render('test/hello_world') + end + + test 'rendering with locals' do + renderer = ApplicationController.renderer + content = renderer.render template: 'test/render_file_with_locals', + locals: { secret: 'bar' } + + assert_equal "The secret is bar\n", content + end + + test 'rendering with assigns' do + renderer = ApplicationController.renderer + content = renderer.render template: 'test/render_file_with_ivar', + assigns: { secret: 'foo' } + + assert_equal "The secret is foo\n", content + end + + test 'rendering with custom env' do + renderer = ApplicationController.renderer.new method: 'post' + content = renderer.render inline: '<%= request.post? %>' + + assert_equal 'true', content + end + + test 'rendering with defaults' do + renderer = ApplicationController.renderer.new https: true + content = renderer.render inline: '<%= request.ssl? %>' + + assert_equal 'true', content + end + + test 'same defaults from the same controller' do + renderer_defaults = ->(controller) { controller.renderer.defaults } + + assert_equal renderer_defaults[AccountsController], renderer_defaults[AccountsController] + assert_equal renderer_defaults[AccountsController], renderer_defaults[CommentsController] + end + + test 'rendering with different formats' do + html = 'Hello world!' + xml = "<p>Hello world!</p>\n" + + assert_equal html, render['respond_to/using_defaults'] + assert_equal xml, render['respond_to/using_defaults.xml.builder'] + assert_equal xml, render['respond_to/using_defaults', formats: :xml] + end + + test 'rendering with helpers' do + assert_equal "<p>1\n<br />2</p>", render[inline: '<%= simple_format "1\n2" %>'] + end + + private + def render + @render ||= ApplicationController.renderer.method(:render) + end +end diff --git a/actionpack/test/controller/request/test_request_test.rb b/actionpack/test/controller/request/test_request_test.rb index e624f11773..e5d698d5c2 100644 --- a/actionpack/test/controller/request/test_request_test.rb +++ b/actionpack/test/controller/request/test_request_test.rb @@ -1,11 +1,7 @@ require 'abstract_unit' require 'stringio' -class ActionController::TestRequestTest < ActiveSupport::TestCase - - def setup - @request = ActionController::TestRequest.new - end +class ActionController::TestRequestTest < ActionController::TestCase def test_test_request_has_session_options_initialized assert @request.session_options @@ -24,12 +20,4 @@ class ActionController::TestRequestTest < ActiveSupport::TestCase end end - def test_session_id_exists_by_default - assert_not_nil(@request.session_options[:id]) - end - - def test_session_id_different_on_each_call - assert_not_equal(@request.session_options[:id], ActionController::TestRequest.new.session_options[:id]) - end - end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 3e0bfe8d14..94ffbe3cd0 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'digest/sha1' require "active_support/log_subscriber/test_helper" # common controller actions @@ -12,30 +11,14 @@ module RequestForgeryProtectionActions render :inline => "<%= button_to('New', '/') %>" end - def external_form - render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => 'external_token') {} %>" - end - - def external_form_without_protection - render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => false) {} %>" - end - def unsafe - render :text => 'pwn' + render plain: 'pwn' end def meta render :inline => "<%= csrf_meta_tags %>" end - def external_form_for - render :inline => "<%= form_for(:some_resource, :authenticity_token => 'external_token') {} %>" - end - - def form_for_without_protection - render :inline => "<%= form_for(:some_resource, :authenticity_token => false ) {} %>" - end - def form_for_remote render :inline => "<%= form_for(:some_resource, :remote => true ) {} %>" end @@ -70,7 +53,6 @@ module RequestForgeryProtectionActions negotiate_same_origin end - def rescue_action(e) raise e end end # sample controllers @@ -89,17 +71,42 @@ class RequestForgeryProtectionControllerUsingNullSession < ActionController::Bas def signed cookies.signed[:foo] = 'bar' - render :nothing => true + head :ok end def encrypted cookies.encrypted[:foo] = 'bar' - render :nothing => true + head :ok end def try_to_reset_session reset_session - render :nothing => true + head :ok + end +end + +class PrependProtectForgeryBaseController < ActionController::Base + before_action :custom_action + attr_accessor :called_callbacks + + def index + render inline: 'OK' + end + + protected + + def add_called_callback(name) + @called_callbacks ||= [] + @called_callbacks << name + end + + + def custom_action + add_called_callback("custom_action") + end + + def verify_authenticity_token + add_called_callback("verify_authenticity_token") end end @@ -124,10 +131,7 @@ end # common test methods module RequestForgeryProtectionTests def setup - @token = "cf50faa3fe97702ca1ae" - @controller.stubs(:form_authenticity_token).returns(@token) - @controller.stubs(:valid_authenticity_token?).with{ |_, t| t == @token }.returns(true) - @controller.stubs(:valid_authenticity_token?).with{ |_, t| t != @token }.returns(false) + @token = Base64.strict_encode64('railstestrailstestrailstestrails') @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token ActionController::Base.request_forgery_protection_token = :custom_authenticity_token end @@ -137,17 +141,21 @@ module RequestForgeryProtectionTests end def test_should_render_form_with_token_tag - assert_not_blocked do - get :index + @controller.stub :form_authenticity_token, @token do + assert_not_blocked do + get :index + end + assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end - assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end def test_should_render_button_to_with_token_tag - assert_not_blocked do - get :show_button + @controller.stub :form_authenticity_token, @token do + assert_not_blocked do + get :show_button + end + assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end - assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end def test_should_render_form_without_token_tag_if_remote @@ -191,17 +199,21 @@ module RequestForgeryProtectionTests end def test_should_render_form_with_token_tag_if_remote_and_authenticity_token_requested - assert_not_blocked do - get :form_for_remote_with_token + @controller.stub :form_authenticity_token, @token do + assert_not_blocked do + get :form_for_remote_with_token + end + assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end - assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end def test_should_render_form_with_token_tag_with_authenticity_token_requested - assert_not_blocked do - get :form_for_with_token + @controller.stub :form_authenticity_token, @token do + assert_not_blocked do + get :form_for_with_token + end + assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end - assert_select 'form>input[name=?][value=?]', 'custom_authenticity_token', @token end def test_should_allow_get @@ -237,41 +249,57 @@ module RequestForgeryProtectionTests end def test_should_not_allow_xhr_post_without_token - assert_blocked { xhr :post, :index } + assert_blocked { post :index, xhr: true } end def test_should_allow_post_with_token - assert_not_blocked { post :index, :custom_authenticity_token => @token } + session[:_csrf_token] = @token + @controller.stub :form_authenticity_token, @token do + assert_not_blocked { post :index, params: { custom_authenticity_token: @token } } + end end def test_should_allow_patch_with_token - assert_not_blocked { patch :index, :custom_authenticity_token => @token } + session[:_csrf_token] = @token + @controller.stub :form_authenticity_token, @token do + assert_not_blocked { patch :index, params: { custom_authenticity_token: @token } } + end end def test_should_allow_put_with_token - assert_not_blocked { put :index, :custom_authenticity_token => @token } + session[:_csrf_token] = @token + @controller.stub :form_authenticity_token, @token do + assert_not_blocked { put :index, params: { custom_authenticity_token: @token } } + end end def test_should_allow_delete_with_token - assert_not_blocked { delete :index, :custom_authenticity_token => @token } + session[:_csrf_token] = @token + @controller.stub :form_authenticity_token, @token do + assert_not_blocked { delete :index, params: { custom_authenticity_token: @token } } + end end def test_should_allow_post_with_token_in_header + session[:_csrf_token] = @token @request.env['HTTP_X_CSRF_TOKEN'] = @token assert_not_blocked { post :index } end def test_should_allow_delete_with_token_in_header + session[:_csrf_token] = @token @request.env['HTTP_X_CSRF_TOKEN'] = @token assert_not_blocked { delete :index } end def test_should_allow_patch_with_token_in_header + session[:_csrf_token] = @token @request.env['HTTP_X_CSRF_TOKEN'] = @token assert_not_blocked { patch :index } end def test_should_allow_put_with_token_in_header + session[:_csrf_token] = @token @request.env['HTTP_X_CSRF_TOKEN'] = @token assert_not_blocked { put :index } end @@ -315,21 +343,22 @@ module RequestForgeryProtectionTests get :negotiate_same_origin end - assert_cross_origin_not_blocked { xhr :get, :same_origin_js } - assert_cross_origin_not_blocked { xhr :get, :same_origin_js, format: 'js' } + assert_cross_origin_not_blocked { get :same_origin_js, xhr: true } + assert_cross_origin_not_blocked { get :same_origin_js, xhr: true, format: 'js'} assert_cross_origin_not_blocked do @request.accept = 'text/javascript' - xhr :get, :negotiate_same_origin + get :negotiate_same_origin, xhr: true end end # Allow non-GET requests since GET is all a remote <script> tag can muster. def test_should_allow_non_get_js_without_xhr_header - assert_cross_origin_not_blocked { post :same_origin_js, custom_authenticity_token: @token } - assert_cross_origin_not_blocked { post :same_origin_js, format: 'js', custom_authenticity_token: @token } + session[:_csrf_token] = @token + assert_cross_origin_not_blocked { post :same_origin_js, params: { custom_authenticity_token: @token } } + assert_cross_origin_not_blocked { post :same_origin_js, params: { format: 'js', custom_authenticity_token: @token } } assert_cross_origin_not_blocked do @request.accept = 'text/javascript' - post :negotiate_same_origin, custom_authenticity_token: @token + post :negotiate_same_origin, params: { custom_authenticity_token: @token} end end @@ -341,11 +370,17 @@ module RequestForgeryProtectionTests get :negotiate_cross_origin end - assert_cross_origin_not_blocked { xhr :get, :cross_origin_js } - assert_cross_origin_not_blocked { xhr :get, :cross_origin_js, format: 'js' } + assert_cross_origin_not_blocked { get :cross_origin_js, xhr: true } + assert_cross_origin_not_blocked { get :cross_origin_js, xhr: true, format: 'js' } assert_cross_origin_not_blocked do @request.accept = 'text/javascript' - xhr :get, :negotiate_cross_origin + get :negotiate_cross_origin, xhr: true + end + end + + def test_should_not_raise_error_if_token_is_not_a_string + assert_blocked do + patch :index, params: { custom_authenticity_token: { foo: 'bar' } } end end @@ -387,11 +422,13 @@ class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController end test 'should emit a csrf-param meta tag and a csrf-token meta tag' do - @controller.stubs(:form_authenticity_token).returns(@token + '<=?') - get :meta - assert_select 'meta[name=?][content=?]', 'csrf-param', 'custom_authenticity_token' - assert_select 'meta[name=?]', 'csrf-token' - assert_match(/cf50faa3fe97702ca1ae<=\?/, @response.body) + @controller.stub :form_authenticity_token, @token + '<=?' do + get :meta + assert_select 'meta[name=?][content=?]', 'csrf-param', 'custom_authenticity_token' + assert_select 'meta[name=?]', 'csrf-token' + regexp = "#{@token}<=\?" + assert_match(/#{regexp}/, @response.body) + end end end @@ -431,35 +468,75 @@ class RequestForgeryProtectionControllerUsingExceptionTest < ActionController::T end end +class PrependProtectForgeryBaseControllerTest < ActionController::TestCase + PrependTrueController = Class.new(PrependProtectForgeryBaseController) do + protect_from_forgery prepend: true + end + + PrependFalseController = Class.new(PrependProtectForgeryBaseController) do + protect_from_forgery prepend: false + end + + PrependDefaultController = Class.new(PrependProtectForgeryBaseController) do + protect_from_forgery + end + + def test_verify_authenticity_token_is_prepended + @controller = PrependTrueController.new + get :index + expected_callback_order = ["verify_authenticity_token", "custom_action"] + assert_equal(expected_callback_order, @controller.called_callbacks) + end + + def test_verify_authenticity_token_is_not_prepended + @controller = PrependFalseController.new + get :index + expected_callback_order = ["custom_action", "verify_authenticity_token"] + assert_equal(expected_callback_order, @controller.called_callbacks) + end + + def test_verify_authenticity_token_is_prepended_by_default + @controller = PrependDefaultController.new + get :index + expected_callback_order = ["verify_authenticity_token", "custom_action"] + assert_equal(expected_callback_order, @controller.called_callbacks) + end +end + class FreeCookieControllerTest < ActionController::TestCase def setup @controller = FreeCookieController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new @token = "cf50faa3fe97702ca1ae" - - SecureRandom.stubs(:base64).returns(@token) + super end def test_should_not_render_form_with_token_tag - get :index - assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + SecureRandom.stub :base64, @token do + get :index + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + end end def test_should_not_render_button_to_with_token_tag - get :show_button - assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + SecureRandom.stub :base64, @token do + get :show_button + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + end end def test_should_allow_all_methods_without_token - [:post, :patch, :put, :delete].each do |method| - assert_nothing_raised { send(method, :index)} + SecureRandom.stub :base64, @token do + [:post, :patch, :put, :delete].each do |method| + assert_nothing_raised { send(method, :index)} + end end end test 'should not emit a csrf-token meta tag' do - get :meta - assert @response.body.blank? + SecureRandom.stub :base64, @token do + get :meta + assert @response.body.blank? + end end end @@ -480,11 +557,11 @@ class CustomAuthenticityParamControllerTest < ActionController::TestCase def test_should_not_warn_if_form_authenticity_param_matches_form_authenticity_token ActionController::Base.logger = @logger - @controller.stubs(:valid_authenticity_token?).returns(:true) - begin - post :index, :custom_token_name => 'foobar' - assert_equal 0, @logger.logged(:warn).size + @controller.stub :valid_authenticity_token?, :true do + post :index, params: { custom_token_name: 'foobar' } + assert_equal 0, @logger.logged(:warn).size + end ensure ActionController::Base.logger = @old_logger end @@ -494,7 +571,7 @@ class CustomAuthenticityParamControllerTest < ActionController::TestCase ActionController::Base.logger = @logger begin - post :index, :custom_token_name => 'bazqux' + post :index, params: { custom_token_name: 'bazqux' } assert_equal 1, @logger.logged(:warn).size ensure ActionController::Base.logger = @old_logger diff --git a/actionpack/test/controller/required_params_test.rb b/actionpack/test/controller/required_params_test.rb index 6803dbbb62..168f64ce41 100644 --- a/actionpack/test/controller/required_params_test.rb +++ b/actionpack/test/controller/required_params_test.rb @@ -12,21 +12,21 @@ class ActionControllerRequiredParamsTest < ActionController::TestCase test "missing required parameters will raise exception" do assert_raise ActionController::ParameterMissing do - post :create, { magazine: { name: "Mjallo!" } } + post :create, params: { magazine: { name: "Mjallo!" } } end assert_raise ActionController::ParameterMissing do - post :create, { book: { title: "Mjallo!" } } + post :create, params: { book: { title: "Mjallo!" } } end end test "required parameters that are present will not raise" do - post :create, { book: { name: "Mjallo!" } } + post :create, params: { book: { name: "Mjallo!" } } assert_response :ok end test "required parameters with false value will not raise" do - post :create, { book: { name: false } } + post :create, params: { book: { name: false } } assert_response :ok end end @@ -48,4 +48,21 @@ class ParametersRequireTest < ActiveSupport::TestCase ActionController::Parameters.new(person: {}).require(:person) end end + + test "require array when all required params are present" do + safe_params = ActionController::Parameters.new(person: {first_name: 'Gaurish', title: 'Mjallo', city: 'Barcelona'}) + .require(:person) + .require([:first_name, :title]) + + assert_kind_of Array, safe_params + assert_equal ['Gaurish', 'Mjallo'], safe_params + end + + test "require array when a required param is missing" do + assert_raises(ActionController::ParameterMissing) do + ActionController::Parameters.new(person: {first_name: 'Gaurish', title: nil}) + .require(:person) + .require([:first_name, :title]) + end + end end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 4898b0c57f..f42bef883f 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -43,29 +43,29 @@ class RescueController < ActionController::Base rescue_from NotAllowed, :with => proc { head :forbidden } rescue_from 'RescueController::NotAllowedToRescueAsString', :with => proc { head :forbidden } - rescue_from InvalidRequest, :with => proc { |exception| render :text => exception.message } - rescue_from 'InvalidRequestToRescueAsString', :with => proc { |exception| render :text => exception.message } + rescue_from InvalidRequest, with: proc { |exception| render plain: exception.message } + rescue_from 'InvalidRequestToRescueAsString', with: proc { |exception| render plain: exception.message } rescue_from BadGateway do - head :status => 502 + head 502 end rescue_from 'BadGatewayToRescueAsString' do - head :status => 502 + head 502 end rescue_from ResourceUnavailable do |exception| - render :text => exception.message + render plain: exception.message end rescue_from 'ResourceUnavailableToRescueAsString' do |exception| - render :text => exception.message + render plain: exception.message end rescue_from ActionView::TemplateError do - render :text => 'action_view templater error' + render plain: 'action_view templater error' end rescue_from IOError do - render :text => 'io error' + render plain: 'io error' end before_action(only: :before_action_raises) { raise 'umm nice' } @@ -74,7 +74,7 @@ class RescueController < ActionController::Base end def raises - render :text => 'already rendered' + render plain: 'already rendered' raise "don't panic!" end @@ -132,11 +132,19 @@ class RescueController < ActionController::Base end def io_error_in_view - raise ActionView::TemplateError.new(nil, IOError.new('this is io error')) + begin + raise IOError.new('this is io error') + rescue + raise ActionView::TemplateError.new(nil) + end end def zero_division_error_in_view - raise ActionView::TemplateError.new(nil, ZeroDivisionError.new('this is zero division error')) + begin + raise ZeroDivisionError.new('this is zero division error') + rescue + raise ActionView::TemplateError.new(nil) + end end protected @@ -246,12 +254,15 @@ class RescueControllerTest < ActionController::TestCase end def test_rescue_handler_with_argument - @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) } - get :record_invalid + assert_called_with @controller, :show_errors, [Exception] do + get :record_invalid + end end + def test_rescue_handler_with_argument_as_string - @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) } - get :record_invalid_raise_as_string + assert_called_with @controller, :show_errors, [Exception] do + get :record_invalid_raise_as_string + end end def test_proc_rescue_handler @@ -302,7 +313,7 @@ class RescueTest < ActionDispatch::IntegrationTest rescue_from RecordInvalid, :with => :show_errors def foo - render :text => "foo" + render plain: "foo" end def invalid @@ -315,7 +326,7 @@ class RescueTest < ActionDispatch::IntegrationTest protected def show_errors(exception) - render :text => exception.message + render plain: exception.message end end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index a5f43c4b6b..4490abf7b2 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -43,11 +43,11 @@ class ResourcesTest < ActionController::TestCase :member => member_methods, :path_names => path_names do |options| - collection_methods.keys.each do |action| + collection_methods.each_key do |action| assert_named_route "/messages/#{path_names[action] || action}", "#{action}_messages_path", :action => action end - member_methods.keys.each do |action| + member_methods.each_key do |action| assert_named_route "/messages/1/#{path_names[action] || action}", "#{action}_message_path", :action => action, :id => "1" end @@ -149,8 +149,8 @@ class ResourcesTest < ActionController::TestCase end end - assert_restful_named_routes_for :messages do |options| - actions.keys.each do |action| + assert_restful_named_routes_for :messages do + actions.each_key do |action| assert_named_route "/messages/#{action}", "#{action}_messages_path", :action => action end end @@ -179,8 +179,8 @@ class ResourcesTest < ActionController::TestCase end end - assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| - actions.keys.each do |action| + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do + actions.each_key do |action| assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action end end @@ -206,8 +206,8 @@ class ResourcesTest < ActionController::TestCase end end - assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| - actions.keys.each do |action| + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do + actions.each_key do |action| assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action end end @@ -236,8 +236,8 @@ class ResourcesTest < ActionController::TestCase end end - assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| - actions.keys.each do |action| + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do + actions.each_key do |action| assert_named_route "/threads/1/messages/#{action}.xml", "#{action}_thread_messages_path", :action => action, :format => 'xml' end end @@ -253,7 +253,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method) end - assert_restful_named_routes_for :messages do |options| + assert_restful_named_routes_for :messages do assert_named_route mark_path, :mark_message_path, mark_options end end @@ -278,7 +278,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method) end - assert_restful_named_routes_for :messages, :path_names => {:new => 'nuevo'} do |options| + assert_restful_named_routes_for :messages, :path_names => {:new => 'nuevo'} do assert_named_route mark_path, :mark_message_path, mark_options end end @@ -304,7 +304,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(action_options), :path => action_path, :method => method) end - assert_restful_named_routes_for :messages do |options| + assert_restful_named_routes_for :messages do assert_named_route action_path, "#{action}_message_path".to_sym, action_options end end @@ -351,7 +351,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) end - assert_restful_named_routes_for :messages do |options| + assert_restful_named_routes_for :messages do assert_named_route preview_path, :preview_new_message_path, preview_options end end @@ -373,7 +373,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) end - assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do assert_named_route preview_path, :preview_new_thread_message_path, preview_options end end @@ -395,7 +395,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) end - assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do assert_named_route preview_path, :preview_new_thread_message_path, preview_options end end @@ -505,8 +505,8 @@ class ResourcesTest < ActionController::TestCase routes = @routes.routes routes.each do |route| routes.each do |r| - next if route === r # skip the comparison instance - assert_not_equal [route.conditions, route.path.spec.to_s], [r.conditions, r.path.spec.to_s] + next if route == r # skip the comparison instance + assert_not_equal [route.conditions, route.path.spec.to_s, route.verb], [r.conditions, r.path.spec.to_s, r.verb] end end end @@ -519,9 +519,9 @@ class ResourcesTest < ActionController::TestCase end def test_should_create_multiple_singleton_resource_routes - with_singleton_resources :account, :logo do + with_singleton_resources :account, :product do assert_singleton_restful_for :account - assert_singleton_restful_for :logo + assert_singleton_restful_for :product end end @@ -553,7 +553,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method) end - assert_singleton_named_routes_for :account do |options| + assert_singleton_named_routes_for :account do assert_named_route reset_path, :reset_account_path, reset_options end end @@ -577,7 +577,7 @@ class ResourcesTest < ActionController::TestCase assert_recognizes(options.merge(action_options), :path => action_path, :method => method) end - assert_singleton_named_routes_for :account do |options| + assert_singleton_named_routes_for :account do assert_named_route action_path, "#{action}_account_path".to_sym, action_options end end @@ -1047,9 +1047,31 @@ class ResourcesTest < ActionController::TestCase end end + def test_assert_routing_accepts_all_as_a_valid_method + with_routing do |set| + set.draw do + match "/products", to: "products#show", via: :all + end + + assert_routing({ method: "all", path: "/products" }, { controller: "products", action: "show" }) + end + end + + def test_assert_routing_fails_when_not_all_http_methods_are_recognized + with_routing do |set| + set.draw do + match "/products", to: "products#show", via: [:get, :post, :put] + end + + assert_raises(Minitest::Assertion) do + assert_routing({ method: "all", path: "/products" }, { controller: "products", action: "show" }) + end + end + end + def test_singleton_resource_name_is_not_singularized - with_singleton_resources(:preferences) do - assert_singleton_restful_for :preferences + with_singleton_resources(:products) do + assert_singleton_restful_for :products end end @@ -1106,14 +1128,14 @@ class ResourcesTest < ActionController::TestCase end def assert_restful_routes_for(controller_name, options = {}) - options[:options] ||= {} - options[:options][:controller] = options[:controller] || controller_name.to_s + route_options = (options[:options] ||= {}).dup + route_options[:controller] = options[:controller] || controller_name.to_s if options[:shallow] options[:shallow_options] ||= {} - options[:shallow_options][:controller] = options[:options][:controller] + options[:shallow_options][:controller] = route_options[:controller] else - options[:shallow_options] = options[:options] + options[:shallow_options] = route_options end new_action = @routes.resources_path_names[:new] || "new" @@ -1132,7 +1154,7 @@ class ResourcesTest < ActionController::TestCase edit_member_path = "#{member_path}/#{edit_action}" formatted_edit_member_path = "#{member_path}/#{edit_action}.xml" - with_options(options[:options]) do |controller| + with_options(route_options) do |controller| controller.assert_routing collection_path, :action => 'index' controller.assert_routing new_path, :action => 'new' controller.assert_routing "#{collection_path}.xml", :action => 'index', :format => 'xml' @@ -1146,23 +1168,23 @@ class ResourcesTest < ActionController::TestCase controller.assert_routing formatted_edit_member_path, :action => 'edit', :id => '1', :format => 'xml' end - assert_recognizes(options[:options].merge(:action => 'index'), :path => collection_path, :method => :get) - assert_recognizes(options[:options].merge(:action => 'new'), :path => new_path, :method => :get) - assert_recognizes(options[:options].merge(:action => 'create'), :path => collection_path, :method => :post) + assert_recognizes(route_options.merge(:action => 'index'), :path => collection_path, :method => :get) + assert_recognizes(route_options.merge(:action => 'new'), :path => new_path, :method => :get) + assert_recognizes(route_options.merge(:action => 'create'), :path => collection_path, :method => :post) assert_recognizes(options[:shallow_options].merge(:action => 'show', :id => '1'), :path => member_path, :method => :get) assert_recognizes(options[:shallow_options].merge(:action => 'edit', :id => '1'), :path => edit_member_path, :method => :get) assert_recognizes(options[:shallow_options].merge(:action => 'update', :id => '1'), :path => member_path, :method => :put) assert_recognizes(options[:shallow_options].merge(:action => 'destroy', :id => '1'), :path => member_path, :method => :delete) - assert_recognizes(options[:options].merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get) - assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get) - assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post) + assert_recognizes(route_options.merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get) + assert_recognizes(route_options.merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get) + assert_recognizes(route_options.merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post) assert_recognizes(options[:shallow_options].merge(:action => 'show', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :get) assert_recognizes(options[:shallow_options].merge(:action => 'edit', :id => '1', :format => 'xml'), :path => formatted_edit_member_path, :method => :get) assert_recognizes(options[:shallow_options].merge(:action => 'update', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :put) assert_recognizes(options[:shallow_options].merge(:action => 'destroy', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :delete) - yield options[:options] if block_given? + yield route_options if block_given? end # test named routes like foo_path and foos_path map to the correct options. @@ -1173,22 +1195,20 @@ class ResourcesTest < ActionController::TestCase end singular_name ||= controller_name.to_s.singularize - options[:options] ||= {} - options[:options][:controller] = options[:controller] || controller_name.to_s + route_options = (options[:options] ||= {}).dup + route_options[:controller] = options[:controller] || controller_name.to_s if options[:shallow] options[:shallow_options] ||= {} - options[:shallow_options][:controller] = options[:options][:controller] + options[:shallow_options][:controller] = route_options[:controller] else - options[:shallow_options] = options[:options] + options[:shallow_options] = route_options end - @controller = "#{options[:options][:controller].camelize}Controller".constantize.new - @controller.singleton_class.send(:include, @routes.url_helpers) - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - get :index, options[:options] - options[:options].delete :action + @controller = "#{route_options[:controller].camelize}Controller".constantize.new + @controller.singleton_class.include(@routes.url_helpers) + get :index, params: route_options + route_options.delete :action path = "#{options[:as] || controller_name}" shallow_path = "/#{options[:shallow] ? options[:namespace] : options[:path_prefix]}#{path}" @@ -1203,29 +1223,29 @@ class ResourcesTest < ActionController::TestCase edit_action = options[:path_names][:edit] || "edit" end - assert_named_route "#{full_path}", "#{name_prefix}#{controller_name}_path", options[:options] - assert_named_route "#{full_path}.xml", "#{name_prefix}#{controller_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}", "#{name_prefix}#{controller_name}_path", route_options + assert_named_route "#{full_path}.xml", "#{name_prefix}#{controller_name}_path", route_options.merge(:format => 'xml') assert_named_route "#{shallow_path}/1", "#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1') assert_named_route "#{shallow_path}/1.xml", "#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1', :format => 'xml') - assert_named_route "#{full_path}/#{new_action}", "new_#{name_prefix}#{singular_name}_path", options[:options] - assert_named_route "#{full_path}/#{new_action}.xml", "new_#{name_prefix}#{singular_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}/#{new_action}", "new_#{name_prefix}#{singular_name}_path", route_options + assert_named_route "#{full_path}/#{new_action}.xml", "new_#{name_prefix}#{singular_name}_path", route_options.merge(:format => 'xml') assert_named_route "#{shallow_path}/1/#{edit_action}", "edit_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1') assert_named_route "#{shallow_path}/1/#{edit_action}.xml", "edit_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1', :format => 'xml') - yield options[:options] if block_given? + yield route_options if block_given? end def assert_singleton_routes_for(singleton_name, options = {}) - options[:options] ||= {} - options[:options][:controller] = options[:controller] || singleton_name.to_s.pluralize + route_options = (options[:options] ||= {}).dup + route_options[:controller] = options[:controller] || singleton_name.to_s.pluralize full_path = "/#{options[:path_prefix]}#{options[:as] || singleton_name}" new_path = "#{full_path}/new" edit_path = "#{full_path}/edit" formatted_edit_path = "#{full_path}/edit.xml" - with_options options[:options] do |controller| + with_options route_options do |controller| controller.assert_routing full_path, :action => 'show' controller.assert_routing new_path, :action => 'new' controller.assert_routing edit_path, :action => 'edit' @@ -1234,42 +1254,41 @@ class ResourcesTest < ActionController::TestCase controller.assert_routing formatted_edit_path, :action => 'edit', :format => 'xml' end - assert_recognizes(options[:options].merge(:action => 'show'), :path => full_path, :method => :get) - assert_recognizes(options[:options].merge(:action => 'new'), :path => new_path, :method => :get) - assert_recognizes(options[:options].merge(:action => 'edit'), :path => edit_path, :method => :get) - assert_recognizes(options[:options].merge(:action => 'create'), :path => full_path, :method => :post) - assert_recognizes(options[:options].merge(:action => 'update'), :path => full_path, :method => :put) - assert_recognizes(options[:options].merge(:action => 'destroy'), :path => full_path, :method => :delete) + assert_recognizes(route_options.merge(:action => 'show'), :path => full_path, :method => :get) + assert_recognizes(route_options.merge(:action => 'new'), :path => new_path, :method => :get) + assert_recognizes(route_options.merge(:action => 'edit'), :path => edit_path, :method => :get) + assert_recognizes(route_options.merge(:action => 'create'), :path => full_path, :method => :post) + assert_recognizes(route_options.merge(:action => 'update'), :path => full_path, :method => :put) + assert_recognizes(route_options.merge(:action => 'destroy'), :path => full_path, :method => :delete) - assert_recognizes(options[:options].merge(:action => 'show', :format => 'xml'), :path => "#{full_path}.xml", :method => :get) - assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get) - assert_recognizes(options[:options].merge(:action => 'edit', :format => 'xml'), :path => formatted_edit_path, :method => :get) - assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{full_path}.xml", :method => :post) - assert_recognizes(options[:options].merge(:action => 'update', :format => 'xml'), :path => "#{full_path}.xml", :method => :put) - assert_recognizes(options[:options].merge(:action => 'destroy', :format => 'xml'), :path => "#{full_path}.xml", :method => :delete) + assert_recognizes(route_options.merge(:action => 'show', :format => 'xml'), :path => "#{full_path}.xml", :method => :get) + assert_recognizes(route_options.merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get) + assert_recognizes(route_options.merge(:action => 'edit', :format => 'xml'), :path => formatted_edit_path, :method => :get) + assert_recognizes(route_options.merge(:action => 'create', :format => 'xml'), :path => "#{full_path}.xml", :method => :post) + assert_recognizes(route_options.merge(:action => 'update', :format => 'xml'), :path => "#{full_path}.xml", :method => :put) + assert_recognizes(route_options.merge(:action => 'destroy', :format => 'xml'), :path => "#{full_path}.xml", :method => :delete) - yield options[:options] if block_given? + yield route_options if block_given? end def assert_singleton_named_routes_for(singleton_name, options = {}) - (options[:options] ||= {})[:controller] ||= singleton_name.to_s.pluralize - @controller = "#{options[:options][:controller].camelize}Controller".constantize.new - @controller.singleton_class.send(:include, @routes.url_helpers) - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - get :show, options[:options] - options[:options].delete :action + route_options = (options[:options] ||= {}).dup + controller_name = route_options[:controller] || options[:controller] || singleton_name.to_s.pluralize + @controller = "#{controller_name.camelize}Controller".constantize.new + @controller.singleton_class.include(@routes.url_helpers) + get :show, params: route_options + route_options.delete :action full_path = "/#{options[:path_prefix]}#{options[:as] || singleton_name}" name_prefix = options[:name_prefix] - assert_named_route "#{full_path}", "#{name_prefix}#{singleton_name}_path", options[:options] - assert_named_route "#{full_path}.xml", "#{name_prefix}#{singleton_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}", "#{name_prefix}#{singleton_name}_path", route_options + assert_named_route "#{full_path}.xml", "#{name_prefix}#{singleton_name}_path", route_options.merge(:format => 'xml') - assert_named_route "#{full_path}/new", "new_#{name_prefix}#{singleton_name}_path", options[:options] - assert_named_route "#{full_path}/new.xml", "new_#{name_prefix}#{singleton_name}_path", options[:options].merge(:format => 'xml') - assert_named_route "#{full_path}/edit", "edit_#{name_prefix}#{singleton_name}_path", options[:options] - assert_named_route "#{full_path}/edit.xml", "edit_#{name_prefix}#{singleton_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}/new", "new_#{name_prefix}#{singleton_name}_path", route_options + assert_named_route "#{full_path}/new.xml", "new_#{name_prefix}#{singleton_name}_path", route_options.merge(:format => 'xml') + assert_named_route "#{full_path}/edit", "edit_#{name_prefix}#{singleton_name}_path", route_options + assert_named_route "#{full_path}/edit.xml", "edit_#{name_prefix}#{singleton_name}_path", route_options.merge(:format => 'xml') end def assert_named_route(expected, route, options) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index c18914cc8e..a39fede5b9 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 require 'abstract_unit' require 'controller/fake_controllers' require 'active_support/core_ext/object/with_options' @@ -9,8 +8,6 @@ class MilestonesController < ActionController::Base alias_method :show, :index end -ROUTING = ActionDispatch::Routing - # See RFC 3986, section 3.3 for allowed path characters. class UriReservedCharactersRoutingTest < ActiveSupport::TestCase include RoutingTestHelpers @@ -292,12 +289,6 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal({:id=>"1", :filters=>"foo", :format=>"js"}, params) end - def test_draw_with_block_arity_one_raises - assert_raise(RuntimeError) do - rs.draw { |map| map.match '/:controller(/:action(/:id))' } - end - end - def test_specific_controller_action_failure rs.draw do mount lambda {} => "/foo" @@ -330,17 +321,23 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal '/stuff', controller.url_for({ :controller => '/stuff', :only_path => true }) end - def test_ignores_leading_slash - rs.clear! - rs.draw { get '/:controller(/:action(/:id))'} - test_default_setup - end - def test_route_with_colon_first rs.draw do - get '/:controller/:action/:id', :action => 'index', :id => nil - get ':url', :controller => 'tiny_url', :action => 'translate' + get '/:controller/:action/:id', action: 'index', id: nil + get ':url', controller: 'content', action: 'translate' end + + assert_equal({controller: 'content', action: 'translate', url: 'example'}, rs.recognize_path('/example')) + end + + def test_route_with_regexp_for_action + rs.draw { get '/:controller/:action', action: /auth[-|_].+/ } + + assert_equal({ action: 'auth_google', controller: 'content' }, rs.recognize_path('/content/auth_google')) + assert_equal({ action: 'auth-facebook', controller: 'content' }, rs.recognize_path('/content/auth-facebook')) + + assert_equal '/content/auth_google', url_for(rs, { controller: "content", action: "auth_google" }) + assert_equal '/content/auth-facebook', url_for(rs, { controller: "content", action: "auth-facebook" }) end def test_route_with_regexp_for_controller @@ -872,7 +869,7 @@ class RouteSetTest < ActiveSupport::TestCase def default_route_set @default_route_set ||= begin - set = ROUTING::RouteSet.new + set = ActionDispatch::Routing::RouteSet.new set.draw do get '/:controller(/:action(/:id))' end @@ -884,13 +881,13 @@ class RouteSetTest < ActiveSupport::TestCase set.draw { get ':controller/(:action(/:id))' } path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal "/foo/bar/15", path - assert_equal %w(that this), extras.map { |e| e.to_s }.sort + assert_equal %w(that this), extras.map(&:to_s).sort end def test_extra_keys set.draw { get ':controller/:action/:id' } extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") - assert_equal %w(that this), extras.map { |e| e.to_s }.sort + assert_equal %w(that this), extras.map(&:to_s).sort end def test_generate_extras_not_first @@ -900,7 +897,7 @@ class RouteSetTest < ActiveSupport::TestCase end path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal "/foo/bar/15", path - assert_equal %w(that this), extras.map { |e| e.to_s }.sort + assert_equal %w(that this), extras.map(&:to_s).sort end def test_generate_not_first @@ -918,7 +915,7 @@ class RouteSetTest < ActiveSupport::TestCase get ':controller/:action/:id' end extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") - assert_equal %w(that this), extras.map { |e| e.to_s }.sort + assert_equal %w(that this), extras.map(&:to_s).sort end def test_draw @@ -1001,6 +998,9 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal "http://test.host/people?baz=bar#location", controller.send(:index_url, :baz => "bar", :anchor => 'location') + + assert_equal "http://test.host/people", controller.send(:index_url, anchor: nil) + assert_equal "http://test.host/people", controller.send(:index_url, anchor: false) end def test_named_route_url_method_with_port @@ -1383,7 +1383,7 @@ class RouteSetTest < ActiveSupport::TestCase url = controller.url_for({ :controller => "connection", :only_path => true }) assert_equal "/connection/connection", url - url = controller.url_for({ :use_route => :family_connection, + url = controller.url_for({ :use_route => "family_connection", :controller => "connection", :only_path => true }) assert_equal "/connection", url end @@ -1746,40 +1746,10 @@ class RouteSetTest < ActiveSupport::TestCase 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 = make_set false set.draw do get "blog/", :controller => "blog", :action => "index" diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index c002cf4d8f..2820425c31 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 require 'abstract_unit' module TestFileUtils @@ -21,6 +20,47 @@ class SendFileController < ActionController::Base send_file(file_path, options) end + def test_send_file_headers_bang + options = { + :type => Mime[:png], + :disposition => 'disposition', + :filename => 'filename' + } + + send_data "foo", options + end + + def test_send_file_headers_with_disposition_as_a_symbol + options = { + :type => Mime[:png], + :disposition => :disposition, + :filename => 'filename' + } + + send_data "foo", options + end + + def test_send_file_headers_with_mime_lookup_with_symbol + options = { :type => :png } + + send_data "foo", options + end + + def test_send_file_headers_with_bad_symbol + options = { :type => :this_type_is_not_registered } + send_data "foo", options + end + + def test_send_file_headers_with_nil_content_type + options = { :type => nil } + send_data "foo", options + end + + def test_send_file_headers_guess_type_from_extension + options = { :filename => params[:filename] } + send_data "foo", options + end + def data send_data(file_data, options) end @@ -35,8 +75,6 @@ class SendFileTest < ActionController::TestCase def setup @controller = SendFileController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new end def test_file_nostream @@ -91,62 +129,39 @@ class SendFileTest < ActionController::TestCase # Test that send_file_headers! is setting the correct HTTP headers. def test_send_file_headers_bang - options = { - :type => Mime::PNG, - :disposition => 'disposition', - :filename => 'filename' - } - # Do it a few times: the resulting headers should be identical # no matter how many times you send with the same options. # Test resolving Ticket #458. - @controller.headers = {} - @controller.send(:send_file_headers!, options) - @controller.send(:send_file_headers!, options) - @controller.send(:send_file_headers!, options) + 5.times do + get :test_send_file_headers_bang - h = @controller.headers - assert_equal 'image/png', @controller.content_type - assert_equal 'disposition; filename="filename"', h['Content-Disposition'] - assert_equal 'binary', h['Content-Transfer-Encoding'] - - # test overriding Cache-Control: no-cache header to fix IE open/save dialog - @controller.send(:send_file_headers!, options) - @controller.response.prepare! - assert_equal 'private', h['Cache-Control'] + assert_equal 'image/png', response.content_type + assert_equal 'disposition; filename="filename"', response.get_header('Content-Disposition') + assert_equal 'binary', response.get_header('Content-Transfer-Encoding') + assert_equal 'private', response.get_header('Cache-Control') + end end def test_send_file_headers_with_disposition_as_a_symbol - options = { - :type => Mime::PNG, - :disposition => :disposition, - :filename => 'filename' - } + get :test_send_file_headers_with_disposition_as_a_symbol - @controller.headers = {} - @controller.send(:send_file_headers!, options) - assert_equal 'disposition; filename="filename"', @controller.headers['Content-Disposition'] + assert_equal 'disposition; filename="filename"', response.get_header('Content-Disposition') end def test_send_file_headers_with_mime_lookup_with_symbol - options = { - :type => :png - } - - @controller.headers = {} - @controller.send(:send_file_headers!, options) - - assert_equal 'image/png', @controller.content_type + get __method__ + assert_equal 'image/png', response.content_type end def test_send_file_headers_with_bad_symbol - options = { - :type => :this_type_is_not_registered - } + error = assert_raise(ArgumentError) { get __method__ } + assert_equal "Unknown MIME type this_type_is_not_registered", error.message + end - @controller.headers = {} - assert_raise(ArgumentError) { @controller.send(:send_file_headers!, options) } + def test_send_file_headers_with_nil_content_type + error = assert_raise(ArgumentError) { get __method__ } + assert_equal ":type option required", error.message end def test_send_file_headers_guess_type_from_extension @@ -161,10 +176,8 @@ class SendFileTest < ActionController::TestCase 'file.unk' => 'application/octet-stream', 'zip' => 'application/octet-stream' }.each do |filename,expected_type| - options = { :filename => filename } - @controller.headers = {} - @controller.send(:send_file_headers!, options) - assert_equal expected_type, @controller.content_type + get __method__, params: { filename: filename } + assert_equal expected_type, response.content_type end end @@ -182,7 +195,7 @@ class SendFileTest < ActionController::TestCase %w(file data).each do |method| define_method "test_send_#{method}_status" do @controller.options = { :stream => false, :status => 500 } - assert_nothing_raised { assert_not_nil process(method) } + assert_not_nil process(method) assert_equal 500, @response.status end diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index f7eba1ef43..786dc15444 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -58,13 +58,13 @@ module ShowExceptions class ShowExceptionsOverriddenTest < ActionDispatch::IntegrationTest test 'show error page' do @app = ShowExceptionsOverriddenController.action(:boom) - get '/', {'detailed' => '0'} + get '/', params: { 'detailed' => '0' } assert_equal "500 error fixture\n", body end test 'show diagnostics message' do @app = ShowExceptionsOverriddenController.action(:boom) - get '/', {'detailed' => '1'} + get '/', params: { 'detailed' => '1' } assert_match(/boom/, body) end end @@ -72,23 +72,23 @@ module ShowExceptions class ShowExceptionsFormatsTest < ActionDispatch::IntegrationTest def test_render_json_exception @app = ShowExceptionsOverriddenController.action(:boom) - get "/", {}, 'HTTP_ACCEPT' => 'application/json' + get "/", headers: { 'HTTP_ACCEPT' => 'application/json' } assert_response :internal_server_error assert_equal 'application/json', response.content_type.to_s - assert_equal({ :status => '500', :error => 'Internal Server Error' }.to_json, response.body) + assert_equal({ :status => 500, :error => 'Internal Server Error' }.to_json, response.body) end def test_render_xml_exception @app = ShowExceptionsOverriddenController.action(:boom) - get "/", {}, 'HTTP_ACCEPT' => 'application/xml' + get "/", headers: { 'HTTP_ACCEPT' => 'application/xml' } assert_response :internal_server_error assert_equal 'application/xml', response.content_type.to_s - assert_equal({ :status => '500', :error => 'Internal Server Error' }.to_xml, response.body) + assert_equal({ :status => 500, :error => 'Internal Server Error' }.to_xml, response.body) end def test_render_fallback_exception @app = ShowExceptionsOverriddenController.action(:boom) - get "/", {}, 'HTTP_ACCEPT' => 'text/csv' + get "/", headers: { 'HTTP_ACCEPT' => 'text/csv' } assert_response :internal_server_error assert_equal 'text/html', response.content_type.to_s end @@ -101,7 +101,7 @@ module ShowExceptions @app.instance_variable_set(:@exceptions_app, nil) $stderr = StringIO.new - get '/', {}, 'HTTP_ACCEPT' => 'text/json' + get '/', headers: { 'HTTP_ACCEPT' => 'text/json' } assert_response :internal_server_error assert_equal 'text/plain', response.content_type.to_s ensure diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index 1280e0d9a3..e50373a0cc 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -1,69 +1,85 @@ require 'abstract_unit' require 'controller/fake_controllers' require 'active_support/json/decoding' +require 'rails/engine' class TestCaseTest < ActionController::TestCase + def self.fixture_path; end; + class TestController < ActionController::Base def no_op - render :text => 'dummy' + render plain: 'dummy' end def set_flash flash["test"] = ">#{flash["test"]}<" - render :text => 'ignore me' + render plain: 'ignore me' + end + + def delete_flash + flash.delete("test") + render plain: 'ignore me' end def set_flash_now flash.now["test_now"] = ">#{flash["test_now"]}<" - render :text => 'ignore me' + render plain: 'ignore me' end def set_session session['string'] = 'A wonder' session[:symbol] = 'it works' - render :text => 'Success' + render plain: 'Success' end def reset_the_session reset_session - render :text => 'ignore me' + render plain: 'ignore me' end def render_raw_post raise ActiveSupport::TestCase::Assertion, "#raw_post is blank" if request.raw_post.blank? - render :text => request.raw_post + render plain: request.raw_post end def render_body - render :text => request.body.read + render plain: request.body.read end def test_params - render :text => params.inspect + render plain: ::JSON.dump(params.to_unsafe_h) + end + + def test_query_parameters + render plain: ::JSON.dump(request.query_parameters) + end + + def test_request_parameters + render plain: request.request_parameters.inspect end def test_uri - render :text => request.fullpath + render plain: request.fullpath end def test_format - render :text => request.format + render plain: request.format end def test_query_string - render :text => request.query_string + render plain: request.query_string end def test_protocol - render :text => request.protocol + render plain: request.protocol end def test_headers - render text: request.headers.env.to_json + render plain: ::JSON.dump(request.headers.env) end def test_html_output - render :text => <<HTML + render plain: <<HTML <html> <body> <a href="/"><img src="/images/button.png" /></a> @@ -85,7 +101,7 @@ HTML def test_xml_output response.content_type = "application/xml" - render :text => <<XML + render plain: <<XML <?xml version="1.0" encoding="UTF-8"?> <root> <area>area is an empty tag in HTML, raising an error if not in xml mode</area> @@ -94,15 +110,15 @@ XML end def test_only_one_param - render :text => (params[:left] && params[:right]) ? "EEP, Both here!" : "OK" + render plain: (params[:left] && params[:right]) ? "EEP, Both here!" : "OK" end def test_remote_addr - render :text => (request.remote_addr || "not specified") + render plain: (request.remote_addr || "not specified") end def test_file_upload - render :text => params[:file].size + render plain: params[:file].size end def test_send_file @@ -110,41 +126,41 @@ XML end def redirect_to_same_controller - redirect_to :controller => 'test', :action => 'test_uri', :id => 5 + redirect_to controller: 'test', action: 'test_uri', id: 5 end def redirect_to_different_controller - redirect_to :controller => 'fail', :id => 5 + redirect_to controller: 'fail', id: 5 end def create - head :created, :location => 'created resource' + head :created, location: 'created resource' end def delete_cookie cookies.delete("foo") - render :nothing => true + render plain: 'ok' end - def test_assigns - @foo = "foo" - @foo_hash = {:foo => :bar} - render :nothing => true + def test_without_body + render html: '<div class="foo"></div>'.html_safe + end + + def test_with_body + render html: '<body class="foo"></body>'.html_safe end private def generate_url(opts) - url_for(opts.merge(:action => "test_uri")) + url_for(opts.merge(action: "test_uri")) end end def setup super @controller = TestController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - @request.env['PATH_INFO'] = nil + @request.delete_header 'PATH_INFO' @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| r.draw do get ':controller(/:action(/:id))' @@ -152,22 +168,11 @@ XML end end - class ViewAssignsController < ActionController::Base - def test_assigns - @foo = "foo" - render :nothing => true - end - - def view_assigns - { "bar" => "bar" } - end - end - class DefaultUrlOptionsCachingController < ActionController::Base before_action { @dynamic_opt = 'opt' } def test_url_options_reset - render text: url_for(params) + render plain: url_for(params) end def default_url_options @@ -179,6 +184,19 @@ XML end end + def test_assert_select_without_body + get :test_without_body + + assert_select 'body', 0 + assert_select 'div.foo' + end + + def test_assert_select_with_body + get :test_with_body + + assert_select 'body.foo' + end + def test_url_options_reset @controller = DefaultUrlOptionsCachingController.new get :test_url_options_reset @@ -187,32 +205,50 @@ XML end def test_raw_post_handling - params = Hash[:page, {:name => 'page name'}, 'some key', 123] - post :render_raw_post, params.dup + params = Hash[:page, { name: 'page name' }, 'some key', 123] + post :render_raw_post, params: params.dup assert_equal params.to_query, @response.body end def test_body_stream - params = Hash[:page, { :name => 'page name' }, 'some key', 123] + params = Hash[:page, { name: 'page name' }, 'some key', 123] - post :render_body, params.dup + post :render_body, params: params.dup + + assert_equal params.to_query, @response.body + end + + def test_deprecated_body_stream + params = Hash[:page, { name: 'page name' }, 'some key', 123] + + assert_deprecated { post :render_body, params.dup } assert_equal params.to_query, @response.body end def test_document_body_and_params_with_post - post :test_params, :id => 1 - assert_equal("{\"id\"=>\"1\", \"controller\"=>\"test_case_test/test\", \"action\"=>\"test_params\"}", @response.body) + post :test_params, params: { id: 1 } + assert_equal({"id"=>"1", "controller"=>"test_case_test/test", "action"=>"test_params"}, ::JSON.parse(@response.body)) end def test_document_body_with_post - post :render_body, "document body" + post :render_body, body: "document body" + assert_equal "document body", @response.body + end + + def test_deprecated_document_body_with_post + assert_deprecated { post :render_body, "document body" } assert_equal "document body", @response.body end def test_document_body_with_put - put :render_body, "document body" + put :render_body, body: "document body" + assert_equal "document body", @response.body + end + + def test_deprecated_document_body_with_put + assert_deprecated { put :render_body, "document body" } assert_equal "document body", @response.body end @@ -221,25 +257,42 @@ XML assert_equal 200, @response.status end - def test_head_params_as_string - assert_raise(NoMethodError) { head :test_params, "document body", :id => 10 } - end - def test_process_without_flash process :set_flash assert_equal '><', flash['test'] end + def test_deprecated_process_with_flash + assert_deprecated { process :set_flash, "GET", nil, nil, { "test" => "value" } } + assert_equal '>value<', flash['test'] + end + def test_process_with_flash - process :set_flash, "GET", nil, nil, { "test" => "value" } + process :set_flash, + method: "GET", + flash: { "test" => "value" } assert_equal '>value<', flash['test'] end + def test_deprecated_process_with_flash_now + assert_deprecated { process :set_flash_now, "GET", nil, nil, { "test_now" => "value_now" } } + assert_equal '>value_now<', flash['test_now'] + end + def test_process_with_flash_now - process :set_flash_now, "GET", nil, nil, { "test_now" => "value_now" } + process :set_flash_now, + method: "GET", + flash: { "test_now" => "value_now" } assert_equal '>value_now<', flash['test_now'] end + def test_process_delete_flash + process :set_flash + process :delete_flash + assert_empty flash + assert_empty session + end + def test_process_with_session process :set_session assert_equal 'A wonder', session['string'], "A value stored in the session should be available by string key" @@ -249,22 +302,48 @@ XML end def test_process_with_session_arg - process :no_op, "GET", nil, { 'string' => 'value1', :symbol => 'value2' } + assert_deprecated { process :no_op, "GET", nil, { 'string' => 'value1', symbol: 'value2' } } assert_equal 'value1', session['string'] assert_equal 'value1', session[:string] assert_equal 'value2', session['symbol'] assert_equal 'value2', session[:symbol] end + def test_process_with_session_kwarg + process :no_op, method: "GET", session: { 'string' => 'value1', symbol: 'value2' } + assert_equal 'value1', session['string'] + assert_equal 'value1', session[:string] + assert_equal 'value2', session['symbol'] + assert_equal 'value2', session[:symbol] + end + + def test_deprecated_process_merges_session_arg + session[:foo] = 'bar' + assert_deprecated { + get :no_op, nil, { bar: 'baz' } + } + assert_equal 'bar', session[:foo] + assert_equal 'baz', session[:bar] + end + def test_process_merges_session_arg session[:foo] = 'bar' - get :no_op, nil, { :bar => 'baz' } + get :no_op, session: { bar: 'baz' } assert_equal 'bar', session[:foo] assert_equal 'baz', session[:bar] end + def test_deprecated_merged_session_arg_is_retained_across_requests + assert_deprecated { + get :no_op, nil, { foo: 'bar' } + } + assert_equal 'bar', session[:foo] + get :no_op + assert_equal 'bar', session[:foo] + end + def test_merged_session_arg_is_retained_across_requests - get :no_op, nil, { :foo => 'bar' } + get :no_op, session: { foo: 'bar' } assert_equal 'bar', session[:foo] get :no_op assert_equal 'bar', session[:foo] @@ -272,7 +351,7 @@ XML def test_process_overwrites_existing_session_arg session[:foo] = 'bar' - get :no_op, nil, { :foo => 'baz' } + get :no_op, session: { foo: 'baz' } assert_equal 'baz', session[:foo] end @@ -299,19 +378,40 @@ XML assert_equal "/test_case_test/test/test_uri", @response.body end + def test_process_with_symbol_method + process :test_uri, method: :get + assert_equal "/test_case_test/test/test_uri", @response.body + end + + def test_deprecated_process_with_request_uri_with_params + assert_deprecated { process :test_uri, "GET", id: 7 } + assert_equal "/test_case_test/test/test_uri/7", @response.body + end + def test_process_with_request_uri_with_params - process :test_uri, "GET", :id => 7 + process :test_uri, + method: "GET", + params: { id: 7 } + assert_equal "/test_case_test/test/test_uri/7", @response.body end + def test_deprecated_process_with_request_uri_with_params_with_explicit_uri + @request.env['PATH_INFO'] = "/explicit/uri" + assert_deprecated { process :test_uri, "GET", id: 7 } + assert_equal "/explicit/uri", @response.body + end + def test_process_with_request_uri_with_params_with_explicit_uri @request.env['PATH_INFO'] = "/explicit/uri" - process :test_uri, "GET", :id => 7 + process :test_uri, method: "GET", params: { id: 7 } assert_equal "/explicit/uri", @response.body end def test_process_with_query_string - process :test_query_string, "GET", :q => 'test' + process :test_query_string, + method: "GET", + params: { q: 'test' } assert_equal "q=test", @response.body end @@ -323,36 +423,12 @@ XML end def test_multiple_calls - process :test_only_one_param, "GET", :left => true + process :test_only_one_param, method: "GET", params: { left: true } assert_equal "OK", @response.body - process :test_only_one_param, "GET", :right => true + process :test_only_one_param, method: "GET", params: { right: true } assert_equal "OK", @response.body end - def test_assigns - process :test_assigns - # assigns can be accessed using assigns(key) - # or assigns[key], where key is a string or - # a symbol - assert_equal "foo", assigns(:foo) - assert_equal "foo", assigns("foo") - assert_equal "foo", assigns[:foo] - assert_equal "foo", assigns["foo"] - - # but the assigned variable should not have its own keys stringified - expected_hash = { :foo => :bar } - assert_equal expected_hash, assigns(:foo_hash) - end - - def test_view_assigns - @controller = ViewAssignsController.new - process :test_assigns - assert_equal nil, assigns(:foo) - assert_equal nil, assigns[:foo] - assert_equal "bar", assigns(:bar) - assert_equal "bar", assigns[:bar] - end - def test_should_not_impose_childless_html_tags_in_xml process :test_xml_output @@ -368,21 +444,21 @@ XML end def test_assert_generates - assert_generates 'controller/action/5', :controller => 'controller', :action => 'action', :id => '5' - assert_generates 'controller/action/7', {:id => "7"}, {:controller => "controller", :action => "action"} - assert_generates 'controller/action/5', {:controller => "controller", :action => "action", :id => "5", :name => "bob"}, {}, {:name => "bob"} - assert_generates 'controller/action/7', {:id => "7", :name => "bob"}, {:controller => "controller", :action => "action"}, {:name => "bob"} - assert_generates 'controller/action/7', {:id => "7"}, {:controller => "controller", :action => "action", :name => "bob"}, {} + assert_generates 'controller/action/5', controller: 'controller', action: 'action', id: '5' + assert_generates 'controller/action/7', { id: "7" }, { controller: "controller", action: "action" } + assert_generates 'controller/action/5', { controller: "controller", action: "action", id: "5", name: "bob" }, {}, { name: "bob" } + assert_generates 'controller/action/7', { id: "7", name: "bob" }, { controller: "controller", action: "action" }, { name: "bob" } + assert_generates 'controller/action/7', { id: "7" }, { controller: "controller", action: "action", name: "bob" }, {} end def test_assert_routing - assert_routing 'content', :controller => 'content', :action => 'index' + assert_routing 'content', controller: 'content', action: 'index' end def test_assert_routing_with_method with_routing do |set| set.draw { resources(:content) } - assert_routing({ :method => 'post', :path => 'content' }, { :controller => 'content', :action => 'create' }) + assert_routing({ method: 'post', path: 'content' }, { controller: 'content', action: 'create' }) end end @@ -394,30 +470,88 @@ XML end end - assert_routing 'admin/user', :controller => 'admin/user', :action => 'index' + assert_routing 'admin/user', controller: 'admin/user', action: 'index' end end def test_assert_routing_with_glob with_routing do |set| set.draw { get('*path' => "pages#show") } - assert_routing('/company/about', { :controller => 'pages', :action => 'show', :path => 'company/about' }) + assert_routing('/company/about', { controller: 'pages', action: 'show', path: 'company/about' }) end end + def test_deprecated_params_passing + assert_deprecated { + get :test_params, page: { name: "Page name", month: '4', year: '2004', day: '6' } + } + parsed_params = ::JSON.parse(@response.body) + assert_equal( + { + 'controller' => 'test_case_test/test', 'action' => 'test_params', + 'page' => { 'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6' } + }, + parsed_params + ) + end + def test_params_passing - get :test_params, :page => {:name => "Page name", :month => '4', :year => '2004', :day => '6'} + get :test_params, params: { + page: { + name: "Page name", + month: '4', + year: '2004', + day: '6' + } + } + parsed_params = ::JSON.parse(@response.body) + assert_equal( + { + 'controller' => 'test_case_test/test', 'action' => 'test_params', + 'page' => { 'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6' } + }, + parsed_params + ) + end + + def test_query_param_named_action + get :test_query_parameters, params: {action: 'foobar'} + parsed_params = JSON.parse(@response.body) + assert_equal({'action' => 'foobar'}, parsed_params) + end + + def test_request_param_named_action + post :test_request_parameters, params: {action: 'foobar'} parsed_params = eval(@response.body) + assert_equal({'action' => 'foobar'}, parsed_params) + end + + def test_kwarg_params_passing_with_session_and_flash + get :test_params, params: { + page: { + name: "Page name", + month: '4', + year: '2004', + day: '6' + } + }, session: { 'foo' => 'bar' }, flash: { notice: 'created' } + + parsed_params = ::JSON.parse(@response.body) assert_equal( {'controller' => 'test_case_test/test', 'action' => 'test_params', 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}}, parsed_params ) + + assert_equal 'bar', session[:foo] + assert_equal 'created', flash[:notice] end def test_params_passing_with_fixnums - get :test_params, :page => {:name => "Page name", :month => 4, :year => 2004, :day => 6} - parsed_params = eval(@response.body) + get :test_params, params: { + page: { name: "Page name", month: 4, year: 2004, day: 6 } + } + parsed_params = ::JSON.parse(@response.body) assert_equal( {'controller' => 'test_case_test/test', 'action' => 'test_params', 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}}, @@ -426,18 +560,28 @@ XML end def test_params_passing_with_fixnums_when_not_html_request - get :test_params, :format => 'json', :count => 999 - parsed_params = eval(@response.body) + get :test_params, params: { format: 'json', count: 999 } + parsed_params = ::JSON.parse(@response.body) assert_equal( {'controller' => 'test_case_test/test', 'action' => 'test_params', - 'format' => 'json', 'count' => 999 }, + 'format' => 'json', 'count' => '999' }, parsed_params ) end def test_params_passing_path_parameter_is_string_when_not_html_request - get :test_params, :format => 'json', :id => 1 - parsed_params = eval(@response.body) + get :test_params, params: { format: 'json', id: 1 } + parsed_params = ::JSON.parse(@response.body) + assert_equal( + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'format' => 'json', 'id' => '1' }, + parsed_params + ) + end + + def test_deprecated_params_passing_path_parameter_is_string_when_not_html_request + assert_deprecated { get :test_params, format: 'json', id: 1 } + parsed_params = ::JSON.parse(@response.body) assert_equal( {'controller' => 'test_case_test/test', 'action' => 'test_params', 'format' => 'json', 'id' => '1' }, @@ -447,9 +591,11 @@ XML def test_params_passing_with_frozen_values assert_nothing_raised do - get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze, :deepfreeze => { :frozen => 'icy'.freeze }.freeze + get :test_params, params: { + frozen: 'icy'.freeze, frozens: ['icy'.freeze].freeze, deepfreeze: { frozen: 'icy'.freeze }.freeze + } end - parsed_params = eval(@response.body) + parsed_params = ::JSON.parse(@response.body) assert_equal( {'controller' => 'test_case_test/test', 'action' => 'test_params', 'frozen' => 'icy', 'frozens' => ['icy'], 'deepfreeze' => { 'frozen' => 'icy' }}, @@ -458,8 +604,8 @@ XML end def test_params_passing_doesnt_modify_in_place - page = {:name => "Page name", :month => 4, :year => 2004, :day => 6} - get :test_params, :page => page + page = { name: "Page name", month: 4, year: 2004, day: 6 } + get :test_params, params: { page: page } assert_equal 2004, page[:year] end @@ -481,29 +627,61 @@ XML assert_equal "application/json", parsed_env["CONTENT_TYPE"] end + def test_mutating_content_type_headers_for_plain_text_files_sets_the_header + @request.headers['Content-Type'] = 'text/plain' + post :render_body, params: { name: 'foo.txt' } + + assert_equal 'text/plain', @request.headers['Content-type'] + assert_equal 'foo.txt', @request.request_parameters[:name] + assert_equal 'render_body', @request.path_parameters[:action] + end + + def test_mutating_content_type_headers_for_html_files_sets_the_header + @request.headers['Content-Type'] = 'text/html' + post :render_body, params: { name: 'foo.html' } + + assert_equal 'text/html', @request.headers['Content-type'] + assert_equal 'foo.html', @request.request_parameters[:name] + assert_equal 'render_body', @request.path_parameters[:action] + end + + def test_mutating_content_type_headers_for_non_registered_mime_type_raises_an_error + assert_raises(RuntimeError) do + @request.headers['Content-Type'] = 'type/fake' + post :render_body, params: { name: 'foo.fake' } + end + end + def test_id_converted_to_string - get :test_params, :id => 20, :foo => Object.new + get :test_params, params: { + id: 20, foo: Object.new + } + assert_kind_of String, @request.path_parameters[:id] + end + + def test_deprecared_id_converted_to_string + assert_deprecated { get :test_params, id: 20, foo: Object.new} assert_kind_of String, @request.path_parameters[:id] end def test_array_path_parameter_handled_properly with_routing do |set| set.draw do - get 'file/*path', :to => 'test_case_test/test#test_params' + get 'file/*path', to: 'test_case_test/test#test_params' get ':controller/:action' end - get :test_params, :path => ['hello', 'world'] + get :test_params, params: { path: ['hello', 'world'] } 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 + get :test_params, params: { id: 20, foo: Object.new } # All elements of path_parameters should use Symbol keys - @request.path_parameters.keys.each do |key| + @request.path_parameters.each_key do |key| assert_kind_of Symbol, key end end @@ -532,19 +710,51 @@ XML end def test_header_properly_reset_after_remote_http_request - xhr :get, :test_params + get :test_params, xhr: true assert_nil @request.env['HTTP_X_REQUESTED_WITH'] assert_nil @request.env['HTTP_ACCEPT'] end - def test_header_properly_reset_after_get_request - get :test_params - @request.recycle! - assert_nil @request.instance_variable_get("@request_method") + def test_deprecated_xhr_with_params + assert_deprecated { xhr :get, :test_params, params: { id: 1 } } + + assert_equal({"id"=>"1", "controller"=>"test_case_test/test", "action"=>"test_params"}, ::JSON.parse(@response.body)) + end + + def test_xhr_with_params + get :test_params, params: { id: 1 }, xhr: true + + assert_equal({"id"=>"1", "controller"=>"test_case_test/test", "action"=>"test_params"}, ::JSON.parse(@response.body)) + end + + def test_xhr_with_session + get :set_session, xhr: true + + assert_equal 'A wonder', session['string'], "A value stored in the session should be available by string key" + assert_equal 'A wonder', session[:string], "Test session hash should allow indifferent access" + assert_equal 'it works', session['symbol'], "Test session hash should allow indifferent access" + assert_equal 'it works', session[:symbol], "Test session hash should allow indifferent access" + end + + def test_deprecated_xhr_with_session + assert_deprecated { xhr :get, :set_session } + + assert_equal 'A wonder', session['string'], "A value stored in the session should be available by string key" + assert_equal 'A wonder', session[:string], "Test session hash should allow indifferent access" + assert_equal 'it works', session['symbol'], "Test session hash should allow indifferent access" + assert_equal 'it works', session[:symbol], "Test session hash should allow indifferent access" + end + + def test_deprecated_params_reset_between_post_requests + assert_deprecated { post :no_op, foo: "bar" } + assert_equal "bar", @request.params[:foo] + + post :no_op + assert @request.params[:foo].blank? end def test_params_reset_between_post_requests - post :no_op, :foo => "bar" + post :no_op, params: { foo: "bar" } assert_equal "bar", @request.params[:foo] post :no_op @@ -552,15 +762,15 @@ XML end def test_filtered_parameters_reset_between_requests - get :no_op, :foo => "bar" + get :no_op, params: { foo: "bar" } assert_equal "bar", @request.filtered_parameters[:foo] - get :no_op, :foo => "baz" + get :no_op, params: { foo: "baz" } assert_equal "baz", @request.filtered_parameters[:foo] end def test_path_params_reset_between_request - get :test_params, :id => "foo" + get :test_params, params: { id: "foo" } assert_equal "foo", @request.path_parameters[:id] get :test_params @@ -581,19 +791,38 @@ XML end def test_request_format - get :test_format, :format => 'html' + get :test_format, params: { format: 'html' } + assert_equal 'text/html', @response.body + + get :test_format, params: { format: 'json' } + assert_equal 'application/json', @response.body + + get :test_format, params: { format: 'xml' } + assert_equal 'application/xml', @response.body + + get :test_format + assert_equal 'text/html', @response.body + end + + def test_request_format_kwarg + get :test_format, format: 'html' assert_equal 'text/html', @response.body - get :test_format, :format => 'json' + get :test_format, format: 'json' assert_equal 'application/json', @response.body - get :test_format, :format => 'xml' + get :test_format, format: 'xml' assert_equal 'application/xml', @response.body get :test_format assert_equal 'text/html', @response.body end + def test_request_format_kwarg_overrides_params + get :test_format, format: 'json', params: { format: 'html' } + assert_equal 'application/json', @response.body + end + def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set cookies['foo'] = 'bar' get :no_op @@ -647,10 +876,10 @@ XML end def test_fixture_path_is_accessed_from_self_instead_of_active_support_test_case - TestCaseTest.stubs(:fixture_path).returns(FILES_DIR) - - uploaded_file = fixture_file_upload('/mona_lisa.jpg', 'image/png') - assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read + TestCaseTest.stub :fixture_path, FILES_DIR do + uploaded_file = fixture_file_upload('/mona_lisa.jpg', 'image/png') + assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read + end end def test_test_uploaded_file_with_binary @@ -677,27 +906,46 @@ XML assert_equal File.open(path, READ_PLAIN).read, plain_file_upload.read end + def test_fixture_file_upload_should_be_able_access_to_tempfile + file = fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg") + assert file.respond_to?(:tempfile), "expected tempfile should respond on fixture file object, got nothing" + end + def test_fixture_file_upload - post :test_file_upload, :file => fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg") + post :test_file_upload, + params: { + file: fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg") + } assert_equal '159528', @response.body end def test_fixture_file_upload_relative_to_fixture_path - TestCaseTest.stubs(:fixture_path).returns(FILES_DIR) - uploaded_file = fixture_file_upload("mona_lisa.jpg", "image/jpg") - assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read + TestCaseTest.stub :fixture_path, FILES_DIR do + uploaded_file = fixture_file_upload("mona_lisa.jpg", "image/jpg") + assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read + end end def test_fixture_file_upload_ignores_nil_fixture_path - TestCaseTest.stubs(:fixture_path).returns(nil) uploaded_file = fixture_file_upload("#{FILES_DIR}/mona_lisa.jpg", "image/jpg") assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read end + def test_deprecated_action_dispatch_uploaded_file_upload + filename = 'mona_lisa.jpg' + path = "#{FILES_DIR}/#{filename}" + assert_deprecated { + post :test_file_upload, file: Rack::Test::UploadedFile.new(path, "image/jpg", true) + } + assert_equal '159528', @response.body + end + def test_action_dispatch_uploaded_file_upload filename = 'mona_lisa.jpg' path = "#{FILES_DIR}/#{filename}" - post :test_file_upload, :file => ActionDispatch::Http::UploadedFile.new(:filename => path, :type => "image/jpg", :tempfile => File.open(path)) + post :test_file_upload, params: { + file: Rack::Test::UploadedFile.new(path, "image/jpg", true) + } assert_equal '159528', @response.body end @@ -720,6 +968,98 @@ XML end end +class ResponseDefaultHeadersTest < ActionController::TestCase + class TestController < ActionController::Base + def remove_header + headers.delete params[:header] + head :ok, 'C' => '3' + end + + # Render a head response, but don't touch default headers + def leave_alone + head :ok + end + end + + def before_setup + @original = ActionDispatch::Response.default_headers + @defaults = { 'A' => '1', 'B' => '2' } + ActionDispatch::Response.default_headers = @defaults + super + end + + teardown do + ActionDispatch::Response.default_headers = @original + end + + def setup + super + @controller = TestController.new + @request.env['PATH_INFO'] = nil + @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| + r.draw do + get ':controller(/:action(/:id))' + end + end + end + + test "response contains default headers" do + get :leave_alone + + # Response headers start out with the defaults + assert_equal @defaults.merge('Content-Type' => 'text/html'), response.headers + end + + test "response deletes a default header" do + get :remove_header, params: { header: 'A' } + assert_response :ok + + # After a request, the response in the test case doesn't have the + # defaults merged on top again. + assert_not_includes response.headers, 'A' + assert_includes response.headers, 'B' + assert_includes response.headers, 'C' + end +end + +module EngineControllerTests + class Engine < ::Rails::Engine + isolate_namespace EngineControllerTests + + routes.draw do + get '/' => 'bar#index' + end + end + + class BarController < ActionController::Base + def index + render plain: 'bar' + end + end + + class BarControllerTest < ActionController::TestCase + tests BarController + + def test_engine_controller_route + get :index + assert_equal @response.body, 'bar' + end + end + + class BarControllerTestWithExplicitRouteSet < ActionController::TestCase + tests BarController + + def setup + @routes = Engine.routes + end + + def test_engine_controller_route + get :index + assert_equal @response.body, 'bar' + end + end +end + class InferringClassNameTest < ActionController::TestCase def test_determine_controller_class assert_equal ContentController, determine_class("ContentControllerTest") @@ -770,7 +1110,7 @@ class NamedRoutesControllerTest < ActionController::TestCase with_routing do |set| set.draw { resources :contents } assert_equal 'http://test.host/contents/new', new_content_url - assert_equal 'http://test.host/contents/1', content_url(:id => 1) + assert_equal 'http://test.host/contents/1', content_url(id: 1) end end end @@ -779,7 +1119,7 @@ class AnonymousControllerTest < ActionController::TestCase def setup @controller = Class.new(ActionController::Base) do def index - render :text => params[:controller] + render plain: params[:controller] end end.new @@ -800,29 +1140,29 @@ class RoutingDefaultsTest < ActionController::TestCase def setup @controller = Class.new(ActionController::Base) do def post - render :text => request.fullpath + render plain: request.fullpath end def project - render :text => request.fullpath + render plain: request.fullpath end end.new @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| r.draw do - get '/posts/:id', :to => 'anonymous#post', :bucket_type => 'post' - get '/projects/:id', :to => 'anonymous#project', :defaults => { :bucket_type => 'project' } + get '/posts/:id', to: 'anonymous#post', bucket_type: 'post' + get '/projects/:id', to: 'anonymous#project', defaults: { bucket_type: 'project' } end end end def test_route_option_can_be_passed_via_process - get :post, :id => 1, :bucket_type => 'post' + get :post, params: { id: 1, bucket_type: 'post'} assert_equal '/posts/1', @response.body end def test_route_default_is_not_required_for_building_request_uri - get :project, :id => 2 + get :project, params: { id: 2 } assert_equal '/projects/2', @response.body end end diff --git a/actionpack/test/controller/url_for_integration_test.rb b/actionpack/test/controller/url_for_integration_test.rb index 24a09222b1..dfc2712e3e 100644 --- a/actionpack/test/controller/url_for_integration_test.rb +++ b/actionpack/test/controller/url_for_integration_test.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 require 'abstract_unit' require 'controller/fake_controllers' require 'active_support/core_ext/object/with_options' @@ -159,6 +158,7 @@ module ActionPack ['/posts/ping',[ { :controller => 'posts', :action => 'ping' }]], ['/posts/show/1',[ { :controller => 'posts', :action => 'show', :id => '1' }]], + ['/posts/show/1',[ { :controller => 'posts', :action => 'show', :id => '1', :format => '' }]], ['/posts',[ { :controller => 'posts' }]], ['/posts',[ { :controller => 'posts', :action => 'index' }]], ['/posts/create',[ { :action => 'create' }, {:day=>nil, :month=>nil, :controller=>"posts", :action=>"show_date"}, '/blog']], diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index 969129d9ba..78e883f134 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -25,14 +25,13 @@ module AbstractController path = klass.new.fun_path({:controller => :articles, :baz => "baz", - :zot => "zot", - :only_path => true }) + :zot => "zot"}) # :bar key isn't provided assert_equal '/foo/zot', path end - def add_host! - W.default_url_options[:host] = 'www.basecamphq.com' + def add_host!(app = W) + app.default_url_options[:host] = 'www.basecamphq.com' end def add_port! @@ -55,6 +54,20 @@ module AbstractController ) end + def test_nil_anchor + assert_equal( + '/c/a', + W.new.url_for(only_path: true, controller: 'c', action: 'a', anchor: nil) + ) + end + + def test_false_anchor + assert_equal( + '/c/a', + W.new.url_for(only_path: true, controller: 'c', action: 'a', anchor: false) + ) + end + def test_anchor_should_call_to_param assert_equal('/c/a#anchor', W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :anchor => Struct.new(:to_param).new('anchor')) @@ -242,6 +255,20 @@ module AbstractController ) end + def test_relative_url_root_is_respected_with_environment_variable + # `config.relative_url_root` is set by ENV['RAILS_RELATIVE_URL_ROOT'] + w = Class.new { + config = ActionDispatch::Routing::RouteSet::Config.new '/subdir' + r = ActionDispatch::Routing::RouteSet.new(config) + r.draw { get ':controller(/:action(/:id(.:format)))' } + include r.url_helpers + } + add_host!(w) + assert_equal('https://www.basecamphq.com/subdir/c/a/i', + w.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https') + ) + end + def test_named_routes with_routing do |set| set.draw do @@ -277,6 +304,13 @@ module AbstractController end end + def test_using_nil_script_name_properly_concats_with_original_script_name + add_host! + assert_equal('https://www.basecamphq.com/subdir/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https', :script_name => nil, :original_script_name => '/subdir') + ) + end + def test_only_path with_routing do |set| set.draw do @@ -291,7 +325,7 @@ module AbstractController assert_equal '/brave/new/world', controller.url_for(:controller => 'brave', :action => 'new', :id => 'world', :only_path => true) - 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(:user => 'alabama', :host => 'unused')) assert_equal("/home/sweet/home/alabama", controller.home_path('alabama')) end end @@ -417,6 +451,26 @@ module AbstractController end end + def test_url_for_with_array_is_unmodified + with_routing do |set| + set.draw do + namespace :admin do + resources :posts + end + end + + kls = Class.new { include set.url_helpers } + kls.default_url_options[:host] = 'www.basecamphq.com' + + original_components = [:new, :admin, :post, { param: 'value' }] + components = original_components.dup + + kls.new.url_for(components) + + assert_equal(original_components, components) + end + end + private def extract_params(url) url.split('?', 2).last.split('&').sort diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index d9a1ae7d4f..5f2abc9606 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'controller/fake_controllers' -class UrlRewriterTests < ActiveSupport::TestCase +class UrlRewriterTests < ActionController::TestCase class Rewriter def initialize(request) @options = { @@ -16,7 +16,6 @@ class UrlRewriterTests < ActiveSupport::TestCase end def setup - @request = ActionController::TestRequest.new @params = {} @rewriter = Rewriter.new(@request) #.new(@request, @params) @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index d80b0e2da0..6d377c4691 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -5,16 +5,22 @@ class WebServiceTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base def assign_parameters if params[:full] - render :text => dump_params_keys + render plain: dump_params_keys else - render :text => (params.keys - ['controller', 'action']).sort.join(", ") + render plain: (params.keys - ['controller', 'action']).sort.join(", ") end end def dump_params_keys(hash = params) hash.keys.sort.inject("") do |s, k| value = hash[k] - value = Hash === value ? "(#{dump_params_keys(value)})" : "" + + if value.is_a?(Hash) || value.is_a?(ActionController::Parameters) + value = "(#{dump_params_keys(value)})" + else + value = "" + end + s << ", " unless s.empty? s << "#{k}#{value}" end @@ -35,7 +41,9 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_post_json with_test_route_set do - post "/", '{"entry":{"summary":"content..."}}', 'CONTENT_TYPE' => 'application/json' + post "/", + params: '{"entry":{"summary":"content..."}}', + headers: { 'CONTENT_TYPE' => 'application/json' } assert_equal 'entry', @controller.response.body assert @controller.params.has_key?(:entry) @@ -45,7 +53,9 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_put_json with_test_route_set do - put "/", '{"entry":{"summary":"content..."}}', 'CONTENT_TYPE' => 'application/json' + put "/", + params: '{"entry":{"summary":"content..."}}', + headers: { 'CONTENT_TYPE' => 'application/json' } assert_equal 'entry', @controller.response.body assert @controller.params.has_key?(:entry) @@ -55,9 +65,10 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_register_and_use_json_simple with_test_route_set do - with_params_parsers Mime::JSON => Proc.new { |data| ActiveSupport::JSON.decode(data)['request'].with_indifferent_access } do - post "/", '{"request":{"summary":"content...","title":"JSON"}}', - 'CONTENT_TYPE' => 'application/json' + with_params_parsers Mime[:json] => Proc.new { |data| ActiveSupport::JSON.decode(data)['request'].with_indifferent_access } do + post "/", + params: '{"request":{"summary":"content...","title":"JSON"}}', + headers: { 'CONTENT_TYPE' => 'application/json' } assert_equal 'summary, title', @controller.response.body assert @controller.params.has_key?(:summary) @@ -70,26 +81,44 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_use_json_with_empty_request with_test_route_set do - assert_nothing_raised { post "/", "", 'CONTENT_TYPE' => 'application/json' } + assert_nothing_raised { post "/", headers: { 'CONTENT_TYPE' => 'application/json' } } assert_equal '', @controller.response.body end end def test_dasherized_keys_as_json with_test_route_set do - post "/?full=1", '{"first-key":{"sub-key":"..."}}', 'CONTENT_TYPE' => 'application/json' + post "/?full=1", + params: '{"first-key":{"sub-key":"..."}}', + headers: { 'CONTENT_TYPE' => 'application/json' } assert_equal 'action, controller, first-key(sub-key), full', @controller.response.body assert_equal "...", @controller.params['first-key']['sub-key'] end end + def test_parsing_json_doesnot_rescue_exception + req = Class.new(ActionDispatch::Request) do + def params_parsers + { Mime[:json] => Proc.new { |data| raise Interrupt } } + end + + def content_length; get_header('rack.input').length; end + end.new({ 'rack.input' => StringIO.new('{"title":"JSON"}}'), 'CONTENT_TYPE' => 'application/json' }) + + assert_raises(Interrupt) do + req.request_parameters + end + end + private def with_params_parsers(parsers = {}) old_session = @integration_session - @app = ActionDispatch::ParamsParser.new(app.routes, parsers) + original_parsers = ActionDispatch::Request.parameter_parsers + ActionDispatch::Request.parameter_parsers = original_parsers.merge parsers reset! yield ensure + ActionDispatch::Request.parameter_parsers = original_parsers @integration_session = old_session end |