actionpack 4.2.10 → 7.2.0.rc1
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 +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- 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/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +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
@@ -1,152 +1,101 @@
|
|
1
|
-
|
2
|
-
require 'uri'
|
3
|
-
require 'active_support/core_ext/kernel/singleton_class'
|
4
|
-
require 'active_support/core_ext/object/try'
|
5
|
-
require 'rack/test'
|
6
|
-
require 'minitest'
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
8
|
-
|
9
|
-
module Integration #:nodoc:
|
10
|
-
module RequestHelpers
|
11
|
-
# Performs a GET request with the given parameters.
|
12
|
-
#
|
13
|
-
# - +path+: The URI (as a String) on which you want to perform a GET
|
14
|
-
# request.
|
15
|
-
# - +parameters+: The HTTP parameters that you want to pass. This may
|
16
|
-
# be +nil+,
|
17
|
-
# a Hash, or a String that is appropriately encoded
|
18
|
-
# (<tt>application/x-www-form-urlencoded</tt> or
|
19
|
-
# <tt>multipart/form-data</tt>).
|
20
|
-
# - +headers_or_env+: Additional headers to pass, as a Hash. The headers will be
|
21
|
-
# merged into the Rack env hash.
|
22
|
-
#
|
23
|
-
# This method returns a Response object, which one can use to
|
24
|
-
# inspect the details of the response. Furthermore, if this method was
|
25
|
-
# called from an ActionDispatch::IntegrationTest object, then that
|
26
|
-
# object's <tt>@response</tt> instance variable will point to the same
|
27
|
-
# response object.
|
28
|
-
#
|
29
|
-
# You can also perform POST, PATCH, PUT, DELETE, and HEAD requests with
|
30
|
-
# +#post+, +#patch+, +#put+, +#delete+, and +#head+.
|
31
|
-
def get(path, parameters = nil, headers_or_env = nil)
|
32
|
-
process :get, path, parameters, headers_or_env
|
33
|
-
end
|
3
|
+
# :markup: markdown
|
34
4
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
5
|
+
require "stringio"
|
6
|
+
require "uri"
|
7
|
+
require "rack/test"
|
8
|
+
require "active_support/test_case"
|
40
9
|
|
41
|
-
|
42
|
-
|
43
|
-
def patch(path, parameters = nil, headers_or_env = nil)
|
44
|
-
process :patch, path, parameters, headers_or_env
|
45
|
-
end
|
10
|
+
require "action_dispatch/testing/request_encoder"
|
11
|
+
require "action_dispatch/testing/test_helpers/page_dump_helper"
|
46
12
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
13
|
+
module ActionDispatch
|
14
|
+
module Integration # :nodoc:
|
15
|
+
module RequestHelpers
|
16
|
+
# Performs a GET request with the given parameters. See
|
17
|
+
# ActionDispatch::Integration::Session#process for more details.
|
18
|
+
def get(path, **args)
|
19
|
+
process(:get, path, **args)
|
51
20
|
end
|
52
21
|
|
53
|
-
# Performs a
|
54
|
-
# more details.
|
55
|
-
def
|
56
|
-
process
|
22
|
+
# Performs a POST request with the given parameters. See
|
23
|
+
# ActionDispatch::Integration::Session#process for more details.
|
24
|
+
def post(path, **args)
|
25
|
+
process(:post, path, **args)
|
57
26
|
end
|
58
27
|
|
59
|
-
# Performs a
|
60
|
-
# details.
|
61
|
-
def
|
62
|
-
process
|
28
|
+
# Performs a PATCH request with the given parameters. See
|
29
|
+
# ActionDispatch::Integration::Session#process for more details.
|
30
|
+
def patch(path, **args)
|
31
|
+
process(:patch, path, **args)
|
63
32
|
end
|
64
33
|
|
65
|
-
# Performs
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
# +:head+; the parameters are +nil+, a hash, or a url-encoded or multipart
|
70
|
-
# string; the headers are a hash.
|
71
|
-
def xml_http_request(request_method, path, parameters = nil, headers_or_env = nil)
|
72
|
-
headers_or_env ||= {}
|
73
|
-
headers_or_env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
74
|
-
headers_or_env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
|
75
|
-
process(request_method, path, parameters, headers_or_env)
|
76
|
-
end
|
77
|
-
alias xhr :xml_http_request
|
78
|
-
|
79
|
-
# Follow a single redirect response. If the last response was not a
|
80
|
-
# redirect, an exception will be raised. Otherwise, the redirect is
|
81
|
-
# performed on the location header.
|
82
|
-
def follow_redirect!
|
83
|
-
raise "not a redirect! #{status} #{status_message}" unless redirect?
|
84
|
-
get(response.location)
|
85
|
-
status
|
34
|
+
# Performs a PUT request with the given parameters. See
|
35
|
+
# ActionDispatch::Integration::Session#process for more details.
|
36
|
+
def put(path, **args)
|
37
|
+
process(:put, path, **args)
|
86
38
|
end
|
87
39
|
|
88
|
-
# Performs a request
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
def request_via_redirect(http_method, path, parameters = nil, headers_or_env = nil)
|
93
|
-
process(http_method, path, parameters, headers_or_env)
|
94
|
-
follow_redirect! while redirect?
|
95
|
-
status
|
40
|
+
# Performs a DELETE request with the given parameters. See
|
41
|
+
# ActionDispatch::Integration::Session#process for more details.
|
42
|
+
def delete(path, **args)
|
43
|
+
process(:delete, path, **args)
|
96
44
|
end
|
97
45
|
|
98
|
-
# Performs a
|
99
|
-
#
|
100
|
-
def
|
101
|
-
|
46
|
+
# Performs a HEAD request with the given parameters. See
|
47
|
+
# ActionDispatch::Integration::Session#process for more details.
|
48
|
+
def head(path, **args)
|
49
|
+
process(:head, path, **args)
|
102
50
|
end
|
103
51
|
|
104
|
-
# Performs
|
105
|
-
#
|
106
|
-
def
|
107
|
-
|
52
|
+
# Performs an OPTIONS request with the given parameters. See
|
53
|
+
# ActionDispatch::Integration::Session#process for more details.
|
54
|
+
def options(path, **args)
|
55
|
+
process(:options, path, **args)
|
108
56
|
end
|
109
57
|
|
110
|
-
#
|
111
|
-
#
|
112
|
-
|
113
|
-
|
114
|
-
|
58
|
+
# Follow a single redirect response. If the last response was not a redirect, an
|
59
|
+
# exception will be raised. Otherwise, the redirect is performed on the location
|
60
|
+
# header. If the redirection is a 307 or 308 redirect, the same HTTP verb will
|
61
|
+
# be used when redirecting, otherwise a GET request will be performed. Any
|
62
|
+
# arguments are passed to the underlying request.
|
63
|
+
#
|
64
|
+
# The HTTP_REFERER header will be set to the previous url.
|
65
|
+
def follow_redirect!(headers: {}, **args)
|
66
|
+
raise "not a redirect! #{status} #{status_message}" unless redirect?
|
115
67
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
68
|
+
method =
|
69
|
+
if [307, 308].include?(response.status)
|
70
|
+
request.method.downcase
|
71
|
+
else
|
72
|
+
:get
|
73
|
+
end
|
121
74
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
75
|
+
if [ :HTTP_REFERER, "HTTP_REFERER" ].none? { |key| headers.key? key }
|
76
|
+
headers["HTTP_REFERER"] = request.url
|
77
|
+
end
|
78
|
+
|
79
|
+
public_send(method, response.location, headers: headers, **args)
|
80
|
+
status
|
126
81
|
end
|
127
82
|
end
|
128
83
|
|
129
|
-
# An instance of this class represents a set of requests and responses
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
84
|
+
# An instance of this class represents a set of requests and responses performed
|
85
|
+
# sequentially by a test process. Because you can instantiate multiple sessions
|
86
|
+
# and run them side-by-side, you can also mimic (to some limited extent)
|
87
|
+
# multiple simultaneous users interacting with your system.
|
133
88
|
#
|
134
|
-
# Typically, you will instantiate a new session using
|
135
|
-
#
|
136
|
-
# Integration::Session directly.
|
89
|
+
# Typically, you will instantiate a new session using Runner#open_session,
|
90
|
+
# rather than instantiating a Session directly.
|
137
91
|
class Session
|
138
92
|
DEFAULT_HOST = "www.example.com"
|
139
93
|
|
140
94
|
include Minitest::Assertions
|
141
95
|
include TestProcess, RequestHelpers, Assertions
|
142
96
|
|
143
|
-
|
144
|
-
|
145
|
-
end
|
146
|
-
|
147
|
-
%w( path ).each do |method|
|
148
|
-
delegate method, :to => :request, :allow_nil => true
|
149
|
-
end
|
97
|
+
delegate :status, :status_message, :headers, :body, :redirect?, to: :response, allow_nil: true
|
98
|
+
delegate :path, to: :request, allow_nil: true
|
150
99
|
|
151
100
|
# The hostname used in the last request.
|
152
101
|
def host
|
@@ -160,8 +109,8 @@ module ActionDispatch
|
|
160
109
|
# The Accept header to send.
|
161
110
|
attr_accessor :accept
|
162
111
|
|
163
|
-
# A map of the cookies returned by the last response, and which will be
|
164
|
-
#
|
112
|
+
# A map of the cookies returned by the last response, and which will be sent
|
113
|
+
# with the next request.
|
165
114
|
def cookies
|
166
115
|
_mock_session.cookie_jar
|
167
116
|
end
|
@@ -185,35 +134,25 @@ module ActionDispatch
|
|
185
134
|
super()
|
186
135
|
@app = app
|
187
136
|
|
188
|
-
# If the app is a Rails app, make url_helpers available on the session
|
189
|
-
# This makes app.url_for and app.foo_path available in the console
|
190
|
-
if app.respond_to?(:routes)
|
191
|
-
singleton_class.class_eval do
|
192
|
-
include app.routes.url_helpers
|
193
|
-
include app.routes.mounted_helpers
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
137
|
reset!
|
198
138
|
end
|
199
139
|
|
200
140
|
def url_options
|
201
141
|
@url_options ||= default_url_options.dup.tap do |url_options|
|
202
|
-
url_options.reverse_merge!(controller.url_options) if controller
|
142
|
+
url_options.reverse_merge!(controller.url_options) if controller.respond_to?(:url_options)
|
203
143
|
|
204
144
|
if @app.respond_to?(:routes)
|
205
145
|
url_options.reverse_merge!(@app.routes.default_url_options)
|
206
146
|
end
|
207
147
|
|
208
|
-
url_options.reverse_merge!(:
|
148
|
+
url_options.reverse_merge!(host: host, protocol: https? ? "https" : "http")
|
209
149
|
end
|
210
150
|
end
|
211
151
|
|
212
|
-
# Resets the instance. This can be used to reset the state information
|
213
|
-
#
|
214
|
-
# condition.
|
152
|
+
# Resets the instance. This can be used to reset the state information in an
|
153
|
+
# existing session instance, so it can be used from a clean-slate condition.
|
215
154
|
#
|
216
|
-
#
|
155
|
+
# session.reset!
|
217
156
|
def reset!
|
218
157
|
@https = false
|
219
158
|
@controller = @request = @response = nil
|
@@ -223,292 +162,533 @@ module ActionDispatch
|
|
223
162
|
|
224
163
|
self.host = DEFAULT_HOST
|
225
164
|
self.remote_addr = "127.0.0.1"
|
226
|
-
self.accept = "text/xml,application/xml,application/xhtml+xml,"
|
227
|
-
"text/html;q=0.9,text/plain;q=0.8,image/png,"
|
165
|
+
self.accept = "text/xml,application/xml,application/xhtml+xml," \
|
166
|
+
"text/html;q=0.9,text/plain;q=0.8,image/png," \
|
228
167
|
"*/*;q=0.5"
|
229
168
|
|
230
169
|
unless defined? @named_routes_configured
|
231
|
-
# the helpers are made protected by default--we make them public for
|
232
|
-
#
|
170
|
+
# the helpers are made protected by default--we make them public for easier
|
171
|
+
# access during testing and troubleshooting.
|
233
172
|
@named_routes_configured = true
|
234
173
|
end
|
235
174
|
end
|
236
175
|
|
237
176
|
# Specify whether or not the session should mimic a secure HTTPS request.
|
238
177
|
#
|
239
|
-
#
|
240
|
-
#
|
178
|
+
# session.https!
|
179
|
+
# session.https!(false)
|
241
180
|
def https!(flag = true)
|
242
181
|
@https = flag
|
243
182
|
end
|
244
183
|
|
245
|
-
# Returns
|
184
|
+
# Returns `true` if the session is mimicking a secure HTTPS request.
|
246
185
|
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
186
|
+
# if session.https?
|
187
|
+
# ...
|
188
|
+
# end
|
250
189
|
def https?
|
251
190
|
@https
|
252
191
|
end
|
253
192
|
|
254
|
-
#
|
193
|
+
# Performs the actual request.
|
255
194
|
#
|
256
|
-
#
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
195
|
+
# * `method`: The HTTP method (GET, POST, PATCH, PUT, DELETE, HEAD, OPTIONS)
|
196
|
+
# as a symbol.
|
197
|
+
# * `path`: The URI (as a String) on which you want to perform the request.
|
198
|
+
# * `params`: The HTTP parameters that you want to pass. This may be `nil`, a
|
199
|
+
# Hash, or a String that is appropriately encoded
|
200
|
+
# (`application/x-www-form-urlencoded` or `multipart/form-data`).
|
201
|
+
# * `headers`: Additional headers to pass, as a Hash. The headers will be
|
202
|
+
# merged into the Rack env hash.
|
203
|
+
# * `env`: Additional env to pass, as a Hash. The headers will be merged into
|
204
|
+
# the Rack env hash.
|
205
|
+
# * `xhr`: Set to `true` if you want to make an Ajax request. Adds request
|
206
|
+
# headers characteristic of XMLHttpRequest e.g. HTTP_X_REQUESTED_WITH. The
|
207
|
+
# headers will be merged into the Rack env hash.
|
208
|
+
# * `as`: Used for encoding the request with different content type. Supports
|
209
|
+
# `:json` by default and will set the appropriate request headers. The
|
210
|
+
# headers will be merged into the Rack env hash.
|
211
|
+
#
|
212
|
+
#
|
213
|
+
# This method is rarely used directly. Use RequestHelpers#get,
|
214
|
+
# RequestHelpers#post, or other standard HTTP methods in integration tests.
|
215
|
+
# `#process` is only required when using a request method that doesn't have a
|
216
|
+
# method defined in the integration tests.
|
217
|
+
#
|
218
|
+
# This method returns the response status, after performing the request.
|
219
|
+
# Furthermore, if this method was called from an ActionDispatch::IntegrationTest
|
220
|
+
# object, then that object's `@response` instance variable will point to a
|
221
|
+
# Response object which one can use to inspect the details of the response.
|
222
|
+
#
|
223
|
+
# Example:
|
224
|
+
# process :get, '/author', params: { since: 201501011400 }
|
225
|
+
def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
|
226
|
+
request_encoder = RequestEncoder.encoder(as)
|
227
|
+
headers ||= {}
|
228
|
+
|
229
|
+
if method == :get && as == :json && params
|
230
|
+
headers["X-Http-Method-Override"] = "GET"
|
231
|
+
method = :post
|
262
232
|
end
|
263
233
|
|
264
|
-
|
265
|
-
|
266
|
-
if path =~ %r{://}
|
267
|
-
location = URI.parse(path)
|
234
|
+
if path.include?("://")
|
235
|
+
path = build_expanded_path(path) do |location|
|
268
236
|
https! URI::HTTPS === location if location.scheme
|
269
|
-
|
270
|
-
|
237
|
+
|
238
|
+
if url_host = location.host
|
239
|
+
default = Rack::Request::DEFAULT_PORTS[location.scheme]
|
240
|
+
url_host += ":#{location.port}" if default != location.port
|
241
|
+
host! url_host
|
242
|
+
end
|
271
243
|
end
|
244
|
+
end
|
245
|
+
|
246
|
+
hostname, port = host.split(":")
|
247
|
+
|
248
|
+
request_env = {
|
249
|
+
:method => method,
|
250
|
+
:params => request_encoder.encode_params(params),
|
251
|
+
|
252
|
+
"SERVER_NAME" => hostname,
|
253
|
+
"SERVER_PORT" => port || (https? ? "443" : "80"),
|
254
|
+
"HTTPS" => https? ? "on" : "off",
|
255
|
+
"rack.url_scheme" => https? ? "https" : "http",
|
256
|
+
|
257
|
+
"REQUEST_URI" => path,
|
258
|
+
"HTTP_HOST" => host,
|
259
|
+
"REMOTE_ADDR" => remote_addr,
|
260
|
+
"HTTP_ACCEPT" => request_encoder.accept_header || accept
|
261
|
+
}
|
272
262
|
|
273
|
-
|
263
|
+
if request_encoder.content_type
|
264
|
+
request_env["CONTENT_TYPE"] = request_encoder.content_type
|
265
|
+
end
|
274
266
|
|
275
|
-
|
276
|
-
|
277
|
-
:params => parameters,
|
267
|
+
wrapped_headers = Http::Headers.from_hash({})
|
268
|
+
wrapped_headers.merge!(headers) if headers
|
278
269
|
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
270
|
+
if xhr
|
271
|
+
wrapped_headers["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
|
272
|
+
wrapped_headers["HTTP_ACCEPT"] ||= [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ")
|
273
|
+
end
|
283
274
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
Http::Headers.new(env).merge!(headers_or_env || {})
|
275
|
+
# This modifies the passed request_env directly.
|
276
|
+
if wrapped_headers.present?
|
277
|
+
Http::Headers.from_hash(request_env).merge!(wrapped_headers)
|
278
|
+
end
|
279
|
+
if env.present?
|
280
|
+
Http::Headers.from_hash(request_env).merge!(env)
|
281
|
+
end
|
292
282
|
|
293
|
-
|
283
|
+
session = Rack::Test::Session.new(_mock_session)
|
294
284
|
|
295
|
-
|
296
|
-
|
297
|
-
|
285
|
+
# NOTE: rack-test v0.5 doesn't build a default uri correctly Make sure requested
|
286
|
+
# path is always a full URI.
|
287
|
+
session.request(build_full_uri(path, request_env), request_env)
|
298
288
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
289
|
+
@request_count += 1
|
290
|
+
@request = ActionDispatch::Request.new(session.last_request.env)
|
291
|
+
response = _mock_session.last_response
|
292
|
+
@response = ActionDispatch::TestResponse.from_response(response)
|
293
|
+
@response.request = @request
|
294
|
+
@html_document = nil
|
295
|
+
@url_options = nil
|
306
296
|
|
307
|
-
|
297
|
+
@controller = @request.controller_instance
|
298
|
+
|
299
|
+
response.status
|
300
|
+
end
|
301
|
+
|
302
|
+
# Set the host name to use in the next request.
|
303
|
+
#
|
304
|
+
# session.host! "www.example.com"
|
305
|
+
alias :host! :host=
|
308
306
|
|
309
|
-
|
307
|
+
private
|
308
|
+
def _mock_session
|
309
|
+
@_mock_session ||= Rack::MockSession.new(@app, host)
|
310
310
|
end
|
311
311
|
|
312
312
|
def build_full_uri(path, env)
|
313
313
|
"#{env['rack.url_scheme']}://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{path}"
|
314
314
|
end
|
315
|
+
|
316
|
+
def build_expanded_path(path)
|
317
|
+
location = URI.parse(path)
|
318
|
+
yield location if block_given?
|
319
|
+
path = location.path
|
320
|
+
location.query ? "#{path}?#{location.query}" : path
|
321
|
+
end
|
315
322
|
end
|
316
323
|
|
317
324
|
module Runner
|
318
325
|
include ActionDispatch::Assertions
|
319
326
|
|
320
|
-
|
321
|
-
|
327
|
+
APP_SESSIONS = {}
|
328
|
+
|
329
|
+
attr_reader :app
|
330
|
+
attr_accessor :root_session # :nodoc:
|
331
|
+
|
332
|
+
def initialize(*args, &blk)
|
333
|
+
super(*args, &blk)
|
334
|
+
@integration_session = nil
|
322
335
|
end
|
323
336
|
|
324
|
-
|
325
|
-
|
337
|
+
def before_setup # :nodoc:
|
338
|
+
@app = nil
|
339
|
+
super
|
340
|
+
end
|
341
|
+
|
342
|
+
def integration_session
|
343
|
+
@integration_session ||= create_session(app)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Reset the current session. This is useful for testing multiple sessions in a
|
347
|
+
# single test case.
|
326
348
|
def reset!
|
327
|
-
@integration_session =
|
349
|
+
@integration_session = create_session(app)
|
350
|
+
end
|
351
|
+
|
352
|
+
def create_session(app)
|
353
|
+
klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
|
354
|
+
# If the app is a Rails app, make url_helpers available on the session. This
|
355
|
+
# makes app.url_for and app.foo_path available in the console.
|
356
|
+
if app.respond_to?(:routes) && app.routes.is_a?(ActionDispatch::Routing::RouteSet)
|
357
|
+
include app.routes.url_helpers
|
358
|
+
include app.routes.mounted_helpers
|
359
|
+
end
|
360
|
+
}
|
361
|
+
klass.new(app)
|
328
362
|
end
|
329
363
|
|
330
364
|
def remove! # :nodoc:
|
331
365
|
@integration_session = nil
|
332
366
|
end
|
333
367
|
|
334
|
-
%w(get post patch put head delete cookies assigns
|
335
|
-
|
336
|
-
|
337
|
-
|
368
|
+
%w(get post patch put head delete cookies assigns follow_redirect!).each do |method|
|
369
|
+
# reset the html_document variable, except for cookies/assigns calls
|
370
|
+
unless method == "cookies" || method == "assigns"
|
371
|
+
reset_html_document = "@html_document = nil"
|
372
|
+
end
|
338
373
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
@html_scanner_document = nil
|
343
|
-
reset_template_assertion
|
344
|
-
end
|
374
|
+
module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
375
|
+
def #{method}(...)
|
376
|
+
#{reset_html_document}
|
345
377
|
|
346
|
-
|
378
|
+
result = integration_session.#{method}(...)
|
347
379
|
copy_session_variables!
|
380
|
+
result
|
348
381
|
end
|
349
|
-
|
382
|
+
RUBY
|
350
383
|
end
|
351
384
|
|
352
|
-
# Open a new session instance. If a block is given, the new session is
|
353
|
-
#
|
385
|
+
# Open a new session instance. If a block is given, the new session is yielded
|
386
|
+
# to the block before being returned.
|
354
387
|
#
|
355
|
-
#
|
356
|
-
#
|
357
|
-
#
|
388
|
+
# session = open_session do |sess|
|
389
|
+
# sess.extend(CustomAssertions)
|
390
|
+
# end
|
358
391
|
#
|
359
|
-
# By default, a single session is automatically created for you, but you
|
360
|
-
#
|
361
|
-
# simultaneously.
|
392
|
+
# By default, a single session is automatically created for you, but you can use
|
393
|
+
# this method to open multiple sessions that ought to be tested simultaneously.
|
362
394
|
def open_session
|
363
395
|
dup.tap do |session|
|
364
396
|
session.reset!
|
397
|
+
session.root_session = self.root_session || self
|
365
398
|
yield session if block_given?
|
366
399
|
end
|
367
400
|
end
|
368
401
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
402
|
+
def assertions # :nodoc:
|
403
|
+
root_session ? root_session.assertions : super
|
404
|
+
end
|
405
|
+
|
406
|
+
def assertions=(assertions) # :nodoc:
|
407
|
+
root_session ? root_session.assertions = assertions : super
|
408
|
+
end
|
409
|
+
|
410
|
+
# Copy the instance variables from the current session instance into the test
|
411
|
+
# instance.
|
412
|
+
def copy_session_variables! # :nodoc:
|
413
|
+
@controller = @integration_session.controller
|
414
|
+
@response = @integration_session.response
|
415
|
+
@request = @integration_session.request
|
376
416
|
end
|
377
417
|
|
378
418
|
def default_url_options
|
379
|
-
reset! unless integration_session
|
380
419
|
integration_session.default_url_options
|
381
420
|
end
|
382
421
|
|
383
422
|
def default_url_options=(options)
|
384
|
-
reset! unless integration_session
|
385
423
|
integration_session.default_url_options = options
|
386
424
|
end
|
387
425
|
|
388
|
-
|
389
|
-
|
426
|
+
private
|
427
|
+
def respond_to_missing?(method, _)
|
428
|
+
integration_session.respond_to?(method) || super
|
390
429
|
end
|
391
430
|
|
392
431
|
# Delegate unhandled messages to the current session instance.
|
393
|
-
def method_missing(
|
394
|
-
|
395
|
-
|
396
|
-
integration_session.__send__(sym, *args, &block).tap do
|
432
|
+
def method_missing(method, ...)
|
433
|
+
if integration_session.respond_to?(method)
|
434
|
+
integration_session.public_send(method, ...).tap do
|
397
435
|
copy_session_variables!
|
398
436
|
end
|
399
437
|
else
|
400
438
|
super
|
401
439
|
end
|
402
440
|
end
|
403
|
-
|
404
|
-
private
|
405
|
-
def integration_session
|
406
|
-
@integration_session ||= nil
|
407
|
-
end
|
408
441
|
end
|
409
442
|
end
|
410
443
|
|
411
|
-
# An integration test spans multiple controllers and actions,
|
412
|
-
#
|
413
|
-
#
|
414
|
-
#
|
444
|
+
# An integration test spans multiple controllers and actions, tying them all
|
445
|
+
# together to ensure they work together as expected. It tests more completely
|
446
|
+
# than either unit or functional tests do, exercising the entire stack, from the
|
447
|
+
# dispatcher to the database.
|
415
448
|
#
|
416
|
-
# At its simplest, you simply extend
|
417
|
-
# using the get/
|
449
|
+
# At its simplest, you simply extend `IntegrationTest` and write your tests
|
450
|
+
# using the Integration::RequestHelpers#get and/or
|
451
|
+
# Integration::RequestHelpers#post methods:
|
418
452
|
#
|
419
|
-
#
|
453
|
+
# require "test_helper"
|
420
454
|
#
|
421
|
-
#
|
422
|
-
#
|
455
|
+
# class ExampleTest < ActionDispatch::IntegrationTest
|
456
|
+
# fixtures :people
|
423
457
|
#
|
424
|
-
#
|
425
|
-
#
|
426
|
-
#
|
427
|
-
#
|
458
|
+
# def test_login
|
459
|
+
# # get the login page
|
460
|
+
# get "/login"
|
461
|
+
# assert_equal 200, status
|
428
462
|
#
|
429
|
-
#
|
430
|
-
#
|
431
|
-
#
|
432
|
-
#
|
433
|
-
#
|
434
|
-
#
|
463
|
+
# # post the login and follow through to the home page
|
464
|
+
# post "/login", params: { username: people(:jamis).username,
|
465
|
+
# password: people(:jamis).password }
|
466
|
+
# follow_redirect!
|
467
|
+
# assert_equal 200, status
|
468
|
+
# assert_equal "/home", path
|
469
|
+
# end
|
435
470
|
# end
|
436
|
-
# end
|
437
471
|
#
|
438
|
-
# However, you can also have multiple session instances open per test, and
|
439
|
-
#
|
440
|
-
#
|
441
|
-
#
|
472
|
+
# However, you can also have multiple session instances open per test, and even
|
473
|
+
# extend those instances with assertions and methods to create a very powerful
|
474
|
+
# testing DSL that is specific for your application. You can even reference any
|
475
|
+
# named routes you happen to have defined.
|
442
476
|
#
|
443
|
-
#
|
477
|
+
# require "test_helper"
|
444
478
|
#
|
445
|
-
#
|
446
|
-
#
|
479
|
+
# class AdvancedTest < ActionDispatch::IntegrationTest
|
480
|
+
# fixtures :people, :rooms
|
447
481
|
#
|
448
|
-
#
|
449
|
-
#
|
450
|
-
#
|
482
|
+
# def test_login_and_speak
|
483
|
+
# jamis, david = login(:jamis), login(:david)
|
484
|
+
# room = rooms(:office)
|
451
485
|
#
|
452
|
-
#
|
453
|
-
#
|
486
|
+
# jamis.enter(room)
|
487
|
+
# jamis.speak(room, "anybody home?")
|
454
488
|
#
|
455
|
-
#
|
456
|
-
#
|
457
|
-
#
|
489
|
+
# david.enter(room)
|
490
|
+
# david.speak(room, "hello!")
|
491
|
+
# end
|
458
492
|
#
|
459
|
-
#
|
493
|
+
# private
|
460
494
|
#
|
461
|
-
#
|
462
|
-
#
|
463
|
-
#
|
464
|
-
#
|
465
|
-
#
|
466
|
-
#
|
495
|
+
# module CustomAssertions
|
496
|
+
# def enter(room)
|
497
|
+
# # reference a named route, for maximum internal consistency!
|
498
|
+
# get(room_url(id: room.id))
|
499
|
+
# assert(...)
|
500
|
+
# ...
|
501
|
+
# end
|
502
|
+
#
|
503
|
+
# def speak(room, message)
|
504
|
+
# post "/say/#{room.id}", xhr: true, params: { message: message }
|
505
|
+
# assert(...)
|
506
|
+
# ...
|
507
|
+
# end
|
467
508
|
# end
|
468
509
|
#
|
469
|
-
# def
|
470
|
-
#
|
471
|
-
#
|
472
|
-
#
|
510
|
+
# def login(who)
|
511
|
+
# open_session do |sess|
|
512
|
+
# sess.extend(CustomAssertions)
|
513
|
+
# who = people(who)
|
514
|
+
# sess.post "/login", params: { username: who.username,
|
515
|
+
# password: who.password }
|
516
|
+
# assert(...)
|
517
|
+
# end
|
473
518
|
# end
|
519
|
+
# end
|
520
|
+
#
|
521
|
+
# Another longer example would be:
|
522
|
+
#
|
523
|
+
# A simple integration test that exercises multiple controllers:
|
524
|
+
#
|
525
|
+
# require "test_helper"
|
526
|
+
#
|
527
|
+
# class UserFlowsTest < ActionDispatch::IntegrationTest
|
528
|
+
# test "login and browse site" do
|
529
|
+
# # login via https
|
530
|
+
# https!
|
531
|
+
# get "/login"
|
532
|
+
# assert_response :success
|
533
|
+
#
|
534
|
+
# post "/login", params: { username: users(:david).username, password: users(:david).password }
|
535
|
+
# follow_redirect!
|
536
|
+
# assert_equal '/welcome', path
|
537
|
+
# assert_equal 'Welcome david!', flash[:notice]
|
538
|
+
#
|
539
|
+
# https!(false)
|
540
|
+
# get "/articles/all"
|
541
|
+
# assert_response :success
|
542
|
+
# assert_select 'h1', 'Articles'
|
543
|
+
# end
|
544
|
+
# end
|
545
|
+
#
|
546
|
+
# As you can see the integration test involves multiple controllers and
|
547
|
+
# exercises the entire stack from database to dispatcher. In addition you can
|
548
|
+
# have multiple session instances open simultaneously in a test and extend those
|
549
|
+
# instances with assertion methods to create a very powerful testing DSL
|
550
|
+
# (domain-specific language) just for your application.
|
551
|
+
#
|
552
|
+
# Here's an example of multiple sessions and custom DSL in an integration test
|
553
|
+
#
|
554
|
+
# require "test_helper"
|
555
|
+
#
|
556
|
+
# class UserFlowsTest < ActionDispatch::IntegrationTest
|
557
|
+
# test "login and browse site" do
|
558
|
+
# # User david logs in
|
559
|
+
# david = login(:david)
|
560
|
+
# # User guest logs in
|
561
|
+
# guest = login(:guest)
|
562
|
+
#
|
563
|
+
# # Both are now available in different sessions
|
564
|
+
# assert_equal 'Welcome david!', david.flash[:notice]
|
565
|
+
# assert_equal 'Welcome guest!', guest.flash[:notice]
|
566
|
+
#
|
567
|
+
# # User david can browse site
|
568
|
+
# david.browses_site
|
569
|
+
# # User guest can browse site as well
|
570
|
+
# guest.browses_site
|
571
|
+
#
|
572
|
+
# # Continue with other assertions
|
474
573
|
# end
|
475
574
|
#
|
476
|
-
#
|
477
|
-
#
|
478
|
-
#
|
479
|
-
#
|
480
|
-
#
|
481
|
-
#
|
482
|
-
#
|
575
|
+
# private
|
576
|
+
#
|
577
|
+
# module CustomDsl
|
578
|
+
# def browses_site
|
579
|
+
# get "/products/all"
|
580
|
+
# assert_response :success
|
581
|
+
# assert_select 'h1', 'Products'
|
582
|
+
# end
|
583
|
+
# end
|
584
|
+
#
|
585
|
+
# def login(user)
|
586
|
+
# open_session do |sess|
|
587
|
+
# sess.extend(CustomDsl)
|
588
|
+
# u = users(user)
|
589
|
+
# sess.https!
|
590
|
+
# sess.post "/login", params: { username: u.username, password: u.password }
|
591
|
+
# assert_equal '/welcome', sess.path
|
592
|
+
# sess.https!(false)
|
593
|
+
# end
|
483
594
|
# end
|
595
|
+
# end
|
596
|
+
#
|
597
|
+
# See the [request helpers documentation]
|
598
|
+
# (rdoc-ref:ActionDispatch::Integration::RequestHelpers) for help
|
599
|
+
# on how to use `get`, etc.
|
600
|
+
#
|
601
|
+
# ### Changing the request encoding
|
602
|
+
#
|
603
|
+
# You can also test your JSON API easily by setting what the request should be
|
604
|
+
# encoded as:
|
605
|
+
#
|
606
|
+
# require "test_helper"
|
607
|
+
#
|
608
|
+
# class ApiTest < ActionDispatch::IntegrationTest
|
609
|
+
# test "creates articles" do
|
610
|
+
# assert_difference -> { Article.count } do
|
611
|
+
# post articles_path, params: { article: { title: "Ahoy!" } }, as: :json
|
612
|
+
# end
|
613
|
+
#
|
614
|
+
# assert_response :success
|
615
|
+
# assert_equal({ id: Article.last.id, title: "Ahoy!" }, response.parsed_body)
|
484
616
|
# end
|
485
|
-
#
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
617
|
+
# end
|
618
|
+
#
|
619
|
+
# The `as` option passes an "application/json" Accept header (thereby setting
|
620
|
+
# the request format to JSON unless overridden), sets the content type to
|
621
|
+
# "application/json" and encodes the parameters as JSON.
|
622
|
+
#
|
623
|
+
# Calling TestResponse#parsed_body on the response parses the response body
|
624
|
+
# based on the last response MIME type.
|
625
|
+
#
|
626
|
+
# Out of the box, only `:json` is supported. But for any custom MIME types
|
627
|
+
# you've registered, you can add your own encoders with:
|
628
|
+
#
|
629
|
+
# ActionDispatch::IntegrationTest.register_encoder :wibble,
|
630
|
+
# param_encoder: -> params { params.to_wibble },
|
631
|
+
# response_parser: -> body { body }
|
632
|
+
#
|
633
|
+
# Where `param_encoder` defines how the params should be encoded and
|
634
|
+
# `response_parser` defines how the response body should be parsed through
|
635
|
+
# TestResponse#parsed_body.
|
636
|
+
#
|
637
|
+
# Consult the [Rails Testing Guide](https://guides.rubyonrails.org/testing.html)
|
638
|
+
# for more.
|
490
639
|
|
491
|
-
|
640
|
+
class IntegrationTest < ActiveSupport::TestCase
|
641
|
+
include TestProcess::FixtureFile
|
492
642
|
|
493
|
-
|
494
|
-
|
643
|
+
module UrlOptions
|
644
|
+
extend ActiveSupport::Concern
|
645
|
+
def url_options
|
646
|
+
integration_session.url_options
|
647
|
+
end
|
495
648
|
end
|
496
649
|
|
497
|
-
|
498
|
-
|
499
|
-
end
|
650
|
+
module Behavior
|
651
|
+
extend ActiveSupport::Concern
|
500
652
|
|
501
|
-
|
502
|
-
|
503
|
-
|
653
|
+
include Integration::Runner
|
654
|
+
include ActionController::TemplateAssertions
|
655
|
+
include TestHelpers::PageDumpHelper
|
504
656
|
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
657
|
+
included do
|
658
|
+
include ActionDispatch::Routing::UrlFor
|
659
|
+
include UrlOptions # don't let UrlFor override the url_options method
|
660
|
+
include ActionDispatch::Assertions::RoutingAssertions::WithIntegrationRouting
|
661
|
+
ActiveSupport.run_load_hooks(:action_dispatch_integration_test, self)
|
662
|
+
@@app = nil
|
663
|
+
end
|
664
|
+
|
665
|
+
module ClassMethods
|
666
|
+
def app
|
667
|
+
if defined?(@@app) && @@app
|
668
|
+
@@app
|
669
|
+
else
|
670
|
+
ActionDispatch.test_app
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
def app=(app)
|
675
|
+
@@app = app
|
676
|
+
end
|
509
677
|
|
510
|
-
|
511
|
-
|
678
|
+
def register_encoder(*args, **options)
|
679
|
+
RequestEncoder.register_encoder(*args, **options)
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
def app
|
684
|
+
super || self.class.app
|
685
|
+
end
|
686
|
+
|
687
|
+
def document_root_element
|
688
|
+
html_document.root
|
689
|
+
end
|
512
690
|
end
|
691
|
+
|
692
|
+
include Behavior
|
513
693
|
end
|
514
694
|
end
|