actionpack 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +379 -462
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/abstract_controller.rb +0 -2
- data/lib/abstract_controller/base.rb +17 -32
- data/lib/abstract_controller/callbacks.rb +52 -19
- data/lib/abstract_controller/collector.rb +4 -9
- data/lib/abstract_controller/helpers.rb +2 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
- data/lib/abstract_controller/rendering.rb +27 -22
- data/lib/abstract_controller/translation.rb +8 -7
- data/lib/action_controller.rb +4 -3
- data/lib/action_controller/api.rb +146 -0
- data/lib/action_controller/base.rb +6 -10
- data/lib/action_controller/caching.rb +1 -3
- data/lib/action_controller/caching/fragments.rb +48 -3
- data/lib/action_controller/form_builder.rb +48 -0
- data/lib/action_controller/log_subscriber.rb +1 -10
- data/lib/action_controller/metal.rb +89 -62
- data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
- data/lib/action_controller/metal/conditional_get.rb +65 -24
- data/lib/action_controller/metal/cookies.rb +0 -2
- data/lib/action_controller/metal/data_streaming.rb +2 -22
- data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +11 -6
- data/lib/action_controller/metal/force_ssl.rb +6 -6
- data/lib/action_controller/metal/head.rb +14 -7
- data/lib/action_controller/metal/helpers.rb +9 -5
- data/lib/action_controller/metal/http_authentication.rb +37 -38
- data/lib/action_controller/metal/implicit_render.rb +23 -6
- data/lib/action_controller/metal/instrumentation.rb +0 -1
- data/lib/action_controller/metal/live.rb +17 -55
- data/lib/action_controller/metal/mime_responds.rb +17 -37
- data/lib/action_controller/metal/params_wrapper.rb +8 -8
- data/lib/action_controller/metal/redirecting.rb +32 -9
- data/lib/action_controller/metal/renderers.rb +10 -8
- data/lib/action_controller/metal/rendering.rb +38 -6
- data/lib/action_controller/metal/request_forgery_protection.rb +67 -35
- data/lib/action_controller/metal/rescue.rb +2 -4
- data/lib/action_controller/metal/streaming.rb +4 -4
- data/lib/action_controller/metal/strong_parameters.rb +231 -78
- data/lib/action_controller/metal/testing.rb +1 -12
- data/lib/action_controller/metal/url_for.rb +12 -5
- data/lib/action_controller/renderer.rb +111 -0
- data/lib/action_controller/template_assertions.rb +9 -0
- data/lib/action_controller/test_case.rb +267 -363
- data/lib/action_dispatch.rb +2 -1
- data/lib/action_dispatch/http/cache.rb +23 -26
- data/lib/action_dispatch/http/filter_parameters.rb +6 -8
- data/lib/action_dispatch/http/filter_redirect.rb +7 -8
- data/lib/action_dispatch/http/headers.rb +28 -11
- data/lib/action_dispatch/http/mime_negotiation.rb +40 -26
- data/lib/action_dispatch/http/mime_type.rb +92 -61
- data/lib/action_dispatch/http/mime_types.rb +1 -4
- data/lib/action_dispatch/http/parameter_filter.rb +18 -8
- data/lib/action_dispatch/http/parameters.rb +45 -41
- data/lib/action_dispatch/http/request.rb +146 -82
- data/lib/action_dispatch/http/response.rb +180 -99
- data/lib/action_dispatch/http/url.rb +117 -8
- data/lib/action_dispatch/journey/formatter.rb +34 -28
- data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
- data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
- data/lib/action_dispatch/journey/nodes/node.rb +14 -4
- data/lib/action_dispatch/journey/parser_extras.rb +4 -0
- data/lib/action_dispatch/journey/path/pattern.rb +37 -41
- data/lib/action_dispatch/journey/route.rb +71 -17
- data/lib/action_dispatch/journey/router.rb +5 -6
- data/lib/action_dispatch/journey/router/utils.rb +5 -5
- data/lib/action_dispatch/journey/routes.rb +14 -15
- data/lib/action_dispatch/journey/visitors.rb +86 -43
- data/lib/action_dispatch/middleware/cookies.rb +184 -135
- data/lib/action_dispatch/middleware/debug_exceptions.rb +115 -45
- data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -20
- data/lib/action_dispatch/middleware/flash.rb +61 -45
- data/lib/action_dispatch/middleware/load_interlock.rb +21 -0
- data/lib/action_dispatch/middleware/params_parser.rb +30 -46
- data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +2 -4
- data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
- data/lib/action_dispatch/middleware/request_id.rb +11 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
- data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +29 -23
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
- data/lib/action_dispatch/middleware/ssl.rb +93 -36
- data/lib/action_dispatch/middleware/stack.rb +43 -48
- data/lib/action_dispatch/middleware/static.rb +52 -40
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +59 -63
- data/lib/action_dispatch/railtie.rb +0 -2
- data/lib/action_dispatch/request/session.rb +66 -34
- data/lib/action_dispatch/request/utils.rb +51 -19
- data/lib/action_dispatch/routing.rb +3 -8
- data/lib/action_dispatch/routing/inspector.rb +6 -30
- data/lib/action_dispatch/routing/mapper.rb +447 -322
- data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +124 -227
- data/lib/action_dispatch/routing/url_for.rb +27 -10
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +27 -9
- data/lib/action_dispatch/testing/assertions/routing.rb +9 -9
- data/lib/action_dispatch/testing/integration.rb +237 -76
- data/lib/action_dispatch/testing/test_process.rb +5 -5
- data/lib/action_dispatch/testing/test_request.rb +12 -21
- data/lib/action_dispatch/testing/test_response.rb +1 -4
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +26 -25
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -2,19 +2,8 @@ module ActionController
|
|
2
2
|
module Testing
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
include RackDelegation
|
6
|
-
|
7
|
-
# TODO : Rewrite tests using controller.headers= to use Rack env
|
8
|
-
def headers=(new_headers)
|
9
|
-
@_response ||= ActionDispatch::Response.new
|
10
|
-
@_response.headers.replace(new_headers)
|
11
|
-
end
|
12
|
-
|
13
5
|
# Behavior specific to functional tests
|
14
6
|
module Functional # :nodoc:
|
15
|
-
def set_response!(request)
|
16
|
-
end
|
17
|
-
|
18
7
|
def recycle!
|
19
8
|
@_url_options = nil
|
20
9
|
self.formats = nil
|
@@ -24,7 +13,7 @@ module ActionController
|
|
24
13
|
|
25
14
|
module ClassMethods
|
26
15
|
def before_filters
|
27
|
-
_process_action_callbacks.find_all{|x| x.kind == :before}.map
|
16
|
+
_process_action_callbacks.find_all{|x| x.kind == :before}.map(&:name)
|
28
17
|
end
|
29
18
|
end
|
30
19
|
end
|
@@ -4,7 +4,10 @@ module ActionController
|
|
4
4
|
#
|
5
5
|
# In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
|
6
6
|
# url options like the +host+. In order to do so, this module requires the host class
|
7
|
-
# to implement +env+
|
7
|
+
# to implement +env+ which needs to be Rack-compatible and +request+
|
8
|
+
# which is either an instance of +ActionDispatch::Request+ or an object
|
9
|
+
# that responds to the +host+, +optional_port+, +protocol+ and
|
10
|
+
# +symbolized_path_parameter+ methods.
|
8
11
|
#
|
9
12
|
# class RootUrl
|
10
13
|
# include ActionController::UrlFor
|
@@ -30,15 +33,19 @@ module ActionController
|
|
30
33
|
:_recall => request.path_parameters
|
31
34
|
}.merge!(super).freeze
|
32
35
|
|
33
|
-
if (same_origin = _routes.equal?(
|
34
|
-
(script_name =
|
35
|
-
(original_script_name =
|
36
|
+
if (same_origin = _routes.equal?(request.routes)) ||
|
37
|
+
(script_name = request.engine_script_name(_routes)) ||
|
38
|
+
(original_script_name = request.original_script_name)
|
36
39
|
|
37
40
|
options = @_url_options.dup
|
38
41
|
if original_script_name
|
39
42
|
options[:original_script_name] = original_script_name
|
40
43
|
else
|
41
|
-
|
44
|
+
if same_origin
|
45
|
+
options[:script_name] = request.script_name.empty? ? "".freeze : request.script_name.dup
|
46
|
+
else
|
47
|
+
options[:script_name] = script_name
|
48
|
+
end
|
42
49
|
end
|
43
50
|
options.freeze
|
44
51
|
else
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
# ActionController::Renderer allows to render arbitrary templates
|
5
|
+
# without requirement of being in controller actions.
|
6
|
+
#
|
7
|
+
# You get a concrete renderer class by invoking ActionController::Base#renderer.
|
8
|
+
# For example,
|
9
|
+
#
|
10
|
+
# ApplicationController.renderer
|
11
|
+
#
|
12
|
+
# It allows you to call method #render directly.
|
13
|
+
#
|
14
|
+
# ApplicationController.renderer.render template: '...'
|
15
|
+
#
|
16
|
+
# You can use a shortcut on controller to replace previous example with:
|
17
|
+
#
|
18
|
+
# ApplicationController.render template: '...'
|
19
|
+
#
|
20
|
+
# #render method allows you to use any options as when rendering in controller.
|
21
|
+
# For example,
|
22
|
+
#
|
23
|
+
# FooController.render :action, locals: { ... }, assigns: { ... }
|
24
|
+
#
|
25
|
+
# The template will be rendered in a Rack environment which is accessible through
|
26
|
+
# ActionController::Renderer#env. You can set it up in two ways:
|
27
|
+
#
|
28
|
+
# * by changing renderer defaults, like
|
29
|
+
#
|
30
|
+
# ApplicationController.renderer.defaults # => hash with default Rack environment
|
31
|
+
#
|
32
|
+
# * by initializing an instance of renderer by passing it a custom environment.
|
33
|
+
#
|
34
|
+
# ApplicationController.renderer.new(method: 'post', https: true)
|
35
|
+
#
|
36
|
+
class Renderer
|
37
|
+
attr_reader :defaults, :controller
|
38
|
+
|
39
|
+
DEFAULTS = {
|
40
|
+
http_host: 'example.org',
|
41
|
+
https: false,
|
42
|
+
method: 'get',
|
43
|
+
script_name: '',
|
44
|
+
input: ''
|
45
|
+
}.freeze
|
46
|
+
|
47
|
+
# Create a new renderer instance for a specific controller class.
|
48
|
+
def self.for(controller, env = {}, defaults = DEFAULTS)
|
49
|
+
new(controller, env, defaults)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Create a new renderer for the same controller but with a new env.
|
53
|
+
def new(env = {})
|
54
|
+
self.class.new controller, env, defaults
|
55
|
+
end
|
56
|
+
|
57
|
+
# Create a new renderer for the same controller but with new defaults.
|
58
|
+
def with_defaults(defaults)
|
59
|
+
self.class.new controller, env, self.defaults.merge(defaults)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Accepts a custom Rack environment to render templates in.
|
63
|
+
# It will be merged with ActionController::Renderer.defaults
|
64
|
+
def initialize(controller, env, defaults)
|
65
|
+
@controller = controller
|
66
|
+
@defaults = defaults
|
67
|
+
@env = normalize_keys defaults.merge(env)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Render templates with any options from ActionController::Base#render_to_string.
|
71
|
+
def render(*args)
|
72
|
+
raise 'missing controller' unless controller
|
73
|
+
|
74
|
+
request = ActionDispatch::Request.new @env
|
75
|
+
request.routes = controller._routes
|
76
|
+
|
77
|
+
instance = controller.new
|
78
|
+
instance.set_request! request
|
79
|
+
instance.set_response! controller.make_response!(request)
|
80
|
+
instance.render_to_string(*args)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def normalize_keys(env)
|
85
|
+
new_env = {}
|
86
|
+
env.each_pair { |k,v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
|
87
|
+
new_env
|
88
|
+
end
|
89
|
+
|
90
|
+
RACK_KEY_TRANSLATION = {
|
91
|
+
http_host: 'HTTP_HOST',
|
92
|
+
https: 'HTTPS',
|
93
|
+
method: 'REQUEST_METHOD',
|
94
|
+
script_name: 'SCRIPT_NAME',
|
95
|
+
input: 'rack.input'
|
96
|
+
}
|
97
|
+
|
98
|
+
IDENTITY = ->(_) { _ }
|
99
|
+
|
100
|
+
RACK_VALUE_TRANSLATION = {
|
101
|
+
https: ->(v) { v ? 'on' : 'off' },
|
102
|
+
method: ->(v) { v.upcase },
|
103
|
+
}
|
104
|
+
|
105
|
+
def rack_key_for(key); RACK_KEY_TRANSLATION[key]; end
|
106
|
+
|
107
|
+
def rack_value_for(key, value)
|
108
|
+
RACK_VALUE_TRANSLATION.fetch(key, IDENTITY).call value
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module ActionController
|
2
|
+
module TemplateAssertions
|
3
|
+
def assert_template(options = {}, message = nil)
|
4
|
+
raise NoMethodError,
|
5
|
+
"assert_template has been extracted to a gem. To continue using it,
|
6
|
+
add `gem 'rails-controller-testing'` to your Gemfile."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -1,224 +1,60 @@
|
|
1
1
|
require 'rack/session/abstract/id'
|
2
|
+
require 'active_support/core_ext/hash/conversions'
|
2
3
|
require 'active_support/core_ext/object/to_query'
|
3
4
|
require 'active_support/core_ext/module/anonymous'
|
4
5
|
require 'active_support/core_ext/hash/keys'
|
5
|
-
require '
|
6
|
-
|
6
|
+
require 'action_controller/template_assertions'
|
7
7
|
require 'rails-dom-testing'
|
8
8
|
|
9
9
|
module ActionController
|
10
|
-
|
11
|
-
|
10
|
+
# :stopdoc:
|
11
|
+
# ActionController::TestCase will be deprecated and moved to a gem in Rails 5.1.
|
12
|
+
# Please use ActionDispatch::IntegrationTest going forward.
|
13
|
+
class TestRequest < ActionDispatch::TestRequest #:nodoc:
|
14
|
+
DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
|
15
|
+
DEFAULT_ENV.delete 'PATH_INFO'
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
teardown :teardown_subscriptions
|
17
|
+
def self.new_session
|
18
|
+
TestSession.new
|
16
19
|
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@_subscribers = []
|
26
|
-
|
27
|
-
@_subscribers << ActiveSupport::Notifications.subscribe("render_template.action_view") do |_name, _start, _finish, _id, payload|
|
28
|
-
path = payload[:layout]
|
29
|
-
if path
|
30
|
-
@_layouts[path] += 1
|
31
|
-
if path =~ /^layouts\/(.*)/
|
32
|
-
@_layouts[$1] += 1
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
@_subscribers << ActiveSupport::Notifications.subscribe("!render_template.action_view") do |_name, _start, _finish, _id, payload|
|
38
|
-
if virtual_path = payload[:virtual_path]
|
39
|
-
partial = virtual_path =~ /^.*\/_[^\/]*$/
|
40
|
-
|
41
|
-
if partial
|
42
|
-
@_partials[virtual_path] += 1
|
43
|
-
@_partials[virtual_path.split("/").last] += 1
|
44
|
-
end
|
45
|
-
|
46
|
-
@_templates[virtual_path] += 1
|
47
|
-
else
|
48
|
-
path = payload[:identifier]
|
49
|
-
if path
|
50
|
-
@_files[path] += 1
|
51
|
-
@_files[path.split("/").last] += 1
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
21
|
+
# Create a new test request with default `env` values
|
22
|
+
def self.create
|
23
|
+
env = {}
|
24
|
+
env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
|
25
|
+
env["rack.request.cookie_hash"] = {}.with_indifferent_access
|
26
|
+
new(default_env.merge(env), new_session)
|
55
27
|
end
|
56
28
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
@_subscribers.each do |subscriber|
|
61
|
-
ActiveSupport::Notifications.unsubscribe(subscriber)
|
62
|
-
end
|
29
|
+
def self.default_env
|
30
|
+
DEFAULT_ENV
|
63
31
|
end
|
32
|
+
private_class_method :default_env
|
64
33
|
|
65
|
-
def
|
66
|
-
|
67
|
-
super
|
68
|
-
end
|
34
|
+
def initialize(env, session)
|
35
|
+
super(env)
|
69
36
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
37
|
+
self.session = session
|
38
|
+
self.session_options = TestSession::DEFAULT_OPTIONS
|
39
|
+
@custom_param_parsers = {
|
40
|
+
Mime[:xml] => lambda { |raw_post| Hash.from_xml(raw_post)['hash'] }
|
41
|
+
}
|
77
42
|
end
|
78
43
|
|
79
|
-
|
80
|
-
|
81
|
-
# # assert that the "new" view template was rendered
|
82
|
-
# assert_template "new"
|
83
|
-
#
|
84
|
-
# # assert that the exact template "admin/posts/new" was rendered
|
85
|
-
# assert_template %r{\Aadmin/posts/new\Z}
|
86
|
-
#
|
87
|
-
# # assert that the layout 'admin' was rendered
|
88
|
-
# assert_template layout: 'admin'
|
89
|
-
# assert_template layout: 'layouts/admin'
|
90
|
-
# assert_template layout: :admin
|
91
|
-
#
|
92
|
-
# # assert that no layout was rendered
|
93
|
-
# assert_template layout: nil
|
94
|
-
# assert_template layout: false
|
95
|
-
#
|
96
|
-
# # assert that the "_customer" partial was rendered twice
|
97
|
-
# assert_template partial: '_customer', count: 2
|
98
|
-
#
|
99
|
-
# # assert that no partials were rendered
|
100
|
-
# assert_template partial: false
|
101
|
-
#
|
102
|
-
# # assert that a file was rendered
|
103
|
-
# assert_template file: "README.rdoc"
|
104
|
-
#
|
105
|
-
# # assert that no file was rendered
|
106
|
-
# assert_template file: nil
|
107
|
-
# assert_template file: false
|
108
|
-
#
|
109
|
-
# In a view test case, you can also assert that specific locals are passed
|
110
|
-
# to partials:
|
111
|
-
#
|
112
|
-
# # assert that the "_customer" partial was rendered with a specific object
|
113
|
-
# assert_template partial: '_customer', locals: { customer: @customer }
|
114
|
-
def assert_template(options = {}, message = nil)
|
115
|
-
# Force body to be read in case the template is being streamed.
|
116
|
-
response.body
|
117
|
-
|
118
|
-
case options
|
119
|
-
when NilClass, Regexp, String, Symbol
|
120
|
-
options = options.to_s if Symbol === options
|
121
|
-
rendered = @_templates
|
122
|
-
msg = message || sprintf("expecting <%s> but rendering with <%s>",
|
123
|
-
options.inspect, rendered.keys)
|
124
|
-
matches_template =
|
125
|
-
case options
|
126
|
-
when String
|
127
|
-
!options.empty? && rendered.any? do |t, num|
|
128
|
-
options_splited = options.split(File::SEPARATOR)
|
129
|
-
t_splited = t.split(File::SEPARATOR)
|
130
|
-
t_splited.last(options_splited.size) == options_splited
|
131
|
-
end
|
132
|
-
when Regexp
|
133
|
-
rendered.any? { |t,num| t.match(options) }
|
134
|
-
when NilClass
|
135
|
-
rendered.blank?
|
136
|
-
end
|
137
|
-
assert matches_template, msg
|
138
|
-
when Hash
|
139
|
-
options.assert_valid_keys(:layout, :partial, :locals, :count, :file)
|
140
|
-
|
141
|
-
if options.key?(:layout)
|
142
|
-
expected_layout = options[:layout]
|
143
|
-
msg = message || sprintf("expecting layout <%s> but action rendered <%s>",
|
144
|
-
expected_layout, @_layouts.keys)
|
145
|
-
|
146
|
-
case expected_layout
|
147
|
-
when String, Symbol
|
148
|
-
assert_includes @_layouts.keys, expected_layout.to_s, msg
|
149
|
-
when Regexp
|
150
|
-
assert(@_layouts.keys.any? {|l| l =~ expected_layout }, msg)
|
151
|
-
when nil, false
|
152
|
-
assert(@_layouts.empty?, msg)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
if options[:file]
|
157
|
-
assert_includes @_files.keys, options[:file]
|
158
|
-
elsif options.key?(:file)
|
159
|
-
assert @_files.blank?, "expected no files but #{@_files.keys} was rendered"
|
160
|
-
end
|
161
|
-
|
162
|
-
if expected_partial = options[:partial]
|
163
|
-
if expected_locals = options[:locals]
|
164
|
-
if defined?(@_rendered_views)
|
165
|
-
view = expected_partial.to_s.sub(/^_/, '').sub(/\/_(?=[^\/]+\z)/, '/')
|
166
|
-
|
167
|
-
partial_was_not_rendered_msg = "expected %s to be rendered but it was not." % view
|
168
|
-
assert_includes @_rendered_views.rendered_views, view, partial_was_not_rendered_msg
|
169
|
-
|
170
|
-
msg = 'expecting %s to be rendered with %s but was with %s' % [expected_partial,
|
171
|
-
expected_locals,
|
172
|
-
@_rendered_views.locals_for(view)]
|
173
|
-
assert(@_rendered_views.view_rendered?(view, options[:locals]), msg)
|
174
|
-
else
|
175
|
-
warn "the :locals option to #assert_template is only supported in a ActionView::TestCase"
|
176
|
-
end
|
177
|
-
elsif expected_count = options[:count]
|
178
|
-
actual_count = @_partials[expected_partial]
|
179
|
-
msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
|
180
|
-
expected_partial, expected_count, actual_count)
|
181
|
-
assert(actual_count == expected_count.to_i, msg)
|
182
|
-
else
|
183
|
-
msg = message || sprintf("expecting partial <%s> but action rendered <%s>",
|
184
|
-
options[:partial], @_partials.keys)
|
185
|
-
assert_includes @_partials, expected_partial, msg
|
186
|
-
end
|
187
|
-
elsif options.key?(:partial)
|
188
|
-
assert @_partials.empty?,
|
189
|
-
"Expected no partials to be rendered"
|
190
|
-
end
|
191
|
-
else
|
192
|
-
raise ArgumentError, "assert_template only accepts a String, Symbol, Hash, Regexp, or nil"
|
193
|
-
end
|
44
|
+
def query_string=(string)
|
45
|
+
set_header Rack::QUERY_STRING, string
|
194
46
|
end
|
195
|
-
end
|
196
|
-
|
197
|
-
class TestRequest < ActionDispatch::TestRequest #:nodoc:
|
198
|
-
DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
|
199
|
-
DEFAULT_ENV.delete 'PATH_INFO'
|
200
|
-
|
201
|
-
def initialize(env = {})
|
202
|
-
super
|
203
47
|
|
204
|
-
|
205
|
-
|
48
|
+
def content_type=(type)
|
49
|
+
set_header 'CONTENT_TYPE', type
|
206
50
|
end
|
207
51
|
|
208
|
-
def assign_parameters(routes, controller_path, action, parameters
|
209
|
-
|
210
|
-
|
211
|
-
non_path_parameters = get? ? query_parameters : request_parameters
|
212
|
-
parameters.each do |key, value|
|
213
|
-
if value.is_a?(Array) && (value.frozen? || value.any?(&:frozen?))
|
214
|
-
value = value.map{ |v| v.duplicable? ? v.dup : v }
|
215
|
-
elsif value.is_a?(Hash) && (value.frozen? || value.any?{ |k,v| v.frozen? })
|
216
|
-
value = Hash[value.map{ |k,v| [k, v.duplicable? ? v.dup : v] }]
|
217
|
-
elsif value.frozen? && value.duplicable?
|
218
|
-
value = value.dup
|
219
|
-
end
|
52
|
+
def assign_parameters(routes, controller_path, action, parameters, generated_path, query_string_keys)
|
53
|
+
non_path_parameters = {}
|
54
|
+
path_parameters = {}
|
220
55
|
|
221
|
-
|
56
|
+
parameters.each do |key, value|
|
57
|
+
if query_string_keys.include?(key)
|
222
58
|
non_path_parameters[key] = value
|
223
59
|
else
|
224
60
|
if value.is_a?(Array)
|
@@ -231,72 +67,88 @@ module ActionController
|
|
231
67
|
end
|
232
68
|
end
|
233
69
|
|
234
|
-
|
235
|
-
|
70
|
+
if get?
|
71
|
+
if self.query_string.blank?
|
72
|
+
self.query_string = non_path_parameters.to_query
|
73
|
+
end
|
74
|
+
else
|
75
|
+
if ENCODER.should_multipart?(non_path_parameters)
|
76
|
+
self.content_type = ENCODER.content_type
|
77
|
+
data = ENCODER.build_multipart non_path_parameters
|
78
|
+
else
|
79
|
+
fetch_header('CONTENT_TYPE') do |k|
|
80
|
+
set_header k, 'application/x-www-form-urlencoded'
|
81
|
+
end
|
236
82
|
|
237
|
-
|
238
|
-
|
83
|
+
case content_mime_type.to_sym
|
84
|
+
when nil
|
85
|
+
raise "Unknown Content-Type: #{content_type}"
|
86
|
+
when :json
|
87
|
+
data = ActiveSupport::JSON.encode(non_path_parameters)
|
88
|
+
when :xml
|
89
|
+
data = non_path_parameters.to_xml
|
90
|
+
when :url_encoded_form
|
91
|
+
data = non_path_parameters.to_query
|
92
|
+
else
|
93
|
+
@custom_param_parsers[content_mime_type] = ->(_) { non_path_parameters }
|
94
|
+
data = non_path_parameters.to_query
|
95
|
+
end
|
96
|
+
end
|
239
97
|
|
240
|
-
|
241
|
-
|
242
|
-
params.delete(k)
|
243
|
-
params.delete(k.to_sym)
|
98
|
+
set_header 'CONTENT_LENGTH', data.length.to_s
|
99
|
+
set_header 'rack.input', StringIO.new(data)
|
244
100
|
end
|
245
|
-
data = params.to_query
|
246
101
|
|
247
|
-
|
248
|
-
|
249
|
-
|
102
|
+
fetch_header("PATH_INFO") do |k|
|
103
|
+
set_header k, generated_path
|
104
|
+
end
|
105
|
+
path_parameters[:controller] = controller_path
|
106
|
+
path_parameters[:action] = action
|
250
107
|
|
251
|
-
|
252
|
-
@formats = nil
|
253
|
-
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
|
254
|
-
@env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
|
255
|
-
@method = @request_method = nil
|
256
|
-
@fullpath = @ip = @remote_ip = @protocol = nil
|
257
|
-
@env['action_dispatch.request.query_parameters'] = {}
|
258
|
-
@set_cookies ||= {}
|
259
|
-
@set_cookies.update(Hash[cookie_jar.instance_variable_get("@set_cookies").map{ |k,o| [k,o[:value]] }])
|
260
|
-
deleted_cookies = cookie_jar.instance_variable_get("@delete_cookies")
|
261
|
-
@set_cookies.reject!{ |k,v| deleted_cookies.include?(k) }
|
262
|
-
cookie_jar.update(rack_cookies)
|
263
|
-
cookie_jar.update(cookies)
|
264
|
-
cookie_jar.update(@set_cookies)
|
265
|
-
cookie_jar.recycle!
|
108
|
+
self.path_parameters = path_parameters
|
266
109
|
end
|
267
110
|
|
268
|
-
|
111
|
+
ENCODER = Class.new do
|
112
|
+
include Rack::Test::Utils
|
113
|
+
|
114
|
+
def should_multipart?(params)
|
115
|
+
# FIXME: lifted from Rack-Test. We should push this separation upstream
|
116
|
+
multipart = false
|
117
|
+
query = lambda { |value|
|
118
|
+
case value
|
119
|
+
when Array
|
120
|
+
value.each(&query)
|
121
|
+
when Hash
|
122
|
+
value.values.each(&query)
|
123
|
+
when Rack::Test::UploadedFile
|
124
|
+
multipart = true
|
125
|
+
end
|
126
|
+
}
|
127
|
+
params.values.each(&query)
|
128
|
+
multipart
|
129
|
+
end
|
269
130
|
|
270
|
-
|
271
|
-
DEFAULT_ENV
|
272
|
-
end
|
273
|
-
end
|
131
|
+
public :build_multipart
|
274
132
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
end
|
279
|
-
end
|
133
|
+
def content_type
|
134
|
+
"multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}"
|
135
|
+
end
|
136
|
+
end.new
|
280
137
|
|
281
|
-
|
282
|
-
def recycle!
|
283
|
-
@body = nil
|
284
|
-
initialize
|
285
|
-
end
|
138
|
+
private
|
286
139
|
|
287
|
-
def
|
288
|
-
@
|
140
|
+
def params_parsers
|
141
|
+
super.merge @custom_param_parsers
|
289
142
|
end
|
143
|
+
end
|
290
144
|
|
145
|
+
class LiveTestResponse < Live::Response
|
291
146
|
# Was the response successful?
|
292
147
|
alias_method :success?, :successful?
|
293
148
|
|
294
149
|
# Was the URL not found?
|
295
150
|
alias_method :missing?, :not_found?
|
296
151
|
|
297
|
-
# Were we redirected?
|
298
|
-
alias_method :redirect?, :redirection?
|
299
|
-
|
300
152
|
# Was there a server-side error?
|
301
153
|
alias_method :error?, :server_error?
|
302
154
|
end
|
@@ -304,7 +156,7 @@ module ActionController
|
|
304
156
|
# Methods #destroy and #load! are overridden to avoid calling methods on the
|
305
157
|
# @store object, which does not exist for the TestSession class.
|
306
158
|
class TestSession < Rack::Session::Abstract::SessionHash #:nodoc:
|
307
|
-
DEFAULT_OPTIONS = Rack::Session::Abstract::
|
159
|
+
DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
|
308
160
|
|
309
161
|
def initialize(session = {})
|
310
162
|
super(nil, nil)
|
@@ -359,13 +211,13 @@ module ActionController
|
|
359
211
|
# class BooksControllerTest < ActionController::TestCase
|
360
212
|
# def test_create
|
361
213
|
# # Simulate a POST response with the given HTTP parameters.
|
362
|
-
# post(:create, book: { title: "Love Hina" })
|
214
|
+
# post(:create, params: { book: { title: "Love Hina" }})
|
363
215
|
#
|
364
|
-
# #
|
216
|
+
# # Asserts that the controller tried to redirect us to
|
365
217
|
# # the created book's URI.
|
366
218
|
# assert_response :found
|
367
219
|
#
|
368
|
-
# #
|
220
|
+
# # Asserts that the controller really put the book in the database.
|
369
221
|
# assert_not_nil Book.find_by(title: "Love Hina")
|
370
222
|
# end
|
371
223
|
# end
|
@@ -389,7 +241,7 @@ module ActionController
|
|
389
241
|
# request. You can modify this object before sending the HTTP request. For example,
|
390
242
|
# you might want to set some session properties before sending a GET request.
|
391
243
|
# <b>@response</b>::
|
392
|
-
# An
|
244
|
+
# An ActionDispatch::TestResponse object, representing the response
|
393
245
|
# of the last HTTP response. In the above example, <tt>@response</tt> becomes valid
|
394
246
|
# after calling +post+. If the various assert methods are not sufficient, then you
|
395
247
|
# may use this object to inspect the HTTP response in detail.
|
@@ -412,21 +264,15 @@ module ActionController
|
|
412
264
|
# In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions
|
413
265
|
# can be used against. These collections are:
|
414
266
|
#
|
415
|
-
# * assigns: Instance variables assigned in the action that are available for the view.
|
416
267
|
# * session: Objects being saved in the session.
|
417
268
|
# * flash: The flash objects currently in the session.
|
418
269
|
# * cookies: \Cookies being sent to the user on this request.
|
419
270
|
#
|
420
271
|
# These collections can be used just like any other hash:
|
421
272
|
#
|
422
|
-
# assert_not_nil assigns(:person) # makes sure that a @person instance variable was set
|
423
273
|
# assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
|
424
274
|
# assert flash.empty? # makes sure that there's nothing in the flash
|
425
275
|
#
|
426
|
-
# For historic reasons, the assigns hash uses string-based keys. So <tt>assigns[:person]</tt> won't work, but <tt>assigns["person"]</tt> will. To
|
427
|
-
# appease our yearning for symbols, though, an alternative accessor has been devised using a method call instead of index referencing.
|
428
|
-
# So <tt>assigns(:person)</tt> will work just like <tt>assigns["person"]</tt>, but again, <tt>assigns[:person]</tt> will not work.
|
429
|
-
#
|
430
276
|
# On top of the collections, you have the complete url that a given action redirected to available in <tt>redirect_to_url</tt>.
|
431
277
|
#
|
432
278
|
# For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
|
@@ -499,169 +345,227 @@ module ActionController
|
|
499
345
|
# Simulate a GET request with the given parameters.
|
500
346
|
#
|
501
347
|
# - +action+: The controller action to call.
|
502
|
-
# - +
|
503
|
-
#
|
348
|
+
# - +params+: The hash with HTTP parameters that you want to pass. This may be +nil+.
|
349
|
+
# - +body+: The request body with a string that is appropriately encoded
|
504
350
|
# (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
|
505
351
|
# - +session+: A hash of parameters to store in the session. This may be +nil+.
|
506
352
|
# - +flash+: A hash of parameters to store in the flash. This may be +nil+.
|
507
353
|
#
|
508
354
|
# You can also simulate POST, PATCH, PUT, DELETE, and HEAD requests with
|
509
355
|
# +post+, +patch+, +put+, +delete+, and +head+.
|
356
|
+
# Example sending parameters, session and setting a flash message:
|
357
|
+
#
|
358
|
+
# get :show,
|
359
|
+
# params: { id: 7 },
|
360
|
+
# session: { user_id: 1 },
|
361
|
+
# flash: { notice: 'This is flash message' }
|
510
362
|
#
|
511
363
|
# Note that the request method is not verified. The different methods are
|
512
364
|
# available to make the tests more expressive.
|
513
365
|
def get(action, *args)
|
514
|
-
|
366
|
+
res = process_with_kwargs("GET", action, *args)
|
367
|
+
cookies.update res.cookies
|
368
|
+
res
|
515
369
|
end
|
516
370
|
|
517
371
|
# Simulate a POST request with the given parameters and set/volley the response.
|
518
372
|
# See +get+ for more details.
|
519
373
|
def post(action, *args)
|
520
|
-
|
374
|
+
process_with_kwargs("POST", action, *args)
|
521
375
|
end
|
522
376
|
|
523
377
|
# Simulate a PATCH request with the given parameters and set/volley the response.
|
524
378
|
# See +get+ for more details.
|
525
379
|
def patch(action, *args)
|
526
|
-
|
380
|
+
process_with_kwargs("PATCH", action, *args)
|
527
381
|
end
|
528
382
|
|
529
383
|
# Simulate a PUT request with the given parameters and set/volley the response.
|
530
384
|
# See +get+ for more details.
|
531
385
|
def put(action, *args)
|
532
|
-
|
386
|
+
process_with_kwargs("PUT", action, *args)
|
533
387
|
end
|
534
388
|
|
535
389
|
# Simulate a DELETE request with the given parameters and set/volley the response.
|
536
390
|
# See +get+ for more details.
|
537
391
|
def delete(action, *args)
|
538
|
-
|
392
|
+
process_with_kwargs("DELETE", action, *args)
|
539
393
|
end
|
540
394
|
|
541
395
|
# Simulate a HEAD request with the given parameters and set/volley the response.
|
542
396
|
# See +get+ for more details.
|
543
397
|
def head(action, *args)
|
544
|
-
|
398
|
+
process_with_kwargs("HEAD", action, *args)
|
545
399
|
end
|
546
400
|
|
547
|
-
def xml_http_request(
|
401
|
+
def xml_http_request(*args)
|
402
|
+
ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
|
403
|
+
xhr and xml_http_request methods are deprecated in favor of
|
404
|
+
`get :index, xhr: true` and `post :create, xhr: true`
|
405
|
+
MSG
|
406
|
+
|
548
407
|
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
549
|
-
@request.env['HTTP_ACCEPT'] ||=
|
550
|
-
__send__(
|
408
|
+
@request.env['HTTP_ACCEPT'] ||= [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ')
|
409
|
+
__send__(*args).tap do
|
551
410
|
@request.env.delete 'HTTP_X_REQUESTED_WITH'
|
552
411
|
@request.env.delete 'HTTP_ACCEPT'
|
553
412
|
end
|
554
413
|
end
|
555
414
|
alias xhr :xml_http_request
|
556
415
|
|
557
|
-
def paramify_values(hash_or_array_or_value)
|
558
|
-
case hash_or_array_or_value
|
559
|
-
when Hash
|
560
|
-
Hash[hash_or_array_or_value.map{|key, value| [key, paramify_values(value)] }]
|
561
|
-
when Array
|
562
|
-
hash_or_array_or_value.map {|i| paramify_values(i)}
|
563
|
-
when Rack::Test::UploadedFile, ActionDispatch::Http::UploadedFile
|
564
|
-
hash_or_array_or_value
|
565
|
-
else
|
566
|
-
hash_or_array_or_value.to_param
|
567
|
-
end
|
568
|
-
end
|
569
|
-
|
570
416
|
# Simulate a HTTP request to +action+ by specifying request method,
|
571
417
|
# parameters and set/volley the response.
|
572
418
|
#
|
573
419
|
# - +action+: The controller action to call.
|
574
|
-
# - +
|
575
|
-
# are +GET+, +POST+, +PATCH+, +PUT+, +DELETE+, +HEAD+. Defaults to +GET+.
|
576
|
-
# - +
|
577
|
-
#
|
578
|
-
# or
|
420
|
+
# - +method+: Request method used to send the HTTP request. Possible values
|
421
|
+
# are +GET+, +POST+, +PATCH+, +PUT+, +DELETE+, +HEAD+. Defaults to +GET+. Can be a symbol.
|
422
|
+
# - +params+: The hash with HTTP parameters that you want to pass. This may be +nil+.
|
423
|
+
# - +body+: The request body with a string that is appropriately encoded
|
424
|
+
# (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
|
579
425
|
# - +session+: A hash of parameters to store in the session. This may be +nil+.
|
580
426
|
# - +flash+: A hash of parameters to store in the flash. This may be +nil+.
|
427
|
+
# - +format+: Request format. Defaults to +nil+. Can be string or symbol.
|
581
428
|
#
|
582
429
|
# Example calling +create+ action and sending two params:
|
583
430
|
#
|
584
|
-
# process :create,
|
585
|
-
#
|
586
|
-
#
|
587
|
-
#
|
588
|
-
#
|
431
|
+
# process :create,
|
432
|
+
# method: 'POST',
|
433
|
+
# params: {
|
434
|
+
# user: { name: 'Gaurish Sharma', email: 'user@example.com' }
|
435
|
+
# },
|
436
|
+
# session: { user_id: 1 },
|
437
|
+
# flash: { notice: 'This is flash message' }
|
589
438
|
#
|
590
439
|
# To simulate +GET+, +POST+, +PATCH+, +PUT+, +DELETE+ and +HEAD+ requests
|
591
440
|
# prefer using #get, #post, #patch, #put, #delete and #head methods
|
592
441
|
# respectively which will make tests more expressive.
|
593
442
|
#
|
594
443
|
# Note that the request method is not verified.
|
595
|
-
def process(action,
|
444
|
+
def process(action, *args)
|
596
445
|
check_required_ivars
|
597
446
|
|
598
|
-
if
|
599
|
-
|
447
|
+
if kwarg_request?(args)
|
448
|
+
parameters, session, body, flash, http_method, format, xhr = args[0].values_at(:params, :session, :body, :flash, :method, :format, :xhr)
|
449
|
+
else
|
450
|
+
http_method, parameters, session, flash = args
|
451
|
+
format = nil
|
452
|
+
|
453
|
+
if parameters.is_a?(String) && http_method != 'HEAD'
|
454
|
+
body = parameters
|
455
|
+
parameters = nil
|
456
|
+
end
|
457
|
+
|
458
|
+
if parameters.present? || session.present? || flash.present?
|
459
|
+
non_kwarg_request_warning
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
if body.present?
|
464
|
+
@request.set_header 'RAW_POST_DATA', body
|
465
|
+
end
|
466
|
+
|
467
|
+
if http_method.present?
|
468
|
+
http_method = http_method.to_s.upcase
|
469
|
+
else
|
470
|
+
http_method = "GET"
|
600
471
|
end
|
601
472
|
|
602
|
-
parameters, session, flash = args
|
603
473
|
parameters ||= {}
|
604
474
|
|
605
|
-
|
606
|
-
|
607
|
-
|
475
|
+
if format.present?
|
476
|
+
parameters[:format] = format
|
477
|
+
end
|
608
478
|
|
609
479
|
@html_document = nil
|
610
|
-
@html_scanner_document = nil
|
611
480
|
|
612
481
|
unless @controller.respond_to?(:recycle!)
|
613
482
|
@controller.extend(Testing::Functional)
|
614
483
|
end
|
615
484
|
|
616
|
-
@request.
|
617
|
-
|
485
|
+
self.cookies.update @request.cookies
|
486
|
+
self.cookies.update_cookies_from_jar
|
487
|
+
@request.set_header 'HTTP_COOKIE', cookies.to_header
|
488
|
+
@request.delete_header 'action_dispatch.cookies'
|
489
|
+
|
490
|
+
@request = TestRequest.new scrub_env!(@request.env), @request.session
|
491
|
+
@response = build_response @response_klass
|
492
|
+
@response.request = @request
|
618
493
|
@controller.recycle!
|
619
494
|
|
620
|
-
@request.
|
495
|
+
@request.set_header 'REQUEST_METHOD', http_method
|
496
|
+
|
497
|
+
parameters = parameters.symbolize_keys
|
621
498
|
|
622
|
-
|
623
|
-
|
624
|
-
|
499
|
+
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action.to_s))
|
500
|
+
generated_path = generated_path(generated_extras)
|
501
|
+
query_string_keys = query_parameter_names(generated_extras)
|
625
502
|
|
626
|
-
@request.assign_parameters(@routes, controller_class_name, action.to_s, parameters)
|
503
|
+
@request.assign_parameters(@routes, controller_class_name, action.to_s, parameters, generated_path, query_string_keys)
|
627
504
|
|
628
505
|
@request.session.update(session) if session
|
629
506
|
@request.flash.update(flash || {})
|
630
507
|
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
508
|
+
if xhr
|
509
|
+
@request.set_header 'HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'
|
510
|
+
@request.fetch_header('HTTP_ACCEPT') do |k|
|
511
|
+
@request.set_header k, [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ')
|
512
|
+
end
|
513
|
+
end
|
635
514
|
|
636
|
-
|
515
|
+
@request.fetch_header("SCRIPT_NAME") do |k|
|
516
|
+
@request.set_header k, @controller.config.relative_url_root
|
517
|
+
end
|
637
518
|
|
638
519
|
@controller.recycle!
|
639
|
-
@controller.
|
520
|
+
@controller.dispatch(action, @request, @response)
|
521
|
+
@request = @controller.request
|
522
|
+
@response = @controller.response
|
523
|
+
|
524
|
+
@request.delete_header 'HTTP_COOKIE'
|
640
525
|
|
641
|
-
if
|
642
|
-
unless @
|
643
|
-
|
526
|
+
if @request.have_cookie_jar?
|
527
|
+
unless @request.cookie_jar.committed?
|
528
|
+
@request.cookie_jar.write(@response)
|
529
|
+
self.cookies.update(@request.cookie_jar.instance_variable_get(:@cookies))
|
644
530
|
end
|
645
531
|
end
|
646
532
|
@response.prepare!
|
647
533
|
|
648
|
-
@assigns = @controller.respond_to?(:view_assigns) ? @controller.view_assigns : {}
|
649
|
-
|
650
534
|
if flash_value = @request.flash.to_session_value
|
651
535
|
@request.session['flash'] = flash_value
|
536
|
+
else
|
537
|
+
@request.session.delete('flash')
|
652
538
|
end
|
653
539
|
|
540
|
+
if xhr
|
541
|
+
@request.delete_header 'HTTP_X_REQUESTED_WITH'
|
542
|
+
@request.delete_header 'HTTP_ACCEPT'
|
543
|
+
end
|
544
|
+
@request.query_string = ''
|
545
|
+
|
654
546
|
@response
|
655
547
|
end
|
656
548
|
|
549
|
+
def controller_class_name
|
550
|
+
@controller.class.anonymous? ? "anonymous" : @controller.class.controller_path
|
551
|
+
end
|
552
|
+
|
553
|
+
def generated_path(generated_extras)
|
554
|
+
generated_extras[0]
|
555
|
+
end
|
556
|
+
|
557
|
+
def query_parameter_names(generated_extras)
|
558
|
+
generated_extras[1] + [:controller, :action]
|
559
|
+
end
|
560
|
+
|
657
561
|
def setup_controller_request_and_response
|
658
562
|
@controller = nil unless defined? @controller
|
659
563
|
|
660
|
-
response_klass = TestResponse
|
564
|
+
@response_klass = ActionDispatch::TestResponse
|
661
565
|
|
662
566
|
if klass = self.class.controller_class
|
663
567
|
if klass < ActionController::Live
|
664
|
-
response_klass = LiveTestResponse
|
568
|
+
@response_klass = LiveTestResponse
|
665
569
|
end
|
666
570
|
unless @controller
|
667
571
|
begin
|
@@ -672,8 +576,8 @@ module ActionController
|
|
672
576
|
end
|
673
577
|
end
|
674
578
|
|
675
|
-
@request =
|
676
|
-
@response = build_response response_klass
|
579
|
+
@request = TestRequest.create
|
580
|
+
@response = build_response @response_klass
|
677
581
|
@response.request = @request
|
678
582
|
|
679
583
|
if @controller
|
@@ -682,12 +586,8 @@ module ActionController
|
|
682
586
|
end
|
683
587
|
end
|
684
588
|
|
685
|
-
def build_request
|
686
|
-
TestRequest.new
|
687
|
-
end
|
688
|
-
|
689
589
|
def build_response(klass)
|
690
|
-
klass.
|
590
|
+
klass.create
|
691
591
|
end
|
692
592
|
|
693
593
|
included do
|
@@ -699,6 +599,46 @@ module ActionController
|
|
699
599
|
|
700
600
|
private
|
701
601
|
|
602
|
+
def scrub_env!(env)
|
603
|
+
env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
|
604
|
+
env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
|
605
|
+
env.delete 'action_dispatch.request.query_parameters'
|
606
|
+
env.delete 'action_dispatch.request.request_parameters'
|
607
|
+
env
|
608
|
+
end
|
609
|
+
|
610
|
+
def process_with_kwargs(http_method, action, *args)
|
611
|
+
if kwarg_request?(args)
|
612
|
+
args.first.merge!(method: http_method)
|
613
|
+
process(action, *args)
|
614
|
+
else
|
615
|
+
non_kwarg_request_warning if args.any?
|
616
|
+
|
617
|
+
args = args.unshift(http_method)
|
618
|
+
process(action, *args)
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
REQUEST_KWARGS = %i(params session flash method body xhr)
|
623
|
+
def kwarg_request?(args)
|
624
|
+
args[0].respond_to?(:keys) && (
|
625
|
+
(args[0].key?(:format) && args[0].keys.size == 1) ||
|
626
|
+
args[0].keys.any? { |k| REQUEST_KWARGS.include?(k) }
|
627
|
+
)
|
628
|
+
end
|
629
|
+
|
630
|
+
def non_kwarg_request_warning
|
631
|
+
ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
|
632
|
+
ActionController::TestCase HTTP request methods will accept only
|
633
|
+
keyword arguments in future Rails versions.
|
634
|
+
|
635
|
+
Examples:
|
636
|
+
|
637
|
+
get :show, params: { id: 1 }, session: { user_id: 1 }
|
638
|
+
process :update, method: :post, params: { id: 1 }
|
639
|
+
MSG
|
640
|
+
end
|
641
|
+
|
702
642
|
def document_root_element
|
703
643
|
html_document.root
|
704
644
|
end
|
@@ -713,43 +653,6 @@ module ActionController
|
|
713
653
|
end
|
714
654
|
end
|
715
655
|
|
716
|
-
def build_request_uri(action, parameters)
|
717
|
-
unless @request.env["PATH_INFO"]
|
718
|
-
options = @controller.respond_to?(:url_options) ? @controller.__send__(:url_options).merge(parameters) : parameters
|
719
|
-
options.update(
|
720
|
-
:action => action,
|
721
|
-
:relative_url_root => nil,
|
722
|
-
:_recall => @request.path_parameters)
|
723
|
-
|
724
|
-
if route_name = options.delete(:use_route)
|
725
|
-
ActiveSupport::Deprecation.warn <<-MSG.squish
|
726
|
-
Passing the `use_route` option in functional tests are deprecated.
|
727
|
-
Support for this option in the `process` method (and the related
|
728
|
-
`get`, `head`, `post`, `patch`, `put` and `delete` helpers) will
|
729
|
-
be removed in the next version without replacement.
|
730
|
-
|
731
|
-
Functional tests are essentially unit tests for controllers and
|
732
|
-
they should not require knowledge to how the application's routes
|
733
|
-
are configured. Instead, you should explicitly pass the appropiate
|
734
|
-
params to the `process` method.
|
735
|
-
|
736
|
-
Previously the engines guide also contained an incorrect example
|
737
|
-
that recommended using this option to test an engine's controllers
|
738
|
-
within the dummy application. That recommendation was incorrect
|
739
|
-
and has since been corrected. Instead, you should override the
|
740
|
-
`@routes` variable in the test case with `Foo::Engine.routes`. See
|
741
|
-
the updated engines guide for details.
|
742
|
-
MSG
|
743
|
-
end
|
744
|
-
|
745
|
-
url, query_string = @routes.path_for(options, route_name).split("?", 2)
|
746
|
-
|
747
|
-
@request.env["SCRIPT_NAME"] = @controller.config.relative_url_root
|
748
|
-
@request.env["PATH_INFO"] = url
|
749
|
-
@request.env["QUERY_STRING"] = query_string || ""
|
750
|
-
end
|
751
|
-
end
|
752
|
-
|
753
656
|
def html_format?(parameters)
|
754
657
|
return true unless parameters.key?(:format)
|
755
658
|
Mime.fetch(parameters[:format]) { Mime['html'] }.html?
|
@@ -758,4 +661,5 @@ module ActionController
|
|
758
661
|
|
759
662
|
include Behavior
|
760
663
|
end
|
664
|
+
# :startdoc:
|
761
665
|
end
|