aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md65
-rw-r--r--actionpack/lib/abstract_controller/translation.rb15
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb78
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb4
-rw-r--r--actionpack/lib/action_controller/test_case.rb21
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb12
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb5
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb12
-rw-r--r--actionpack/lib/action_dispatch/routing/routes_proxy.rb9
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb22
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb90
-rw-r--r--actionpack/test/abstract/translation_test.rb33
-rw-r--r--actionpack/test/controller/integration_test.rb155
-rw-r--r--actionpack/test/controller/mime/respond_to_test.rb20
-rw-r--r--actionpack/test/controller/render_js_test.rb4
-rw-r--r--actionpack/test/controller/render_json_test.rb4
-rw-r--r--actionpack/test/controller/render_test.rb104
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb21
-rw-r--r--actionpack/test/controller/resources_test.rb22
-rw-r--r--actionpack/test/controller/test_case_test.rb21
-rw-r--r--actionpack/test/dispatch/response_test.rb4
-rw-r--r--actionpack/test/dispatch/routing_test.rb12
24 files changed, 519 insertions, 216 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 5e0c64900f..055d4b4f5b 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,68 @@
+* Non-string authenticity tokens do not raise NoMethodError when decoding
+ the masked token.
+
+ *Ville Lautanala*
+
+* Add http_cache_forever to Action Controller, so we can cache a response that never gets expired.
+
+ *arthurnn*
+
+* ActionController#translate supports symbols as shortcuts.
+ When shortcut is given it also lookups without action name.
+
+ *Max Melentiev*
+
+* Expand `ActionController::ConditionalGet#fresh_when` and `stale?` to also
+ accept a collection of records as the first argument, so that the
+ following code can be written in a shorter form.
+
+ # Before
+ def index
+ @articles = Article.all
+ fresh_when(etag: @articles, last_modified: @articles.maximum(:updated_at))
+ end
+
+ # After
+ def index
+ @articles = Article.all
+ fresh_when(@articles)
+ end
+
+ *claudiob*
+
+* Explicitly ignored wildcard verbs when searching for HEAD routes before fallback
+
+ Fixes an issue where a mounted rack app at root would intercept the HEAD
+ request causing an incorrect behavior during the fall back to GET requests.
+
+ Example:
+ ```ruby
+ draw do
+ get '/home' => 'test#index'
+ mount rack_app, at: '/'
+ end
+ head '/home'
+ assert_response :success
+ ```
+ In this case, a HEAD request runs through the routes the first time and fails
+ to match anything. Then, it runs through the list with the fallback and matches
+ `get '/home'`. The original behavior would match the rack app in the first pass.
+
+ *Terence Sun*
+
+* Migrating xhr methods to keyword arguments syntax
+ in `ActionController::TestCase` and `ActionDispatch::Integration`
+
+ Old syntax:
+
+ xhr :get, :create, params: { id: 1 }
+
+ New syntax example:
+
+ get :create, params: { id: 1 }, xhr: true
+
+ *Kir Shatrov*
+
* Migrating to keyword arguments syntax in `ActionController::TestCase` and
`ActionDispatch::Integration` HTTP request methods.
diff --git a/actionpack/lib/abstract_controller/translation.rb b/actionpack/lib/abstract_controller/translation.rb
index 02028d8e05..56b8ce895e 100644
--- a/actionpack/lib/abstract_controller/translation.rb
+++ b/actionpack/lib/abstract_controller/translation.rb
@@ -8,14 +8,15 @@ module AbstractController
# <tt>I18n.translate("people.index.foo")</tt>. This makes it less repetitive
# to translate many keys within the same controller / action and gives you a
# simple framework for scoping them consistently.
- def translate(*args)
- key = args.first
- if key.is_a?(String) && (key[0] == '.')
- key = "#{ controller_path.tr('/', '.') }.#{ action_name }#{ key }"
- args[0] = key
+ def translate(key, options = {})
+ if key.to_s.first == '.'
+ path = controller_path.tr('/', '.')
+ defaults = [:"#{path}#{key}"]
+ defaults << options[:default] if options[:default]
+ options[:default] = defaults
+ key = "#{path}.#{action_name}#{key}"
end
-
- I18n.translate(*args)
+ I18n.translate(key, options)
end
alias :t :translate
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index febbc72861..858870d8b8 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -57,15 +57,25 @@ module ActionController
# This will render the show template if the request isn't sending a matching ETag or
# If-Modified-Since header and just a <tt>304 Not Modified</tt> response if there's a match.
#
- # You can also just pass a record where +last_modified+ will be set by calling
- # +updated_at+ and the +etag+ by passing the object itself.
+ # You can also just pass a record. In this case +last_modified+ will be set
+ # by calling +updated_at+ and +etag+ by passing the object itself.
#
# def show
# @article = Article.find(params[:id])
# fresh_when(@article)
# end
#
- # When passing a record, you can still set whether the public header:
+ # You can also pass an object that responds to +maximum+, such as a
+ # collection of active records. In this case +last_modified+ will be set by
+ # calling +maximum(:updated_at)+ on the collection (the timestamp of the
+ # most recently updated record) and the +etag+ by passing the object itself.
+ #
+ # def index
+ # @articles = Article.all
+ # fresh_when(@articles)
+ # end
+ #
+ # When passing a record or a collection, you can still set the public header:
#
# def show
# @article = Article.find(params[:id])
@@ -77,18 +87,16 @@ module ActionController
#
# before_action { fresh_when @article, template: 'widgets/show' }
#
- def fresh_when(record_or_options, additional_options = {})
- if record_or_options.is_a? Hash
- options = record_or_options
- options.assert_valid_keys(:etag, :last_modified, :public, :template)
- else
- record = record_or_options
- options = { etag: record, last_modified: record.try(:updated_at) }.merge!(additional_options)
+ def fresh_when(object = nil, etag: object, last_modified: nil, public: false, template: nil)
+ last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)
+
+ if etag || template
+ response.etag = combine_etags(etag: etag, last_modified: last_modified,
+ public: public, template: template)
end
- response.etag = combine_etags(options) if options[:etag] || options[:template]
- response.last_modified = options[:last_modified] if options[:last_modified]
- response.cache_control[:public] = true if options[:public]
+ response.last_modified = last_modified if last_modified
+ response.cache_control[:public] = true if public
head :not_modified if request.fresh?(response)
end
@@ -123,8 +131,8 @@ module ActionController
# end
# end
#
- # You can also just pass a record where +last_modified+ will be set by calling
- # +updated_at+ and the +etag+ by passing the object itself.
+ # You can also just pass a record. In this case +last_modified+ will be set
+ # by calling +updated_at+ and +etag+ by passing the object itself.
#
# def show
# @article = Article.find(params[:id])
@@ -137,7 +145,23 @@ module ActionController
# end
# end
#
- # When passing a record, you can still set whether the public header:
+ # You can also pass an object that responds to +maximum+, such as a
+ # collection of active records. In this case +last_modified+ will be set by
+ # calling +maximum(:updated_at)+ on the collection (the timestamp of the
+ # most recently updated record) and the +etag+ by passing the object itself.
+ #
+ # def index
+ # @articles = Article.all
+ #
+ # if stale?(@articles)
+ # @statistics = @articles.really_expensive_call
+ # respond_to do |format|
+ # # all the supported formats
+ # end
+ # end
+ # end
+ #
+ # When passing a record or a collection, you can still set the public header:
#
# def show
# @article = Article.find(params[:id])
@@ -157,8 +181,8 @@ module ActionController
# super if stale? @article, template: 'widgets/show'
# end
#
- def stale?(record_or_options, additional_options = {})
- fresh_when(record_or_options, additional_options)
+ def stale?(object = nil, etag: object, last_modified: nil, public: nil, template: nil)
+ fresh_when(object, etag: etag, last_modified: last_modified, public: public, template: template)
!request.fresh?(response)
end
@@ -191,6 +215,24 @@ module ActionController
response.cache_control.replace(:no_cache => true)
end
+ # Cache or yield the block. The cache is supposed to never expire.
+ #
+ # You can use this method when you have a HTTP response that never changes,
+ # and the browser and proxies should cache it indefinitely.
+ #
+ # * +public+: By default, HTTP responses are private, cached only on the
+ # user's web browser. To allow proxies to cache the response, set +true+ to
+ # indicate that they can serve the cached response to all users.
+ #
+ # * +version+: the version passed as a key for the cache.
+ def http_cache_forever(public: false, version: 'v1')
+ expires_in 100.years, public: public
+
+ yield if stale?(etag: "#{version}-#{request.fullpath}",
+ last_modified: Time.parse('2011-01-01').utc,
+ public: public)
+ end
+
private
def combine_etags(options)
etags = etaggers.map { |etagger| instance_exec(options, &etagger) }.compact
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 7facbe79aa..367b736035 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -275,7 +275,9 @@ module ActionController #:nodoc:
# session token. Essentially the inverse of
# +masked_authenticity_token+.
def valid_authenticity_token?(session, encoded_masked_token)
- return false if encoded_masked_token.nil? || encoded_masked_token.empty?
+ if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String)
+ return false
+ end
begin
masked_token = Base64.strict_decode64(encoded_masked_token)
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index b05700aace..4782991463 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -546,8 +546,13 @@ module ActionController
end
def xml_http_request(*args)
+ ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
+ xhr and xml_http_request methods are deprecated in favor of
+ `get :index, xhr: true` and `post :create, xhr: true`
+ MSG
+
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
- @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
__send__(*args).tap do
@request.env.delete 'HTTP_X_REQUESTED_WITH'
@request.env.delete 'HTTP_ACCEPT'
@@ -600,7 +605,7 @@ module ActionController
check_required_ivars
if kwarg_request?(*args)
- parameters, session, body, flash, http_method, format = args[0].values_at(:params, :session, :body, :flash, :method, :format)
+ parameters, session, body, flash, http_method, format, xhr = args[0].values_at(:params, :session, :body, :flash, :method, :format, :xhr)
else
http_method, parameters, session, flash = args
format = nil
@@ -656,6 +661,11 @@ module ActionController
@request.session.update(session) if session
@request.flash.update(flash || {})
+ if xhr
+ @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
+ @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ end
+
@controller.request = @request
@controller.response = @response
@@ -681,6 +691,11 @@ module ActionController
@request.session.delete('flash')
end
+ if xhr
+ @request.env.delete 'HTTP_X_REQUESTED_WITH'
+ @request.env.delete 'HTTP_ACCEPT'
+ end
+
@response
end
@@ -741,7 +756,7 @@ module ActionController
end
end
- REQUEST_KWARGS = %i(params session flash method body)
+ REQUEST_KWARGS = %i(params session flash method body xhr)
def kwarg_request?(*args)
args[0].respond_to?(:keys) && (
(args[0].key?(:format) && args[0].keys.size == 1) ||
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 2b036796ab..e9df984c86 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -121,6 +121,7 @@ module ActionDispatch
end
def match_head_routes(routes, req)
+ routes.delete_if { |route| route.verb == // }
head_routes = match_routes(routes, req)
if head_routes.empty?
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 5595a73887..d176a73633 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -1,5 +1,6 @@
require 'action_controller/metal/exceptions'
require 'active_support/core_ext/module/attribute_accessors'
+require 'rack/utils'
module ActionDispatch
class ExceptionWrapper
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
index 25658bac3d..cf31815c23 100644
--- a/actionpack/lib/action_dispatch/middleware/request_id.rb
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -12,19 +12,23 @@ module ActionDispatch
# The unique request id can be used to trace a request end-to-end and would typically end up being part of log files
# from multiple pieces of the stack.
class RequestId
+ X_REQUEST_ID = "X-Request-Id".freeze # :nodoc:
+ ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc:
+ HTTP_X_REQUEST_ID = "HTTP_X_REQUEST_ID".freeze # :nodoc:
+
def initialize(app)
@app = app
end
def call(env)
- env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id
- @app.call(env).tap { |_status, headers, _body| headers["X-Request-Id"] = env["action_dispatch.request_id"] }
+ env[ACTION_DISPATCH_REQUEST_ID] = external_request_id(env) || internal_request_id
+ @app.call(env).tap { |_status, headers, _body| headers[X_REQUEST_ID] = env[ACTION_DISPATCH_REQUEST_ID] }
end
private
def external_request_id(env)
- if request_id = env["HTTP_X_REQUEST_ID"].presence
- request_id.gsub(/[^\w\-]/, "").first(255)
+ if request_id = env[HTTP_X_REQUEST_ID].presence
+ request_id.gsub(/[^\w\-]/, "".freeze).first(255)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 002bf8b11a..2e1bd45c3d 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -23,10 +23,9 @@ module ActionDispatch
def match?(path)
path = URI.parser.unescape(path)
return false unless path.valid_encoding?
+ path = Rack::Utils.clean_path_info path
- paths = [path, "#{path}#{ext}", "#{path}/index#{ext}"].map { |v|
- Rack::Utils.clean_path_info v
- }
+ paths = [path, "#{path}#{ext}", "#{path}/index#{ext}"]
if match = paths.detect { |p|
path = File.join(@root, p)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 948cbdc014..ce04f0b08a 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -395,9 +395,11 @@ module ActionDispatch
return if MountedHelpers.method_defined?(name)
routes = self
+ helpers = routes.url_helpers
+
MountedHelpers.class_eval do
define_method "_#{name}" do
- RoutesProxy.new(routes, _routes_context)
+ RoutesProxy.new(routes, _routes_context, helpers)
end
end
@@ -409,14 +411,6 @@ module ActionDispatch
end
def url_helpers(supports_path = true)
- if supports_path
- @url_helpers_with_paths ||= generate_url_helpers(supports_path)
- else
- @url_helpers_without_paths ||= generate_url_helpers(supports_path)
- end
- end
-
- def generate_url_helpers(supports_path)
routes = self
Module.new do
diff --git a/actionpack/lib/action_dispatch/routing/routes_proxy.rb b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
index e2393d3799..040ea04046 100644
--- a/actionpack/lib/action_dispatch/routing/routes_proxy.rb
+++ b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
@@ -8,8 +8,9 @@ module ActionDispatch
attr_accessor :scope, :routes
alias :_routes :routes
- def initialize(routes, scope)
+ def initialize(routes, scope, helpers)
@routes, @scope = routes, scope
+ @helpers = helpers
end
def url_options
@@ -19,16 +20,16 @@ module ActionDispatch
end
def respond_to?(method, include_private = false)
- super || routes.url_helpers.respond_to?(method)
+ super || @helpers.respond_to?(method)
end
def method_missing(method, *args)
- if routes.url_helpers.respond_to?(method)
+ if @helpers.respond_to?(method)
self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(*args)
options = args.extract_options!
args << url_options.merge((options || {}).symbolize_keys)
- routes.url_helpers.#{method}(*args)
+ @helpers.#{method}(*args)
end
RUBY
send(method, *args)
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index a927738b42..c94eea9134 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -38,18 +38,24 @@ module ActionDispatch
# # Test a custom route
# assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
def assert_recognizes(expected_options, path, extras={}, msg=nil)
- request = recognized_request_for(path, extras, msg)
+ if path.is_a?(Hash) && path[:method].to_s == "all"
+ [:get, :post, :put, :delete].each do |method|
+ assert_recognizes(expected_options, path.merge(method: method), extras, msg)
+ end
+ else
+ request = recognized_request_for(path, extras, msg)
- expected_options = expected_options.clone
+ expected_options = expected_options.clone
- expected_options.stringify_keys!
+ expected_options.stringify_keys!
- msg = message(msg, "") {
- sprintf("The recognized options <%s> did not match <%s>, difference:",
- request.path_parameters, expected_options)
- }
+ msg = message(msg, "") {
+ sprintf("The recognized options <%s> did not match <%s>, difference:",
+ request.path_parameters, expected_options)
+ }
- assert_equal(expected_options, request.path_parameters, msg)
+ assert_equal(expected_options, request.path_parameters, msg)
+ end
end
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index db6233840a..9b00616968 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -92,11 +92,12 @@ module ActionDispatch
end
end
- headers ||= {}
- headers.merge!(env) if env
- headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
- headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
- process(request_method, path, params: params, headers: headers)
+ ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
+ xhr and xml_http_request methods are deprecated in favor of
+ `get "/posts", xhr: true` and `post "/posts/1", xhr: true`
+ MSG
+
+ process(request_method, path, params: params, headers: headers, xhr: true)
end
alias xhr :xml_http_request
@@ -221,15 +222,6 @@ module ActionDispatch
super()
@app = app
- # If the app is a Rails app, make url_helpers available on the session
- # This makes app.url_for and app.foo_path available in the console
- if app.respond_to?(:routes)
- singleton_class.class_eval do
- include app.routes.url_helpers
- include app.routes.mounted_helpers
- end
- end
-
reset!
end
@@ -306,30 +298,29 @@ module ActionDispatch
end
end
- REQUEST_KWARGS = %i(params headers env)
+ REQUEST_KWARGS = %i(params headers env xhr)
def kwarg_request?(*args)
args[0].respond_to?(:keys) && args[0].keys.any? { |k| REQUEST_KWARGS.include?(k) }
end
def non_kwarg_request_warning
ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
- ActionDispatch::Integration::TestCase HTTP request methods will accept only
- keyword arguments in future Rails versions.
+ ActionDispatch::IntegrationTest HTTP request methods will accept only
+ the following keyword arguments in future Rails versions:
+ #{REQUEST_KWARGS.join(', ')}
Examples:
get '/profile',
params: { id: 1 },
headers: { 'X-Extra-Header' => '123' },
- env: { 'action_dispatch.custom' => 'custom' }
-
- xhr :post, '/profile',
- params: { id: 1 }
+ env: { 'action_dispatch.custom' => 'custom' },
+ xhr: true
MSG
end
# Performs the actual request.
- def process(method, path, params: nil, headers: nil, env: nil)
+ def process(method, path, params: nil, headers: nil, env: nil, xhr: false)
if path =~ %r{://}
location = URI.parse(path)
https! URI::HTTPS === location if location.scheme
@@ -354,6 +345,13 @@ module ActionDispatch
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
"HTTP_ACCEPT" => accept
}
+
+ if xhr
+ headers ||= {}
+ headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
+ headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ end
+
# this modifies the passed request_env directly
if headers.present?
Http::Headers.new(request_env).merge!(headers)
@@ -377,7 +375,7 @@ module ActionDispatch
@controller = session.last_request.env['action_controller.instance']
- return response.status
+ response.status
end
def build_full_uri(path, env)
@@ -388,14 +386,36 @@ module ActionDispatch
module Runner
include ActionDispatch::Assertions
- def app
- @app ||= nil
+ APP_SESSIONS = {}
+
+ attr_reader :app
+
+ def before_setup
+ super
+ @app = nil
+ @integration_session = nil
+ end
+
+ def integration_session
+ @integration_session ||= create_session(app)
end
# Reset the current session. This is useful for testing multiple sessions
# in a single test case.
def reset!
- @integration_session = Integration::Session.new(app)
+ @integration_session = create_session(app)
+ end
+
+ def create_session(app)
+ klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
+ # If the app is a Rails app, make url_helpers available on the session
+ # This makes app.url_for and app.foo_path available in the console
+ if app.respond_to?(:routes)
+ include app.routes.url_helpers
+ include app.routes.mounted_helpers
+ end
+ }
+ klass.new(app)
end
def remove! # :nodoc:
@@ -405,8 +425,6 @@ module ActionDispatch
%w(get post patch put head delete cookies assigns
xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
define_method(method) do |*args|
- reset! unless integration_session
-
# reset the html_document variable, except for cookies/assigns calls
unless method == 'cookies' || method == 'assigns'
@html_document = nil
@@ -438,19 +456,16 @@ module ActionDispatch
# Copy the instance variables from the current session instance into the
# test instance.
def copy_session_variables! #:nodoc:
- return unless integration_session
- %w(controller response request).each do |var|
- instance_variable_set("@#{var}", @integration_session.__send__(var))
- end
+ @controller = @integration_session.controller
+ @response = @integration_session.response
+ @request = @integration_session.request
end
def default_url_options
- reset! unless integration_session
integration_session.default_url_options
end
def default_url_options=(options)
- reset! unless integration_session
integration_session.default_url_options = options
end
@@ -460,7 +475,6 @@ module ActionDispatch
# Delegate unhandled messages to the current session instance.
def method_missing(sym, *args, &block)
- reset! unless integration_session
if integration_session.respond_to?(sym)
integration_session.__send__(sym, *args, &block).tap do
copy_session_variables!
@@ -469,11 +483,6 @@ module ActionDispatch
super
end
end
-
- private
- def integration_session
- @integration_session ||= nil
- end
end
end
@@ -650,7 +659,6 @@ module ActionDispatch
end
def url_options
- reset! unless integration_session
integration_session.url_options
end
diff --git a/actionpack/test/abstract/translation_test.rb b/actionpack/test/abstract/translation_test.rb
index 4fdc480b43..8289252dfc 100644
--- a/actionpack/test/abstract/translation_test.rb
+++ b/actionpack/test/abstract/translation_test.rb
@@ -9,6 +9,22 @@ module AbstractController
class TranslationControllerTest < ActiveSupport::TestCase
def setup
@controller = TranslationController.new
+ I18n.backend.store_translations(:en, {
+ one: {
+ two: 'bar',
+ },
+ abstract_controller: {
+ testing: {
+ translation: {
+ index: {
+ foo: 'bar',
+ },
+ no_action: 'no_action_tr',
+ },
+ },
+ },
+ })
+ @controller.stubs(action_name: :index)
end
def test_action_controller_base_responds_to_translate
@@ -28,16 +44,19 @@ module AbstractController
end
def test_lazy_lookup
- expected = 'bar'
- @controller.stubs(action_name: :index)
- I18n.stubs(:translate).with('abstract_controller.testing.translation.index.foo').returns(expected)
- assert_equal expected, @controller.t('.foo')
+ assert_equal 'bar', @controller.t('.foo')
+ end
+
+ def test_lazy_lookup_with_symbol
+ assert_equal 'bar', @controller.t(:'.foo')
+ end
+
+ def test_lazy_lookup_fallback
+ assert_equal 'no_action_tr', @controller.t(:'.no_action')
end
def test_default_translation
- key, expected = 'one.two', 'bar'
- I18n.stubs(:translate).with(key).returns(expected)
- assert_equal expected, @controller.t(key)
+ assert_equal 'bar', @controller.t('one.two')
end
def test_localize
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 17d5bae00b..9ab1549e8e 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -195,133 +195,112 @@ class SessionTest < ActiveSupport::TestCase
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: params, headers: headers_after_xhr)
- @session.xml_http_request(:get, path, params: params, headers: headers)
+ @session.expects(:process).with(:get, path, params: params, headers: headers, xhr: true)
+ @session.get(path, params: params, headers: headers, xhr: true)
end
def test_deprecated_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: params, headers: headers_after_xhr)
- assert_deprecated {
- @session.xml_http_request(:get,path,params,headers)
+ @session.expects(:process).with(:get, path, params: params, headers: headers, xhr: true)
+ @session.get(path, params: params, headers: headers, xhr: true)
+ end
+
+ def test_deprecated_args_xml_http_request_get
+ path = "/index"; params = "blah"; headers = { location: 'blah' }
+ @session.expects(:process).with(:get, path, params: params, headers: headers, xhr: true)
+ assert_deprecated(/xml_http_request/) {
+ @session.xml_http_request(:get, path, params, headers)
}
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: params, headers: headers_after_xhr)
- @session.xml_http_request(:post, path, params: params, headers: headers)
+ @session.expects(:process).with(:post, path, params: params, headers: headers, xhr: true)
+ @session.post(path, params: params, headers: headers, xhr: true)
end
def test_deprecated_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: params, headers: headers_after_xhr)
- assert_deprecated { @session.xml_http_request(:post,path,params,headers) }
+ @session.expects(:process).with(:post, path, params: params, headers: headers, xhr: true)
+ @session.post(path, params: params, headers: headers, xhr: true)
+ end
+
+ def test_deprecated_args_xml_http_request_post
+ path = "/index"; params = "blah"; headers = { location: 'blah' }
+ @session.expects(:process).with(:post, path, params: params, headers: headers, xhr: true)
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:post,path,params,headers) }
end
def test_xml_http_request_patch
path = "/index"; params = "blah"; headers = { location: 'blah' }
- headers_after_xhr = headers.merge(
- "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
- "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
- )
- @session.expects(:process).with(:patch, path, params: params, headers: headers_after_xhr)
- @session.xml_http_request(:patch, path, params: params, headers: headers)
+ @session.expects(:process).with(:patch, path, params: params, headers: headers, xhr: true)
+ @session.patch(path, params: params, headers: headers, xhr: true)
end
def test_deprecated_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: params, headers: headers_after_xhr)
- assert_deprecated { @session.xml_http_request(:patch,path,params,headers) }
+ @session.expects(:process).with(:patch, path, params: params, headers: headers, xhr: true)
+ @session.patch(path, params: params, headers: headers, xhr: true)
+ end
+
+ def test_deprecated_args_xml_http_request_patch
+ path = "/index"; params = "blah"; headers = { location: 'blah' }
+ @session.expects(:process).with(:patch, path, params: params, headers: headers, xhr: true)
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:patch,path,params,headers) }
end
def test_xml_http_request_put
path = "/index"; params = "blah"; headers = { location: 'blah' }
- headers_after_xhr = headers.merge(
- "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
- "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
- )
- @session.expects(:process).with(:put, path, params: params, headers: headers_after_xhr)
- @session.xml_http_request(:put, path, params: params, headers: headers)
+ @session.expects(:process).with(:put, path, params: params, headers: headers, xhr: true)
+ @session.put(path, params: params, headers: headers, xhr: true)
end
def test_deprecated_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: params, headers: headers_after_xhr)
- assert_deprecated { @session.xml_http_request(:put, path, params, headers) }
+ @session.expects(:process).with(:put, path, params: params, headers: headers, xhr: true)
+ @session.put(path, params: params, headers: headers, xhr: true)
+ end
+
+ def test_deprecated_args_xml_http_request_put
+ path = "/index"; params = "blah"; headers = { location: 'blah' }
+ @session.expects(:process).with(:put, path, params: params, headers: headers, xhr: true)
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:put, path, params, headers) }
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: params, headers: headers_after_xhr)
- @session.xml_http_request(:delete, path, params: params, headers: headers)
+ @session.expects(:process).with(:delete, path, params: params, headers: headers, xhr: true)
+ @session.delete(path, params: params, headers: headers, xhr: true)
end
def test_deprecated_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: params, headers: headers_after_xhr)
- assert_deprecated { @session.xml_http_request(:delete, path, params, headers) }
+ @session.expects(:process).with(:delete, path, params: params, headers: headers, xhr: true)
+ assert_deprecated { @session.xml_http_request(:delete, path, params: params, headers: headers) }
+ end
+
+ def test_deprecated_args_xml_http_request_delete
+ path = "/index"; params = "blah"; headers = { location: 'blah' }
+ @session.expects(:process).with(:delete, path, params: params, headers: headers, xhr: true)
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:delete, path, params, headers) }
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: params, headers: headers_after_xhr)
- @session.xml_http_request(:head, path, params: params, headers: headers)
+ @session.expects(:process).with(:head, path, params: params, headers: headers, xhr: true)
+ @session.head(path, params: params, headers: headers, xhr: true)
end
def test_deprecated_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: params, headers: headers_after_xhr)
- assert_deprecated { @session.xml_http_request(:head, path, params, headers) }
+ @session.expects(:process).with(:head, path, params: params, headers: headers, xhr: true)
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:head, path, params: params, headers: 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: params, headers: headers_after_xhr)
- @session.xml_http_request(:post, path, params: params, headers: headers)
+ def test_deprecated_args_xml_http_request_head
+ path = "/index"; params = "blah"; headers = { location: 'blah' }
+ @session.expects(:process).with(:head, path, params: params, headers: headers, xhr: true)
+ assert_deprecated { @session.xml_http_request(:head, path, params, headers) }
end
end
@@ -526,7 +505,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
@@ -538,7 +529,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
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index 8bd32f9584..1f5f66dc80 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -310,17 +310,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,7 +335,7 @@ 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'
@@ -357,13 +357,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 +408,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
@@ -525,7 +525,7 @@ 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
diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb
index d482df195f..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..b1ad16bc55 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
- 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_test.rb b/actionpack/test/controller/render_test.rb
index 1c3f436cfa..488585c7a4 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -58,6 +58,27 @@ class TestController < ActionController::Base
end
end
+ class Collection
+ def initialize(records)
+ @records = records
+ end
+
+ def maximum(attribute)
+ @records.max_by(&attribute).public_send(attribute)
+ end
+ end
+
+ 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
+
def conditional_hello_with_expires_in
expires_in 60.1.seconds
render :action => 'hello_world'
@@ -288,7 +309,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']
@@ -299,6 +319,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
@@ -317,6 +338,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']
@@ -512,3 +561,56 @@ class HeadRenderTest < ActionController::TestCase
assert_response :forbidden
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 text: 'hello'
+ end
+ end
+ end
+
+ tests HttpCacheForeverController
+
+ def test_cache_with_public
+ get :cache_me_forever, params: {public: true}
+ assert_equal "max-age=#{100.years.to_i}, 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.to_i}, 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/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 8a0eed5a87..8887f291cf 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -262,7 +262,7 @@ 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
@@ -340,11 +340,11 @@ 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
@@ -366,11 +366,18 @@ 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
+ @controller.unstub(:valid_authenticity_token?)
+ assert_blocked do
+ patch :index, params: { custom_authenticity_token: { foo: 'bar' } }
end
end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 02e7614ba2..f3da2df3ef 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -1047,6 +1047,28 @@ 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
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index 25337a7dd4..ca854040b7 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -706,19 +706,34 @@ 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_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"}), @response.body)
+ end
+
def test_xhr_with_params
- xhr :get, :test_params, params: { id: 1 }
+ get :test_params, params: { id: 1 }, xhr: true
assert_equal(%({"id"=>"1", "controller"=>"test_case_test/test", "action"=>"test_params"}), @response.body)
end
def test_xhr_with_session
- xhr :get, :set_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"
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index c61423dce4..5fbd19acdf 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -254,10 +254,6 @@ class ResponseTest < ActiveSupport::TestCase
end
class ResponseIntegrationTest < ActionDispatch::IntegrationTest
- def app
- @app
- end
-
test "response cache control from railsish app" do
@app = lambda { |env|
ActionDispatch::Response.new.tap { |resp|
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 3a95a9025f..ca5de05814 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -3477,6 +3477,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal '/post/comments/new', new_comment_path
end
+ def test_head_fetch_with_mount_on_root
+ draw do
+ get '/home' => 'test#index'
+ mount lambda { |env| [404, {"Content-Type" => "text/html"}, ["testing"]] }, at: '/'
+ end
+ head '/home'
+ assert_response :success
+
+ head '/'
+ assert_response :not_found
+ end
+
private
def draw(&block)