aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test/controller
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/test/controller')
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb16
-rw-r--r--actionpack/test/controller/caching_test.rb35
-rw-r--r--actionpack/test/controller/filters_test.rb27
-rw-r--r--actionpack/test/controller/flash_hash_test.rb10
-rw-r--r--actionpack/test/controller/flash_test.rb35
-rw-r--r--actionpack/test/controller/http_digest_authentication_test.rb2
-rw-r--r--actionpack/test/controller/http_token_authentication_test.rb2
-rw-r--r--actionpack/test/controller/live_stream_test.rb85
-rw-r--r--actionpack/test/controller/localized_templates_test.rb11
-rw-r--r--actionpack/test/controller/log_subscriber_test.rb11
-rw-r--r--actionpack/test/controller/mime/respond_to_test.rb275
-rw-r--r--actionpack/test/controller/new_base/render_body_test.rb170
-rw-r--r--actionpack/test/controller/new_base/render_html_test.rb190
-rw-r--r--actionpack/test/controller/new_base/render_plain_test.rb168
-rw-r--r--actionpack/test/controller/new_base/render_streaming_test.rb4
-rw-r--r--actionpack/test/controller/new_base/render_template_test.rb4
-rw-r--r--actionpack/test/controller/new_base/render_text_test.rb36
-rw-r--r--actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb30
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb26
-rw-r--r--actionpack/test/controller/parameters/parameters_require_test.rb10
-rw-r--r--actionpack/test/controller/params_wrapper_test.rb20
-rw-r--r--actionpack/test/controller/render_js_test.rb2
-rw-r--r--actionpack/test/controller/render_json_test.rb4
-rw-r--r--actionpack/test/controller/render_test.rb2
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb104
-rw-r--r--actionpack/test/controller/required_params_test.rb8
-rw-r--r--actionpack/test/controller/resources_test.rb5
-rw-r--r--actionpack/test/controller/routing_test.rb13
-rw-r--r--actionpack/test/controller/send_file_test.rb16
-rw-r--r--actionpack/test/controller/test_case_test.rb31
-rw-r--r--actionpack/test/controller/url_for_test.rb3
31 files changed, 1228 insertions, 127 deletions
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index ba4cffcd3e..b6b5a218cc 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -444,22 +444,18 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_assert_response_uses_exception_message
@controller = AssertResponseWithUnexpectedErrorController.new
- get :index
+ e = assert_raise RuntimeError, 'Expected non-success response' do
+ get :index
+ end
assert_response :success
- flunk 'Expected non-success response'
- rescue RuntimeError => e
- assert e.message.include?('FAIL')
+ assert_includes 'FAIL', e.message
end
def test_assert_response_failure_response_with_no_exception
@controller = AssertResponseWithUnexpectedErrorController.new
get :show
- assert_response :success
- flunk 'Expected non-success response'
- rescue ActiveSupport::TestCase::Assertion
- # success
- rescue
- flunk "assert_response failed to handle failure response with missing, but optional, exception."
+ assert_response 500
+ assert_equal 'Boom', response.body
end
end
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 57b45b8f7b..58a86ce9af 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -164,6 +164,13 @@ class FunctionalCachingController < CachingController
end
end
+ def formatted_fragment_cached_with_variant
+ respond_to do |format|
+ format.html.phone
+ format.html
+ end
+ end
+
def fragment_cached_without_digest
end
end
@@ -190,7 +197,7 @@ CACHED
assert_equal expected_body, @response.body
assert_equal "This bit's fragment cached",
- @store.read("views/test.host/functional_caching/fragment_cached/#{template_digest("functional_caching/fragment_cached", "html")}")
+ @store.read("views/test.host/functional_caching/fragment_cached/#{template_digest("functional_caching/fragment_cached")}")
end
def test_fragment_caching_in_partials
@@ -199,7 +206,7 @@ CACHED
assert_match(/Old fragment caching in a partial/, @response.body)
assert_match("Old fragment caching in a partial",
- @store.read("views/test.host/functional_caching/html_fragment_cached_with_partial/#{template_digest("functional_caching/_partial", "html")}"))
+ @store.read("views/test.host/functional_caching/html_fragment_cached_with_partial/#{template_digest("functional_caching/_partial")}"))
end
def test_skipping_fragment_cache_digesting
@@ -217,7 +224,7 @@ CACHED
assert_match(/Some inline content/, @response.body)
assert_match(/Some cached content/, @response.body)
assert_match("Some cached content",
- @store.read("views/test.host/functional_caching/inline_fragment_cached/#{template_digest("functional_caching/inline_fragment_cached", "html")}"))
+ @store.read("views/test.host/functional_caching/inline_fragment_cached/#{template_digest("functional_caching/inline_fragment_cached")}"))
end
def test_html_formatted_fragment_caching
@@ -228,7 +235,7 @@ CACHED
assert_equal expected_body, @response.body
assert_equal "<p>ERB</p>",
- @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached", "html")}")
+ @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached")}")
end
def test_xml_formatted_fragment_caching
@@ -239,12 +246,26 @@ CACHED
assert_equal expected_body, @response.body
assert_equal " <p>Builder</p>\n",
- @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached", "xml")}")
+ @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached")}")
+ end
+
+
+ def test_fragment_caching_with_variant
+ @request.variant = :phone
+
+ get :formatted_fragment_cached_with_variant, :format => "html"
+ assert_response :success
+ expected_body = "<body>\n<p>PHONE</p>\n</body>\n"
+
+ assert_equal expected_body, @response.body
+
+ assert_equal "<p>PHONE</p>",
+ @store.read("views/test.host/functional_caching/formatted_fragment_cached_with_variant/#{template_digest("functional_caching/formatted_fragment_cached_with_variant")}")
end
private
- def template_digest(name, format)
- ActionView::Digestor.digest(name, format, @controller.lookup_context)
+ def template_digest(name)
+ ActionView::Digestor.digest(name: name, finder: @controller.lookup_context)
end
end
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 3b5d7ef446..c87494aa64 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -225,6 +225,10 @@ class FilterTest < ActionController::TestCase
skip_before_filter :clean_up_tmp, if: -> { true }
end
+ class ClassController < ConditionalFilterController
+ before_filter ConditionalClassFilter
+ end
+
class PrependingController < TestController
prepend_before_filter :wonderful_life
# skip_before_filter :fire_flash
@@ -610,6 +614,18 @@ class FilterTest < ActionController::TestCase
assert_equal %w( ensure_login ), assigns["ran_filter"]
end
+ def test_skipping_class_filters
+ test_process(ClassController)
+ assert_equal true, assigns["ran_class_filter"]
+
+ skipping_class_controller = Class.new(ClassController) do
+ skip_before_filter ConditionalClassFilter
+ end
+
+ test_process(skipping_class_controller)
+ assert_nil assigns['ran_class_filter']
+ end
+
def test_running_collection_condition_filters
test_process(ConditionalCollectionFilterController)
assert_equal %w( ensure_login ), assigns["ran_filter"]
@@ -893,17 +909,6 @@ class ControllerWithFilterInstance < PostsController
around_filter YieldingFilter.new, :only => :raises_after
end
-class ControllerWithFilterMethod < PostsController
- class YieldingFilter < DefaultFilter
- def around(controller)
- yield
- raise After
- end
- end
-
- around_filter YieldingFilter.new.method(:around), :only => :raises_after
-end
-
class ControllerWithProcFilter < PostsController
around_filter(:only => :no_raise) do |c,b|
c.instance_variable_set(:"@before", true)
diff --git a/actionpack/test/controller/flash_hash_test.rb b/actionpack/test/controller/flash_hash_test.rb
index 5490d9394b..50b36a0567 100644
--- a/actionpack/test/controller/flash_hash_test.rb
+++ b/actionpack/test/controller/flash_hash_test.rb
@@ -67,6 +67,16 @@ module ActionDispatch
assert_equal({'flashes' => {'message' => 'Hello'}, 'discard' => %w[message]}, hash.to_session_value)
end
+ def test_from_session_value_on_json_serializer
+ decrypted_data = "{ \"session_id\":\"d98bdf6d129618fc2548c354c161cfb5\", \"flash\":{\"discard\":[], \"flashes\":{\"message\":\"hey you\"}} }"
+ 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"]
+ end
+
def test_empty?
assert @hash.empty?
@hash['zomg'] = 'bears'
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index c64ffef654..3720a920d0 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -174,14 +174,14 @@ class FlashTest < ActionController::TestCase
flash.update(:foo => :foo_indeed, :bar => :bar_indeed)
assert_equal(:foo_indeed, flash.discard(:foo)) # valid key passed
- assert_nil flash.discard(:unknown) # non existant key passed
- assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.discard().to_hash) # nothing passed
- assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.discard(nil).to_hash) # nothing passed
+ assert_nil flash.discard(:unknown) # non existent key passed
+ assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.discard().to_hash) # nothing passed
+ assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.discard(nil).to_hash) # nothing passed
assert_equal(:foo_indeed, flash.keep(:foo)) # valid key passed
- assert_nil flash.keep(:unknown) # non existant key passed
- assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.keep().to_hash) # nothing passed
- assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.keep(nil).to_hash) # nothing passed
+ assert_nil flash.keep(:unknown) # non existent key passed
+ assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.keep().to_hash) # nothing passed
+ assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.keep(nil).to_hash) # nothing passed
end
def test_redirect_to_with_alert
@@ -210,20 +210,29 @@ class FlashTest < ActionController::TestCase
end
def test_redirect_to_with_adding_flash_types
- @controller.class.add_flash_types :foo
+ original_controller = @controller
+ test_controller_with_flash_type_foo = Class.new(TestController) do
+ add_flash_types :foo
+ end
+ @controller = test_controller_with_flash_type_foo.new
get :redirect_with_foo_flash
assert_equal "for great justice", @controller.send(:flash)[:foo]
+ ensure
+ @controller = original_controller
end
- class SubclassesTestController < TestController; end
-
def test_add_flash_type_to_subclasses
- TestController.add_flash_types :foo
- assert SubclassesTestController._flash_types.include?(:foo)
+ test_controller_with_flash_type_foo = Class.new(TestController) do
+ add_flash_types :foo
+ end
+ subclass_controller_with_no_flash_type = Class.new(test_controller_with_flash_type_foo)
+ assert subclass_controller_with_no_flash_type._flash_types.include?(:foo)
end
- def test_do_not_add_flash_type_to_parent_class
- SubclassesTestController.add_flash_types :bar
+ def test_does_not_add_flash_type_to_parent_class
+ Class.new(TestController) do
+ add_flash_types :bar
+ end
assert_not TestController._flash_types.include?(:bar)
end
end
diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb
index 9f1c168209..52a0bc9aa3 100644
--- a/actionpack/test/controller/http_digest_authentication_test.rb
+++ b/actionpack/test/controller/http_digest_authentication_test.rb
@@ -21,7 +21,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
def authenticate
authenticate_or_request_with_http_digest("SuperSecret") do |username|
- # Return the password
+ # Returns the password
USERS[username]
end
end
diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb
index ebf6d224aa..86b94652ce 100644
--- a/actionpack/test/controller/http_token_authentication_test.rb
+++ b/actionpack/test/controller/http_token_authentication_test.rb
@@ -21,7 +21,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase
private
def authenticate
- authenticate_or_request_with_http_token do |token, options|
+ authenticate_or_request_with_http_token do |token, _|
token == 'lifo'
end
end
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 0a431270b5..947f64176b 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/concurrency/latch'
+Thread.abort_on_exception = true
module ActionController
class SSETest < ActionController::TestCase
@@ -43,9 +44,7 @@ module ActionController
tests SSETestController
def wait_for_response_stream_close
- while !response.stream.closed?
- sleep 0.01
- end
+ response.body
end
def test_basic_sse
@@ -91,6 +90,9 @@ module ActionController
end
class LiveStreamTest < ActionController::TestCase
+ class Exception < StandardError
+ end
+
class TestController < ActionController::Base
include ActionController::Live
@@ -100,6 +102,12 @@ module ActionController
'test'
end
+ def set_cookie
+ cookies[:hello] = "world"
+ response.stream.write "hello world"
+ response.close
+ end
+
def render_text
render :text => 'zomg'
end
@@ -145,6 +153,11 @@ module ActionController
render 'doesntexist'
end
+ def exception_in_view_after_commit
+ response.stream.write ""
+ render 'doesntexist'
+ end
+
def exception_with_callback
response.headers['Content-Type'] = 'text/event-stream'
@@ -153,32 +166,33 @@ module ActionController
response.stream.close
end
+ response.stream.write "" # make sure the response is committed
raise 'An exception occurred...'
end
+ def exception_in_controller
+ raise Exception, 'Exception in controller'
+ end
+
+ def bad_request_error
+ raise ActionController::BadRequest
+ end
+
def exception_in_exception_callback
response.headers['Content-Type'] = 'text/event-stream'
response.stream.on_error do
raise 'We need to go deeper.'
end
+ response.stream.write ''
response.stream.write params[:widget][:didnt_check_for_nil]
end
end
tests TestController
- class TestResponse < Live::Response
- def recycle!
- initialize
- end
- end
-
- def build_response
- TestResponse.new
- end
-
def assert_stream_closed
assert response.stream.closed?, 'stream should be closed'
+ assert response.sent?, 'stream should be sent'
end
def capture_log_output
@@ -192,6 +206,13 @@ module ActionController
end
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)
@@ -213,6 +234,7 @@ module ActionController
@controller.response = @response
t = Thread.new(@response) { |resp|
+ resp.await_commit
resp.stream.each do |part|
assert_equal parts.shift, part
ol = @controller.latch
@@ -249,24 +271,34 @@ module ActionController
end
def test_exception_handling_html
- capture_log_output do |output|
+ assert_raises(ActionView::MissingTemplate) do
get :exception_in_view
+ end
+
+ capture_log_output do |output|
+ get :exception_in_view_after_commit
assert_match %r((window\.location = "/500\.html"</script></html>)$), response.body
assert_match 'Missing template test/doesntexist', output.rewind && output.read
assert_stream_closed
end
+ assert response.body
+ assert_stream_closed
end
def test_exception_handling_plain_text
- capture_log_output do |output|
+ assert_raises(ActionView::MissingTemplate) do
get :exception_in_view, format: :json
+ end
+
+ capture_log_output do |output|
+ get :exception_in_view_after_commit, format: :json
assert_equal '', response.body
assert_match 'Missing template test/doesntexist', output.rewind && output.read
assert_stream_closed
end
end
- def test_exception_callback
+ def test_exception_callback_when_committed
capture_log_output do |output|
get :exception_with_callback, format: 'text/event-stream'
assert_equal %(data: "500 Internal Server Error"\n\n), response.body
@@ -275,7 +307,19 @@ module ActionController
end
end
- def test_exceptions_raised_handling_exceptions
+ def test_exception_in_controller_before_streaming
+ assert_raises(ActionController::LiveStreamTest::Exception) do
+ get :exception_in_controller, format: 'text/event-stream'
+ end
+ end
+
+ def test_bad_request_in_controller_before_streaming
+ assert_raises(ActionController::BadRequest) do
+ get :bad_request_error, format: 'text/event-stream'
+ end
+ end
+
+ def test_exceptions_raised_handling_exceptions_and_committed
capture_log_output do |output|
get :exception_in_exception_callback, format: 'text/event-stream'
assert_equal '', response.body
@@ -295,4 +339,11 @@ module ActionController
assert_equal 304, @response.status.to_i
end
end
+
+ class BufferTest < ActionController::TestCase
+ def test_nil_callback
+ buf = ActionController::Live::Buffer.new nil
+ assert buf.call_on_error
+ end
+ end
end
diff --git a/actionpack/test/controller/localized_templates_test.rb b/actionpack/test/controller/localized_templates_test.rb
index 6b02eedaed..c95ef8a0c7 100644
--- a/actionpack/test/controller/localized_templates_test.rb
+++ b/actionpack/test/controller/localized_templates_test.rb
@@ -34,4 +34,15 @@ class LocalizedTemplatesTest < ActionController::TestCase
get :hello_world
assert_equal "Gutten Tag", @response.body
end
+
+ def test_localized_template_has_correct_header_with_no_format_in_template_name
+ old_locale = I18n.locale
+ I18n.locale = :it
+
+ get :hello_world
+ assert_equal "Ciao Mondo", @response.body
+ assert_equal "text/html", @response.content_type
+ ensure
+ I18n.locale = old_locale
+ end
end
diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb
index 075347be52..18037b3d2f 100644
--- a/actionpack/test/controller/log_subscriber_test.rb
+++ b/actionpack/test/controller/log_subscriber_test.rb
@@ -137,6 +137,17 @@ class ACLogSubscriberTest < ActionController::TestCase
assert_equal 'Parameters: {"id"=>"10"}', logs[1]
end
+ def test_multiple_process_with_parameters
+ get :show, :id => '10'
+ get :show, :id => '20'
+
+ wait
+
+ assert_equal 6, logs.size
+ assert_equal 'Parameters: {"id"=>"10"}', logs[1]
+ assert_equal 'Parameters: {"id"=>"20"}', logs[4]
+ end
+
def test_process_action_with_wrapped_parameters
@request.env['CONTENT_TYPE'] = 'application/json'
post :show, :id => '10', :name => 'jose'
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index 774dabe105..499c62cc35 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -146,6 +146,106 @@ class RespondToController < ActionController::Base
end
end
+ def variant_with_implicit_rendering
+ end
+
+ def variant_with_format_and_custom_render
+ request.variant = :mobile
+
+ respond_to do |type|
+ type.html { render text: "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" }
+ end
+ end
+ end
+
+ def variant_plus_none_for_format
+ respond_to do |format|
+ format.html do |variant|
+ variant.phone { render text: "phone" }
+ variant.none
+ end
+ end
+ end
+
+ 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" }
+ end
+ end
+
+ def variant_inline_syntax_without_block
+ respond_to do |format|
+ format.js
+ format.html.none
+ format.html.phone
+ end
+ end
+
+ def variant_any
+ respond_to do |format|
+ format.html do |variant|
+ variant.any(:tablet, :phablet){ render text: "any" }
+ variant.phone { render text: "phone" }
+ end
+ end
+ end
+
+ def variant_any_any
+ respond_to do |format|
+ format.html do |variant|
+ variant.any { render text: "any" }
+ variant.phone { render text: "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" }
+ end
+ end
+
+ def variant_inline_any_any
+ respond_to do |format|
+ format.html.phone { render text: "phone" }
+ format.html.any { render text: "any" }
+ end
+ end
+
+ def variant_any_implicit_render
+ respond_to do |format|
+ format.html.phone
+ format.html.any(:tablet, :phablet)
+ end
+ end
+
+ def variant_any_with_none
+ respond_to do |format|
+ format.html.any(:none, :phone){ render text: "none or phone" }
+ end
+ end
+
+ def format_any_variant_any
+ respond_to do |format|
+ format.html { render text: "HTML" }
+ format.any(:js, :xml) do |variant|
+ variant.phone{ render text: "phone" }
+ variant.any(:tablet, :phablet){ render text: "tablet" }
+ end
+ end
+ end
+
protected
def set_layout
case action_name
@@ -490,4 +590,179 @@ class RespondToControllerTest < ActionController::TestCase
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
+ end
+
+ def test_variant_not_set_regular_template_missing
+ assert_raises(ActionView::MissingTemplate) do
+ get :variant_with_implicit_rendering
+ end
+ end
+
+ def test_variant_with_implicit_rendering
+ @request.variant = :mobile
+ get :variant_with_implicit_rendering
+ 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
+ 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
+ assert_equal "text/html", @response.content_type
+ assert_equal "tablet", @response.body
+ end
+
+ def test_no_variant_in_variant_setup
+ get :variant_plus_none_for_format
+ assert_equal "text/html", @response.content_type
+ assert_equal "none", @response.body
+ end
+
+ def test_variant_inline_syntax
+ get :variant_inline_syntax, format: :js
+ assert_equal "text/javascript", @response.content_type
+ assert_equal "js", @response.body
+
+ get :variant_inline_syntax
+ assert_equal "text/html", @response.content_type
+ assert_equal "none", @response.body
+
+ @request.variant = :phone
+ get :variant_inline_syntax
+ 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
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+ end
+
+ def test_variant_any
+ @request.variant = :phone
+ get :variant_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+
+ @request.variant = :tablet
+ get :variant_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "any", @response.body
+
+ @request.variant = :phablet
+ get :variant_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "any", @response.body
+ end
+
+ def test_variant_any_any
+ get :variant_any_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "any", @response.body
+
+ @request.variant = :phone
+ get :variant_any_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+
+ @request.variant = :yolo
+ get :variant_any_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "any", @response.body
+ end
+
+ def test_variant_inline_any
+ @request.variant = :phone
+ get :variant_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+
+ @request.variant = :tablet
+ get :variant_inline_any
+ assert_equal "text/html", @response.content_type
+ assert_equal "any", @response.body
+
+ @request.variant = :phablet
+ get :variant_inline_any
+ 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
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+
+ @request.variant = :yolo
+ get :variant_inline_any_any
+ 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
+ assert_equal "text/html", @response.content_type
+ assert_equal "tablet", @response.body
+
+ @request.variant = :phablet
+ get :variant_any_implicit_render
+ assert_equal "text/html", @response.content_type
+ assert_equal "phablet", @response.body
+ end
+
+ def test_variant_any_with_none
+ get :variant_any_with_none
+ assert_equal "text/html", @response.content_type
+ assert_equal "none or phone", @response.body
+
+ @request.variant = :phone
+ get :variant_any_with_none
+ 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
+ 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
+ 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
+ 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
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+ end
end
diff --git a/actionpack/test/controller/new_base/render_body_test.rb b/actionpack/test/controller/new_base/render_body_test.rb
new file mode 100644
index 0000000000..fad848349a
--- /dev/null
+++ b/actionpack/test/controller/new_base/render_body_test.rb
@@ -0,0 +1,170 @@
+require 'abstract_unit'
+
+module RenderBody
+ class MinimalController < ActionController::Metal
+ include AbstractController::Rendering
+ include ActionController::Rendering
+
+ def index
+ render body: "Hello World!"
+ end
+ end
+
+ class SimpleController < ActionController::Base
+ self.view_paths = [ActionView::FixtureResolver.new]
+
+ def index
+ render body: "hello david"
+ end
+ end
+
+ class WithLayoutController < ::ApplicationController
+ self.view_paths = [ActionView::FixtureResolver.new(
+ "layouts/application.erb" => "<%= yield %>, I'm here!",
+ "layouts/greetings.erb" => "<%= yield %>, I wish thee well.",
+ "layouts/ivar.erb" => "<%= yield %>, <%= @ivar %>"
+ )]
+
+ def index
+ render body: "hello david"
+ end
+
+ def custom_code
+ render body: "hello world", status: 404
+ end
+
+ def with_custom_code_as_string
+ render body: "hello world", status: "404 Not Found"
+ end
+
+ def with_nil
+ render body: nil
+ end
+
+ def with_nil_and_status
+ render body: nil, status: 403
+ end
+
+ def with_false
+ render body: false
+ end
+
+ def with_layout_true
+ render body: "hello world", layout: true
+ end
+
+ def with_layout_false
+ render body: "hello world", layout: false
+ end
+
+ def with_layout_nil
+ render body: "hello world", layout: nil
+ end
+
+ def with_custom_layout
+ render body: "hello world", layout: "greetings"
+ end
+
+ def with_custom_content_type
+ response.headers['Content-Type'] = 'application/json'
+ render body: '["troll","face"]'
+ end
+
+ def with_ivar_in_layout
+ @ivar = "hello world"
+ render body: "hello world", layout: "ivar"
+ end
+ end
+
+ class RenderBodyTest < Rack::TestCase
+ test "rendering body from a minimal controller" do
+ get "/render_body/minimal/index"
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering body from an action with default options renders the body with the layout" do
+ with_routing do |set|
+ set.draw { get ':controller', action: 'index' }
+
+ get "/render_body/simple"
+ assert_body "hello david"
+ assert_status 200
+ end
+ end
+
+ test "rendering body from an action with default options renders the body without the layout" do
+ with_routing do |set|
+ set.draw { get ':controller', action: 'index' }
+
+ get "/render_body/with_layout"
+
+ assert_body "hello david"
+ assert_status 200
+ end
+ end
+
+ test "rendering body, while also providing a custom status code" do
+ get "/render_body/with_layout/custom_code"
+
+ assert_body "hello world"
+ assert_status 404
+ end
+
+ test "rendering body with nil returns an empty body padded for Safari" do
+ get "/render_body/with_layout/with_nil"
+
+ assert_body " "
+ assert_status 200
+ end
+
+ test "Rendering body with nil and custom status code returns an empty body padded for Safari and the status" do
+ get "/render_body/with_layout/with_nil_and_status"
+
+ assert_body " "
+ assert_status 403
+ end
+
+ test "rendering body with false returns the string 'false'" do
+ get "/render_body/with_layout/with_false"
+
+ assert_body "false"
+ assert_status 200
+ end
+
+ test "rendering body with layout: true" do
+ get "/render_body/with_layout/with_layout_true"
+
+ assert_body "hello world, I'm here!"
+ assert_status 200
+ end
+
+ test "rendering body with layout: 'greetings'" do
+ get "/render_body/with_layout/with_custom_layout"
+
+ assert_body "hello world, I wish thee well."
+ assert_status 200
+ end
+
+ test "specified content type should not be removed" do
+ get "/render_body/with_layout/with_custom_content_type"
+
+ assert_equal %w{ troll face }, JSON.parse(response.body)
+ assert_equal 'application/json', response.headers['Content-Type']
+ end
+
+ test "rendering body with layout: false" do
+ get "/render_body/with_layout/with_layout_false"
+
+ assert_body "hello world"
+ assert_status 200
+ end
+
+ test "rendering body with layout: nil" do
+ get "/render_body/with_layout/with_layout_nil"
+
+ assert_body "hello world"
+ assert_status 200
+ 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
new file mode 100644
index 0000000000..bfe0271df7
--- /dev/null
+++ b/actionpack/test/controller/new_base/render_html_test.rb
@@ -0,0 +1,190 @@
+require 'abstract_unit'
+
+module RenderHtml
+ class MinimalController < ActionController::Metal
+ include AbstractController::Rendering
+ include ActionController::Rendering
+
+ def index
+ render html: "Hello World!"
+ end
+ end
+
+ class SimpleController < ActionController::Base
+ self.view_paths = [ActionView::FixtureResolver.new]
+
+ def index
+ render html: "hello david"
+ end
+ end
+
+ class WithLayoutController < ::ApplicationController
+ self.view_paths = [ActionView::FixtureResolver.new(
+ "layouts/application.html.erb" => "<%= yield %>, I'm here!",
+ "layouts/greetings.html.erb" => "<%= yield %>, I wish thee well.",
+ "layouts/ivar.html.erb" => "<%= yield %>, <%= @ivar %>"
+ )]
+
+ def index
+ render html: "hello david"
+ end
+
+ def custom_code
+ render html: "hello world", status: 404
+ end
+
+ def with_custom_code_as_string
+ render html: "hello world", status: "404 Not Found"
+ end
+
+ def with_nil
+ render html: nil
+ end
+
+ def with_nil_and_status
+ render html: nil, status: 403
+ end
+
+ def with_false
+ render html: false
+ end
+
+ def with_layout_true
+ render html: "hello world", layout: true
+ end
+
+ def with_layout_false
+ render html: "hello world", layout: false
+ end
+
+ def with_layout_nil
+ render html: "hello world", layout: nil
+ end
+
+ def with_custom_layout
+ render html: "hello world", layout: "greetings"
+ end
+
+ def with_ivar_in_layout
+ @ivar = "hello world"
+ render html: "hello world", layout: "ivar"
+ end
+
+ def with_unsafe_html_tag
+ render html: "<p>hello world</p>", layout: nil
+ end
+
+ def with_safe_html_tag
+ render html: "<p>hello world</p>".html_safe, layout: nil
+ end
+ end
+
+ class RenderHtmlTest < Rack::TestCase
+ test "rendering text from a minimal controller" do
+ get "/render_html/minimal/index"
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering text from an action with default options renders the text with the layout" do
+ with_routing do |set|
+ set.draw { get ':controller', action: 'index' }
+
+ get "/render_html/simple"
+ assert_body "hello david"
+ assert_status 200
+ end
+ end
+
+ test "rendering text from an action with default options renders the text without the layout" do
+ with_routing do |set|
+ set.draw { get ':controller', action: 'index' }
+
+ get "/render_html/with_layout"
+
+ assert_body "hello david"
+ assert_status 200
+ end
+ end
+
+ test "rendering text, while also providing a custom status code" do
+ get "/render_html/with_layout/custom_code"
+
+ assert_body "hello world"
+ assert_status 404
+ end
+
+ test "rendering text with nil returns an empty body padded for Safari" do
+ get "/render_html/with_layout/with_nil"
+
+ assert_body " "
+ assert_status 200
+ end
+
+ test "Rendering text with nil and custom status code returns an empty body padded for Safari and the status" do
+ get "/render_html/with_layout/with_nil_and_status"
+
+ assert_body " "
+ assert_status 403
+ end
+
+ test "rendering text with false returns the string 'false'" do
+ get "/render_html/with_layout/with_false"
+
+ assert_body "false"
+ assert_status 200
+ end
+
+ test "rendering text with layout: true" do
+ get "/render_html/with_layout/with_layout_true"
+
+ assert_body "hello world, I'm here!"
+ assert_status 200
+ end
+
+ test "rendering text with layout: 'greetings'" do
+ get "/render_html/with_layout/with_custom_layout"
+
+ assert_body "hello world, I wish thee well."
+ assert_status 200
+ end
+
+ test "rendering text with layout: false" do
+ get "/render_html/with_layout/with_layout_false"
+
+ assert_body "hello world"
+ assert_status 200
+ end
+
+ test "rendering text with layout: nil" do
+ get "/render_html/with_layout/with_layout_nil"
+
+ assert_body "hello world"
+ assert_status 200
+ end
+
+ test "rendering html should escape the string if it is not html safe" do
+ get "/render_html/with_layout/with_unsafe_html_tag"
+
+ assert_body "&lt;p&gt;hello world&lt;/p&gt;"
+ assert_status 200
+ end
+
+ test "rendering html should not escape the string if it is html safe" do
+ get "/render_html/with_layout/with_safe_html_tag"
+
+ assert_body "<p>hello world</p>"
+ assert_status 200
+ end
+
+ test "rendering from minimal controller returns response with text/html content type" do
+ get "/render_html/minimal/index"
+ assert_content_type "text/html"
+ end
+
+ test "rendering from normal controller returns response with text/html content type" do
+ get "/render_html/simple/index"
+ assert_content_type "text/html; charset=utf-8"
+ end
+ end
+end
diff --git a/actionpack/test/controller/new_base/render_plain_test.rb b/actionpack/test/controller/new_base/render_plain_test.rb
new file mode 100644
index 0000000000..dba2e9f13e
--- /dev/null
+++ b/actionpack/test/controller/new_base/render_plain_test.rb
@@ -0,0 +1,168 @@
+require 'abstract_unit'
+
+module RenderPlain
+ class MinimalController < ActionController::Metal
+ include AbstractController::Rendering
+ include ActionController::Rendering
+
+ def index
+ render plain: "Hello World!"
+ end
+ end
+
+ class SimpleController < ActionController::Base
+ self.view_paths = [ActionView::FixtureResolver.new]
+
+ def index
+ render plain: "hello david"
+ end
+ end
+
+ class WithLayoutController < ::ApplicationController
+ self.view_paths = [ActionView::FixtureResolver.new(
+ "layouts/application.text.erb" => "<%= yield %>, I'm here!",
+ "layouts/greetings.text.erb" => "<%= yield %>, I wish thee well.",
+ "layouts/ivar.text.erb" => "<%= yield %>, <%= @ivar %>"
+ )]
+
+ def index
+ render plain: "hello david"
+ end
+
+ def custom_code
+ render plain: "hello world", status: 404
+ end
+
+ def with_custom_code_as_string
+ render plain: "hello world", status: "404 Not Found"
+ end
+
+ def with_nil
+ render plain: nil
+ end
+
+ def with_nil_and_status
+ render plain: nil, status: 403
+ end
+
+ def with_false
+ render plain: false
+ end
+
+ def with_layout_true
+ render plain: "hello world", layout: true
+ end
+
+ def with_layout_false
+ render plain: "hello world", layout: false
+ end
+
+ def with_layout_nil
+ render plain: "hello world", layout: nil
+ end
+
+ def with_custom_layout
+ render plain: "hello world", layout: "greetings"
+ end
+
+ def with_ivar_in_layout
+ @ivar = "hello world"
+ render plain: "hello world", layout: "ivar"
+ end
+ end
+
+ class RenderPlainTest < Rack::TestCase
+ test "rendering text from a minimal controller" do
+ get "/render_plain/minimal/index"
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering text from an action with default options renders the text with the layout" do
+ with_routing do |set|
+ set.draw { get ':controller', action: 'index' }
+
+ get "/render_plain/simple"
+ assert_body "hello david"
+ assert_status 200
+ end
+ end
+
+ test "rendering text from an action with default options renders the text without the layout" do
+ with_routing do |set|
+ set.draw { get ':controller', action: 'index' }
+
+ get "/render_plain/with_layout"
+
+ assert_body "hello david"
+ assert_status 200
+ end
+ end
+
+ test "rendering text, while also providing a custom status code" do
+ get "/render_plain/with_layout/custom_code"
+
+ assert_body "hello world"
+ assert_status 404
+ end
+
+ test "rendering text with nil returns an empty body padded for Safari" do
+ get "/render_plain/with_layout/with_nil"
+
+ assert_body " "
+ assert_status 200
+ end
+
+ test "Rendering text with nil and custom status code returns an empty body padded for Safari and the status" do
+ get "/render_plain/with_layout/with_nil_and_status"
+
+ assert_body " "
+ assert_status 403
+ end
+
+ test "rendering text with false returns the string 'false'" do
+ get "/render_plain/with_layout/with_false"
+
+ assert_body "false"
+ assert_status 200
+ end
+
+ test "rendering text with layout: true" do
+ get "/render_plain/with_layout/with_layout_true"
+
+ assert_body "hello world, I'm here!"
+ assert_status 200
+ end
+
+ test "rendering text with layout: 'greetings'" do
+ get "/render_plain/with_layout/with_custom_layout"
+
+ assert_body "hello world, I wish thee well."
+ assert_status 200
+ end
+
+ test "rendering text with layout: false" do
+ get "/render_plain/with_layout/with_layout_false"
+
+ assert_body "hello world"
+ assert_status 200
+ end
+
+ test "rendering text with layout: nil" do
+ get "/render_plain/with_layout/with_layout_nil"
+
+ assert_body "hello world"
+ assert_status 200
+ end
+
+ test "rendering from minimal controller returns response with text/plain content type" do
+ get "/render_plain/minimal/index"
+ assert_content_type "text/plain"
+ end
+
+ test "rendering from normal controller returns response with text/plain content type" do
+ get "/render_plain/simple/index"
+ assert_content_type "text/plain; charset=utf-8"
+ end
+ end
+end
diff --git a/actionpack/test/controller/new_base/render_streaming_test.rb b/actionpack/test/controller/new_base/render_streaming_test.rb
index 2b36a399bb..4c9126ca8c 100644
--- a/actionpack/test/controller/new_base/render_streaming_test.rb
+++ b/actionpack/test/controller/new_base/render_streaming_test.rb
@@ -4,7 +4,7 @@ module RenderStreaming
class BasicController < ActionController::Base
self.view_paths = [ActionView::FixtureResolver.new(
"render_streaming/basic/hello_world.html.erb" => "Hello world",
- "render_streaming/basic/boom.html.erb" => "<%= nil.invalid! %>",
+ "render_streaming/basic/boom.html.erb" => "<%= raise 'Ruby was here!' %>",
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
"layouts/boom.html.erb" => "<body class=\"<%= nil.invalid! %>\"<%= yield %></body>"
)]
@@ -90,7 +90,7 @@ module RenderStreaming
begin
get "/render_streaming/basic/template_exception"
io.rewind
- assert_match "(undefined method `invalid!' for nil:NilClass)", io.read
+ assert_match "Ruby was here!", io.read
ensure
ActionView::Base.logger = _old
end
diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb
index 6b2ae2b2a9..b7a9cf92f2 100644
--- a/actionpack/test/controller/new_base/render_template_test.rb
+++ b/actionpack/test/controller/new_base/render_template_test.rb
@@ -14,7 +14,7 @@ module RenderTemplate
"test/with_json.html.erb" => "<%= render :template => 'test/with_json', :formats => [:json] %>",
"test/with_json.json.erb" => "<%= render :template => 'test/final', :formats => [:json] %>",
"test/final.json.erb" => "{ final: json }",
- "test/with_error.html.erb" => "<%= idontexist %>"
+ "test/with_error.html.erb" => "<%= raise 'i do not exist' %>"
)]
def index
@@ -132,7 +132,7 @@ module RenderTemplate
test "rendering a template with error properly excerts the code" do
get :with_error
assert_status 500
- assert_match "undefined local variable or method `idontexist", response.body
+ assert_match "i do not exist", response.body
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 2a253799f3..abb81d7e71 100644
--- a/actionpack/test/controller/new_base/render_text_test.rb
+++ b/actionpack/test/controller/new_base/render_text_test.rb
@@ -14,7 +14,7 @@ module RenderText
self.view_paths = [ActionView::FixtureResolver.new]
def index
- render :text => "hello david"
+ render text: "hello david"
end
end
@@ -26,48 +26,48 @@ module RenderText
)]
def index
- render :text => "hello david"
+ render text: "hello david"
end
def custom_code
- render :text => "hello world", :status => 404
+ render text: "hello world", status: 404
end
def with_custom_code_as_string
- render :text => "hello world", :status => "404 Not Found"
+ render text: "hello world", status: "404 Not Found"
end
def with_nil
- render :text => nil
+ render text: nil
end
def with_nil_and_status
- render :text => nil, :status => 403
+ render text: nil, status: 403
end
def with_false
- render :text => false
+ render text: false
end
def with_layout_true
- render :text => "hello world", :layout => true
+ render text: "hello world", layout: true
end
def with_layout_false
- render :text => "hello world", :layout => false
+ render text: "hello world", layout: false
end
def with_layout_nil
- render :text => "hello world", :layout => nil
+ render text: "hello world", layout: nil
end
def with_custom_layout
- render :text => "hello world", :layout => "greetings"
+ render text: "hello world", layout: "greetings"
end
def with_ivar_in_layout
@ivar = "hello world"
- render :text => "hello world", :layout => "ivar"
+ render text: "hello world", layout: "ivar"
end
end
@@ -80,7 +80,7 @@ module RenderText
test "rendering text from an action with default options renders the text with the layout" do
with_routing do |set|
- set.draw { get ':controller', :action => 'index' }
+ set.draw { get ':controller', action: 'index' }
get "/render_text/simple"
assert_body "hello david"
@@ -90,7 +90,7 @@ module RenderText
test "rendering text from an action with default options renders the text without the layout" do
with_routing do |set|
- set.draw { get ':controller', :action => 'index' }
+ set.draw { get ':controller', action: 'index' }
get "/render_text/with_layout"
@@ -127,28 +127,28 @@ module RenderText
assert_status 200
end
- test "rendering text with :layout => true" do
+ test "rendering text with layout: true" do
get "/render_text/with_layout/with_layout_true"
assert_body "hello world, I'm here!"
assert_status 200
end
- test "rendering text with :layout => 'greetings'" do
+ test "rendering text with layout: 'greetings'" do
get "/render_text/with_layout/with_custom_layout"
assert_body "hello world, I wish thee well."
assert_status 200
end
- test "rendering text with :layout => false" do
+ test "rendering text with layout: false" do
get "/render_text/with_layout/with_layout_false"
assert_body "hello world"
assert_status 200
end
- test "rendering text with :layout => nil" do
+ test "rendering text with layout: nil" do
get "/render_text/with_layout/with_layout_nil"
assert_body "hello world"
diff --git a/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb b/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb
index 22e603b881..9ce04b9aeb 100644
--- a/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb
+++ b/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb
@@ -10,23 +10,45 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase
ActionController::Parameters.action_on_unpermitted_parameters = false
end
- test "logs on unexpected params" do
+ test "logs on unexpected param" do
params = ActionController::Parameters.new({
book: { pages: 65 },
fishing: "Turnips"
})
- assert_logged("Unpermitted parameters: fishing") do
+ assert_logged("Unpermitted parameter: fishing") do
params.permit(book: [:pages])
end
end
- test "logs on unexpected nested params" do
+ test "logs on unexpected params" do
+ params = ActionController::Parameters.new({
+ book: { pages: 65 },
+ fishing: "Turnips",
+ car: "Mersedes"
+ })
+
+ assert_logged("Unpermitted parameters: fishing, car") do
+ params.permit(book: [:pages])
+ end
+ end
+
+ test "logs on unexpected nested param" do
params = ActionController::Parameters.new({
book: { pages: 65, title: "Green Cats and where to find then." }
})
- assert_logged("Unpermitted parameters: title") do
+ assert_logged("Unpermitted parameter: title") do
+ params.permit(book: [:pages])
+ end
+ end
+
+ test "logs on unexpected nested params" do
+ params = ActionController::Parameters.new({
+ book: { pages: 65, title: "Green Cats and where to find then.", author: "G. A. Dog" }
+ })
+
+ assert_logged("Unpermitted parameters: title, author") do
params.permit(book: [:pages])
end
end
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index b60c5f058d..33a91d72d9 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -8,9 +8,16 @@ class ParametersPermitTest < ActiveSupport::TestCase
end
setup do
- @params = ActionController::Parameters.new({ person: {
- age: "32", name: { first: "David", last: "Heinemeier Hansson" }
- }})
+ @params = ActionController::Parameters.new(
+ person: {
+ age: '32',
+ name: {
+ first: 'David',
+ last: 'Heinemeier Hansson'
+ },
+ addresses: [{city: 'Chicago', state: 'Illinois'}]
+ }
+ )
@struct_fields = []
%w(0 1 12).each do |number|
@@ -153,6 +160,18 @@ class ParametersPermitTest < ActiveSupport::TestCase
assert_equal nil, params[:foo]
end
+ test 'hashes in array values get wrapped' do
+ params = ActionController::Parameters.new(foo: [{}, {}])
+ params[:foo].each do |hash|
+ assert !hash.permitted?
+ end
+ end
+
+ test 'arrays are converted at most once' do
+ params = ActionController::Parameters.new(foo: [{}])
+ assert params[:foo].equal?(params[:foo])
+ end
+
test "fetch doesnt raise ParameterMissing exception if there is a default" do
assert_equal "monkey", @params.fetch(:foo, "monkey")
assert_equal "monkey", @params.fetch(:foo) { "monkey" }
@@ -221,6 +240,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
assert @params.permitted?
assert @params[:person].permitted?
assert @params[:person][:name].permitted?
+ assert @params[:person][:addresses][0].permitted?
end
test "permitted takes a default value when Parameters.permit_all_parameters is set" do
diff --git a/actionpack/test/controller/parameters/parameters_require_test.rb b/actionpack/test/controller/parameters/parameters_require_test.rb
deleted file mode 100644
index bdaba8d2d8..0000000000
--- a/actionpack/test/controller/parameters/parameters_require_test.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'abstract_unit'
-require 'action_controller/metal/strong_parameters'
-
-class ParametersRequireTest < ActiveSupport::TestCase
- test "required parameters must be present not merely not nil" do
- assert_raises(ActionController::ParameterMissing) do
- ActionController::Parameters.new(person: {}).require(:person)
- end
- end
-end
diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb
index d87e2b85b0..11ccb6cf3b 100644
--- a/actionpack/test/controller/params_wrapper_test.rb
+++ b/actionpack/test/controller/params_wrapper_test.rb
@@ -188,6 +188,26 @@ class ParamsWrapperTest < ActionController::TestCase
assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu', 'title' => 'Developer' }})
end
end
+
+ def test_preserves_query_string_params
+ with_default_wrapper_options do
+ @request.env['CONTENT_TYPE'] = 'application/json'
+ get :parse, { 'user' => { 'username' => 'nixon' } }
+ assert_parameters(
+ {'user' => { 'username' => 'nixon' } }
+ )
+ end
+ end
+
+ def test_empty_parameter_set
+ with_default_wrapper_options do
+ @request.env['CONTENT_TYPE'] = 'application/json'
+ post :parse, {}
+ assert_parameters(
+ {'user' => { } }
+ )
+ end
+ end
end
class NamespacedParamsWrapperTest < ActionController::TestCase
diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb
index f070109b27..d550422a2f 100644
--- a/actionpack/test/controller/render_js_test.rb
+++ b/actionpack/test/controller/render_js_test.rb
@@ -22,7 +22,7 @@ class RenderJSTest < ActionController::TestCase
tests TestController
def test_render_vanilla_js
- get :render_vanilla_js_hello
+ xhr :get, :render_vanilla_js_hello
assert_equal "alert('hello')", @response.body
assert_equal "text/javascript", @response.content_type
end
diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb
index 7c0a6bd67e..de8d1cbd9b 100644
--- a/actionpack/test/controller/render_json_test.rb
+++ b/actionpack/test/controller/render_json_test.rb
@@ -100,13 +100,13 @@ class RenderJsonTest < ActionController::TestCase
end
def test_render_json_with_callback
- get :render_json_hello_world_with_callback
+ xhr :get, :render_json_hello_world_with_callback
assert_equal 'alert({"hello":"world"})', @response.body
assert_equal 'text/javascript', @response.content_type
end
def test_render_json_with_custom_content_type
- get :render_json_with_custom_content_type
+ xhr :get, :render_json_with_custom_content_type
assert_equal '{"hello":"world"}', @response.body
assert_equal 'text/javascript', @response.content_type
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index f41287381a..26806fb03f 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -529,4 +529,4 @@ class HeadRenderTest < ActionController::TestCase
assert_equal "something", @response.headers["X-Custom-Header"]
assert_response :forbidden
end
-end \ No newline at end of file
+end
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 727db79241..99229b3baf 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -52,18 +52,36 @@ module RequestForgeryProtectionActions
render :inline => "<%= form_for(:some_resource, :remote => true, :authenticity_token => 'external_token') {} %>"
end
+ def same_origin_js
+ render js: 'foo();'
+ end
+
+ def negotiate_same_origin
+ respond_to do |format|
+ format.js { same_origin_js }
+ end
+ end
+
+ def cross_origin_js
+ same_origin_js
+ end
+
+ def negotiate_cross_origin
+ negotiate_same_origin
+ end
+
def rescue_action(e) raise e end
end
# sample controllers
class RequestForgeryProtectionControllerUsingResetSession < ActionController::Base
include RequestForgeryProtectionActions
- protect_from_forgery :only => %w(index meta), :with => :reset_session
+ protect_from_forgery :only => %w(index meta same_origin_js negotiate_same_origin), :with => :reset_session
end
class RequestForgeryProtectionControllerUsingException < ActionController::Base
include RequestForgeryProtectionActions
- protect_from_forgery :only => %w(index meta), :with => :exception
+ protect_from_forgery :only => %w(index meta same_origin_js negotiate_same_origin), :with => :exception
end
class RequestForgeryProtectionControllerUsingNullSession < ActionController::Base
@@ -201,7 +219,7 @@ module RequestForgeryProtectionTests
end
def test_should_not_allow_post_without_token_irrespective_of_format
- assert_blocked { post :index, :format=>'xml' }
+ assert_blocked { post :index, format: 'xml' }
end
def test_should_not_allow_patch_without_token
@@ -271,6 +289,64 @@ module RequestForgeryProtectionTests
end
end
+ def test_should_not_warn_if_csrf_logging_disabled
+ old_logger = ActionController::Base.logger
+ logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
+ ActionController::Base.logger = logger
+ ActionController::Base.log_warning_on_csrf_failure = false
+
+ begin
+ assert_blocked { post :index }
+
+ assert_equal 0, logger.logged(:warn).size
+ ensure
+ ActionController::Base.logger = old_logger
+ ActionController::Base.log_warning_on_csrf_failure = true
+ end
+ end
+
+ def test_should_only_allow_same_origin_js_get_with_xhr_header
+ assert_cross_origin_blocked { get :same_origin_js }
+ assert_cross_origin_blocked { get :same_origin_js, format: 'js' }
+ assert_cross_origin_blocked do
+ @request.accept = 'text/javascript'
+ 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 do
+ @request.accept = 'text/javascript'
+ xhr :get, :negotiate_same_origin
+ 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 }
+ assert_cross_origin_not_blocked do
+ @request.accept = 'text/javascript'
+ post :negotiate_same_origin, custom_authenticity_token: @token
+ end
+ end
+
+ def test_should_only_allow_cross_origin_js_get_without_xhr_header_if_protection_disabled
+ assert_cross_origin_not_blocked { get :cross_origin_js }
+ assert_cross_origin_not_blocked { get :cross_origin_js, format: 'js' }
+ assert_cross_origin_not_blocked do
+ @request.accept = 'text/javascript'
+ 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 do
+ @request.accept = 'text/javascript'
+ xhr :get, :negotiate_cross_origin
+ end
+ end
+
def assert_blocked
session[:something_like_user_id] = 1
yield
@@ -282,6 +358,16 @@ module RequestForgeryProtectionTests
assert_nothing_raised { yield }
assert_response :success
end
+
+ def assert_cross_origin_blocked
+ assert_raises(ActionController::InvalidCrossOriginRequest) do
+ yield
+ end
+ end
+
+ def assert_cross_origin_not_blocked
+ assert_not_blocked { yield }
+ end
end
# OK let's get our test on
@@ -305,13 +391,13 @@ class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController
end
end
-class NullSessionDummyKeyGenerator
- def generate_key(secret)
- '03312270731a2ed0d11ed091c2338a06'
+class RequestForgeryProtectionControllerUsingNullSessionTest < ActionController::TestCase
+ class NullSessionDummyKeyGenerator
+ def generate_key(secret)
+ '03312270731a2ed0d11ed091c2338a06'
+ end
end
-end
-class RequestForgeryProtectionControllerUsingNullSessionTest < ActionController::TestCase
def setup
@request.env[ActionDispatch::Cookies::GENERATOR_KEY] = NullSessionDummyKeyGenerator.new
end
@@ -375,8 +461,8 @@ end
class CustomAuthenticityParamControllerTest < ActionController::TestCase
def setup
- ActionController::Base.request_forgery_protection_token = :custom_token_name
super
+ ActionController::Base.request_forgery_protection_token = :custom_token_name
end
def teardown
diff --git a/actionpack/test/controller/required_params_test.rb b/actionpack/test/controller/required_params_test.rb
index 343d57c300..25d0337212 100644
--- a/actionpack/test/controller/required_params_test.rb
+++ b/actionpack/test/controller/required_params_test.rb
@@ -25,3 +25,11 @@ class ActionControllerRequiredParamsTest < ActionController::TestCase
assert_response :ok
end
end
+
+class ParametersRequireTest < ActiveSupport::TestCase
+ test "required parameters must be present not merely not nil" do
+ assert_raises(ActionController::ParameterMissing) do
+ ActionController::Parameters.new(person: {}).require(:person)
+ end
+ end
+end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 9aea7e860a..a5f43c4b6b 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -4,6 +4,7 @@ require 'active_support/core_ext/object/with_options'
require 'active_support/core_ext/array/extract_options'
class ResourcesTest < ActionController::TestCase
+
def test_default_restful_routes
with_restful_routing :messages do
assert_simply_restful_for :messages
@@ -1004,7 +1005,7 @@ class ResourcesTest < ActionController::TestCase
end
end
- assert_resource_allowed_routes('images', { :product_id => '1' }, { :id => '2' }, [:index, :new, :create, :show, :edit, :update, :destory], [], 'products/1/images')
+ assert_resource_allowed_routes('images', { :product_id => '1' }, { :id => '2' }, [:index, :new, :create, :show, :edit, :update, :destroy], [], 'products/1/images')
assert_resource_allowed_routes('images', { :product_id => '1', :format => 'xml' }, { :id => '2' }, [:index, :new, :create, :show, :edit, :update, :destroy], [], 'products/1/images')
end
end
@@ -1320,6 +1321,8 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes options, path_options
elsif Array(not_allowed).include?(action)
assert_not_recognizes options, path_options
+ else
+ raise Assertion, 'Invalid Action has passed'
end
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 2c84e95c6e..df453a0251 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -1833,11 +1833,11 @@ class RackMountIntegrationTests < ActiveSupport::TestCase
assert_equal({:controller => 'foo', :action => 'id_default', :id => 1 }, @routes.recognize_path('/id_default'))
assert_equal({:controller => 'foo', :action => 'get_or_post'}, @routes.recognize_path('/get_or_post', :method => :get))
assert_equal({:controller => 'foo', :action => 'get_or_post'}, @routes.recognize_path('/get_or_post', :method => :post))
- assert_raise(ActionController::ActionControllerError) { @routes.recognize_path('/get_or_post', :method => :put) }
- assert_raise(ActionController::ActionControllerError) { @routes.recognize_path('/get_or_post', :method => :delete) }
+ assert_raise(ActionController::RoutingError) { @routes.recognize_path('/get_or_post', :method => :put) }
+ assert_raise(ActionController::RoutingError) { @routes.recognize_path('/get_or_post', :method => :delete) }
assert_equal({:controller => 'posts', :action => 'index', :optional => 'bar'}, @routes.recognize_path('/optional/bar'))
- assert_raise(ActionController::ActionControllerError) { @routes.recognize_path('/optional') }
+ assert_raise(ActionController::RoutingError) { @routes.recognize_path('/optional') }
assert_equal({:controller => 'posts', :action => 'show', :id => '1', :ws => true}, @routes.recognize_path('/ws/posts/show/1', :method => :get))
assert_equal({:controller => 'posts', :action => 'list', :ws => true}, @routes.recognize_path('/ws/posts/list', :method => :get))
@@ -1916,11 +1916,4 @@ class RackMountIntegrationTests < ActiveSupport::TestCase
end
extras
end
-
- def assert_raise(e)
- result = yield
- flunk "Did not raise #{e}, but returned #{result.inspect}"
- rescue e
- assert true
- end
end
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 8ecc1c7d73..4df2f8b98d 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -25,6 +25,10 @@ class SendFileController < ActionController::Base
end
end
+class SendFileWithActionControllerLive < SendFileController
+ include ActionController::Live
+end
+
class SendFileTest < ActionController::TestCase
tests SendFileController
include TestFileUtils
@@ -144,7 +148,7 @@ class SendFileTest < ActionController::TestCase
}
@controller.headers = {}
- assert !@controller.send(:send_file_headers!, options)
+ assert_raise(ArgumentError) { @controller.send(:send_file_headers!, options) }
end
def test_send_file_headers_guess_type_from_extension
@@ -196,4 +200,14 @@ class SendFileTest < ActionController::TestCase
assert_equal 200, @response.status
end
end
+
+ tests SendFileWithActionControllerLive
+
+ def test_send_file_with_action_controller_live
+ @controller = SendFileWithActionControllerLive.new
+ @controller.options = { :content_type => "application/x-ruby" }
+
+ response = process('file')
+ assert_equal 200, response.status
+ end
end
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index de0476dbde..fbc10baf21 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -163,6 +163,29 @@ XML
end
end
+ class DefaultUrlOptionsCachingController < ActionController::Base
+ before_filter { @dynamic_opt = 'opt' }
+
+ def test_url_options_reset
+ render text: url_for(params)
+ end
+
+ def default_url_options
+ if defined?(@dynamic_opt)
+ super.merge dynamic_opt: @dynamic_opt
+ else
+ super
+ end
+ end
+ end
+
+ def test_url_options_reset
+ @controller = DefaultUrlOptionsCachingController.new
+ get :test_url_options_reset
+ assert_nil @request.params['dynamic_opt']
+ assert_match(/dynamic_opt=opt/, @response.body)
+ end
+
def test_raw_post_handling
params = Hash[:page, {:name => 'page name'}, 'some key', 123]
post :render_raw_post, params.dup
@@ -706,6 +729,14 @@ XML
assert @request.params[:foo].blank?
end
+ def test_filtered_parameters_reset_between_requests
+ get :no_op, :foo => "bar"
+ assert_equal "bar", @request.filtered_parameters[:foo]
+
+ get :no_op, :foo => "baz"
+ assert_equal "baz", @request.filtered_parameters[:foo]
+ end
+
def test_symbolized_path_params_reset_after_request
get :test_params, :id => "foo"
assert_equal "foo", @request.symbolized_path_parameters[:id]
diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb
index d2b4952759..a8035e5bd7 100644
--- a/actionpack/test/controller/url_for_test.rb
+++ b/actionpack/test/controller/url_for_test.rb
@@ -204,9 +204,6 @@ module AbstractController
end
def test_relative_url_root_is_respected
- # ROUTES TODO: Tests should not have to pass :relative_url_root directly. This
- # should probably come from routes.
-
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 => '/subdir')