Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 672 lines (586 sloc) 22.636 kb
eab7120 @jeremy Performance: integration test benchmarking and profiling. [Jeremy Ke…
jeremy authored
1 require 'stringio'
2 require 'uri'
89978f1 @fxn moves Object#singleton_class to Kernel#singleton_class to match Ruby …
fxn authored
3 require 'active_support/core_ext/kernel/singleton_class'
4f7565c @fxn adds missing requires for Object#try
fxn authored
4 require 'active_support/core_ext/object/try'
3a20e83 @sikachu Add missing require for String#strip_heredoc
sikachu authored
5 require 'active_support/core_ext/string/strip'
ee395fe @josh TestProcess belongs in AD
josh authored
6 require 'rack/test'
4efb36e @spastorino Revert "Merge pull request #15305 from tgxworld/remove_unnecessary_re…
spastorino authored
7 require 'minitest'
4a55d1d @josh Move integration test runner into ActionDispatch
josh authored
8
9 module ActionDispatch
dfd953e @dhh Fixed docs
dhh authored
10 module Integration #:nodoc:
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
11 module RequestHelpers
12 # Performs a GET request with the given parameters.
13 #
14 # - +path+: The URI (as a String) on which you want to perform a GET
15 # request.
7814f90 @rafaelfranca Use fixed fonts only in the name of the parameter
rafaelfranca authored
16 # - +params+: The HTTP parameters that you want to pass. This may
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
17 # be +nil+,
18 # a Hash, or a String that is appropriately encoded
19 # (<tt>application/x-www-form-urlencoded</tt> or
20 # <tt>multipart/form-data</tt>).
7814f90 @rafaelfranca Use fixed fonts only in the name of the parameter
rafaelfranca authored
21 # - +headers+: Additional headers to pass, as a Hash. The headers will be
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
22 # merged into the Rack env hash.
7814f90 @rafaelfranca Use fixed fonts only in the name of the parameter
rafaelfranca authored
23 # - +env+: Additional env to pass, as a Hash. The headers will be
17eedd8 @Vaysman references to the old behavior removed
Vaysman authored
24 # merged into the Rack env hash.
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
25 #
dc69220 @robin850 Fix a typo
robin850 authored
26 # This method returns a Response object, which one can use to
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
27 # inspect the details of the response. Furthermore, if this method was
4a55d1d @josh Move integration test runner into ActionDispatch
josh authored
28 # called from an ActionDispatch::IntegrationTest object, then that
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
29 # object's <tt>@response</tt> instance variable will point to the same
30 # response object.
31 #
002713c @dlee Add config.default_method_for_update to support PATCH
dlee authored
32 # You can also perform POST, PATCH, PUT, DELETE, and HEAD requests with
33 # +#post+, +#patch+, +#put+, +#delete+, and +#head+.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
34 #
35 # Example:
36 #
37 # get '/feed', params: { since: 201501011400 }
bb6fe7e @rafaelfranca Consistent usage of spaces in hashes across our codebase
rafaelfranca authored
38 # post '/profile', headers: { "X-Test-Header" => "testvalue" }
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
39 def get(path, *args)
40 process_with_kwargs(:get, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
41 end
42
07054fe @jfirebaugh Fix grammar, formatting, and cross references
jfirebaugh authored
43 # Performs a POST request with the given parameters. See +#get+ for more
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
44 # details.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
45 def post(path, *args)
46 process_with_kwargs(:post, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
47 end
48
002713c @dlee Add config.default_method_for_update to support PATCH
dlee authored
49 # Performs a PATCH request with the given parameters. See +#get+ for more
50 # details.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
51 def patch(path, *args)
52 process_with_kwargs(:patch, path, *args)
002713c @dlee Add config.default_method_for_update to support PATCH
dlee authored
53 end
54
07054fe @jfirebaugh Fix grammar, formatting, and cross references
jfirebaugh authored
55 # Performs a PUT request with the given parameters. See +#get+ for more
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
56 # details.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
57 def put(path, *args)
58 process_with_kwargs(:put, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
59 end
60
07054fe @jfirebaugh Fix grammar, formatting, and cross references
jfirebaugh authored
61 # Performs a DELETE request with the given parameters. See +#get+ for
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
62 # more details.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
63 def delete(path, *args)
64 process_with_kwargs(:delete, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
65 end
66
07054fe @jfirebaugh Fix grammar, formatting, and cross references
jfirebaugh authored
67 # Performs a HEAD request with the given parameters. See +#get+ for more
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
68 # details.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
69 def head(path, *args)
70 process_with_kwargs(:head, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
71 end
72
73 # Performs an XMLHttpRequest request with the given parameters, mirroring
74 # a request from the Prototype library.
75 #
002713c @dlee Add config.default_method_for_update to support PATCH
dlee authored
76 # The request_method is +:get+, +:post+, +:patch+, +:put+, +:delete+ or
77 # +:head+; the parameters are +nil+, a hash, or a url-encoded or multipart
17eedd8 @Vaysman references to the old behavior removed
Vaysman authored
78 # string; the headers are a hash.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
79 #
80 # Example:
81 #
82 # xhr :get, '/feed', params: { since: 201501011400 }
83 def xml_http_request(request_method, path, *args)
e260975 @eileencodes Use `args` instead of `*args` in `kwargs_request?` method
eileencodes authored
84 if kwarg_request?(args)
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
85 params, headers, env = args.first.values_at(:params, :headers, :env)
86 else
87 params = args[0]
88 headers = args[1]
89 env = {}
90
91 if params.present? || headers.present?
92 non_kwarg_request_warning
93 end
94 end
95
b19999f @kirs Migrating xhr methods to keyword arguments syntax
kirs authored
96 ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
97 xhr and xml_http_request methods are deprecated in favor of
98 `get "/posts", xhr: true` and `post "/posts/1", xhr: true`
99 MSG
100
101 process(request_method, path, params: params, headers: headers, xhr: true)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
102 end
103 alias xhr :xml_http_request
104
105 # Follow a single redirect response. If the last response was not a
106 # redirect, an exception will be raised. Otherwise, the redirect is
107 # performed on the location header.
108 def follow_redirect!
109 raise "not a redirect! #{status} #{status_message}" unless redirect?
110 get(response.location)
111 status
112 end
113
114 # Performs a request using the specified method, following any subsequent
115 # redirect. Note that the redirects are followed until the response is
116 # not a redirect--this means you may run into an infinite loop if your
117 # redirect loops back to itself.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
118 #
119 # Example:
120 #
121 # request_via_redirect :post, '/welcome',
122 # params: { ref_id: 14 },
bb6fe7e @rafaelfranca Consistent usage of spaces in hashes across our codebase
rafaelfranca authored
123 # headers: { "X-Test-Header" => "testvalue" }
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
124 def request_via_redirect(http_method, path, *args)
125 process_with_kwargs(http_method, path, *args)
126
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
127 follow_redirect! while redirect?
128 status
129 end
130
131 # Performs a GET request, following any subsequent redirect.
132 # See +request_via_redirect+ for more information.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
133 def get_via_redirect(path, *args)
751f752 @aditya-kapoor Deprecate *_via_redirect integration test methods
aditya-kapoor authored
134 ActiveSupport::Deprecation.warn('`get_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
135 request_via_redirect(:get, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
136 end
137
138 # Performs a POST request, following any subsequent redirect.
139 # See +request_via_redirect+ for more information.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
140 def post_via_redirect(path, *args)
751f752 @aditya-kapoor Deprecate *_via_redirect integration test methods
aditya-kapoor authored
141 ActiveSupport::Deprecation.warn('`post_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
142 request_via_redirect(:post, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
143 end
144
002713c @dlee Add config.default_method_for_update to support PATCH
dlee authored
145 # Performs a PATCH request, following any subsequent redirect.
146 # See +request_via_redirect+ for more information.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
147 def patch_via_redirect(path, *args)
751f752 @aditya-kapoor Deprecate *_via_redirect integration test methods
aditya-kapoor authored
148 ActiveSupport::Deprecation.warn('`patch_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
149 request_via_redirect(:patch, path, *args)
002713c @dlee Add config.default_method_for_update to support PATCH
dlee authored
150 end
151
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
152 # Performs a PUT request, following any subsequent redirect.
153 # See +request_via_redirect+ for more information.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
154 def put_via_redirect(path, *args)
751f752 @aditya-kapoor Deprecate *_via_redirect integration test methods
aditya-kapoor authored
155 ActiveSupport::Deprecation.warn('`put_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
156 request_via_redirect(:put, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
157 end
158
159 # Performs a DELETE request, following any subsequent redirect.
160 # See +request_via_redirect+ for more information.
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
161 def delete_via_redirect(path, *args)
751f752 @aditya-kapoor Deprecate *_via_redirect integration test methods
aditya-kapoor authored
162 ActiveSupport::Deprecation.warn('`delete_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
163 request_via_redirect(:delete, path, *args)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
164 end
165 end
166
591e87f @tilsammans Expanded routing documentation with current best practices
tilsammans authored
167 # An instance of this class represents a set of requests and responses
168 # performed sequentially by a test process. Because you can instantiate
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
169 # multiple sessions and run them side-by-side, you can also mimic (to some
170 # limited extent) multiple simultaneous users interacting with your system.
171 #
ebec9d4 @josh Make integration test runner more Rack friendly and clean out old CGI…
josh authored
172 # Typically, you will instantiate a new session using
173 # IntegrationTest#open_session, rather than instantiating
174 # Integration::Session directly.
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
175 class Session
0029d5e @brynary Integrating Rack::MockSession (from Rack::Test)
brynary authored
176 DEFAULT_HOST = "www.example.com"
177
7bae292 @vipulnsward Change all `MiniTest` to `Minitest` since, `MiniTest` namespace has b…
vipulnsward authored
178 include Minitest::Assertions
ee395fe @josh TestProcess belongs in AD
josh authored
179 include TestProcess, RequestHelpers, Assertions
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
180
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
181 %w( status status_message headers body redirect? ).each do |method|
182 delegate method, :to => :response, :allow_nil => true
183 end
5b5d0e3 @josh Use Rack::Head middleware to ensure the body is discarded for HEAD re…
josh authored
184
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
185 %w( path ).each do |method|
186 delegate method, :to => :request, :allow_nil => true
187 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
188
189 # The hostname used in the last request.
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
190 def host
191 @host || DEFAULT_HOST
192 end
193 attr_writer :host
fe94ba1 @dhh Added access to remote_addr in integration tests (closes #4266) [Chad…
dhh authored
194
195 # The remote_addr used in the last request.
196 attr_accessor :remote_addr
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
197
9d7de52 @jamis Add Integration::Session.accept for setting the HTTP Accept header to…
jamis authored
198 # The Accept header to send.
199 attr_accessor :accept
200
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
201 # A map of the cookies returned by the last response, and which will be
202 # sent with the next request.
0029d5e @brynary Integrating Rack::MockSession (from Rack::Test)
brynary authored
203 def cookies
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
204 _mock_session.cookie_jar
0029d5e @brynary Integrating Rack::MockSession (from Rack::Test)
brynary authored
205 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
206
207 # A reference to the controller instance used by the last request.
208 attr_reader :controller
209
210 # A reference to the request instance used by the last request.
211 attr_reader :request
212
213 # A reference to the response instance used by the last request.
214 attr_reader :response
215
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
216 # A running counter of the number of requests processed.
217 attr_accessor :request_count
218
0508318 If IntegrationSession is initialized with an objects that responds to…
Carlhuda authored
219 include ActionDispatch::Routing::UrlFor
220
98dc582 @lifo Merge docrails.
lifo authored
221 # Create and initialize a new Session instance.
acfeec5 @josh Allow integration test rack app to be set with "@app" ivar instead of…
josh authored
222 def initialize(app)
b1ae796 @josevalim Fix an error on 1.8.7.
josevalim authored
223 super()
acfeec5 @josh Allow integration test rack app to be set with "@app" ivar instead of…
josh authored
224 @app = app
0508318 If IntegrationSession is initialized with an objects that responds to…
Carlhuda authored
225
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
226 reset!
227 end
228
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
229 def url_options
230 @url_options ||= default_url_options.dup.tap do |url_options|
231 url_options.reverse_merge!(controller.url_options) if controller
232
1ae9f05 @tenderlove routed applications will respond to these methods
tenderlove authored
233 if @app.respond_to?(:routes)
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
234 url_options.reverse_merge!(@app.routes.default_url_options)
235 end
236
237 url_options.reverse_merge!(:host => host, :protocol => https? ? "https" : "http")
238 end
0508318 If IntegrationSession is initialized with an objects that responds to…
Carlhuda authored
239 end
240
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
241 # Resets the instance. This can be used to reset the state information
242 # in an existing session instance, so it can be used from a clean-slate
243 # condition.
244 #
245 # session.reset!
246 def reset!
247 @https = false
248 @controller = @request = @response = nil
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
249 @_mock_session = nil
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
250 @request_count = 0
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
251 @url_options = nil
d1c957d @jeremy Integration tests: alias xhr to xml_http_request and add a request_me…
jeremy authored
252
0029d5e @brynary Integrating Rack::MockSession (from Rack::Test)
brynary authored
253 self.host = DEFAULT_HOST
fe94ba1 @dhh Added access to remote_addr in integration tests (closes #4266) [Chad…
dhh authored
254 self.remote_addr = "127.0.0.1"
ebec9d4 @josh Make integration test runner more Rack friendly and clean out old CGI…
josh authored
255 self.accept = "text/xml,application/xml,application/xhtml+xml," +
256 "text/html;q=0.9,text/plain;q=0.8,image/png," +
257 "*/*;q=0.5"
0fbe683 @jamis more integration tweaks
jamis authored
258
0eacdcf @jeremy Use a consistent load path to avoid double requires. Fix some scatter…
jeremy authored
259 unless defined? @named_routes_configured
0fbe683 @jamis more integration tweaks
jamis authored
260 # the helpers are made protected by default--we make them public for
261 # easier access during testing and troubleshooting.
262 @named_routes_configured = true
263 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
264 end
265
266 # Specify whether or not the session should mimic a secure HTTPS request.
267 #
268 # session.https!
269 # session.https!(false)
ebec9d4 @josh Make integration test runner more Rack friendly and clean out old CGI…
josh authored
270 def https!(flag = true)
d1c957d @jeremy Integration tests: alias xhr to xml_http_request and add a request_me…
jeremy authored
271 @https = flag
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
272 end
273
b1b9a0a @laurocaetano Typos. return -> returns. [ci skip]
laurocaetano authored
274 # Returns +true+ if the session is mimicking a secure HTTPS request.
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
275 #
276 # if session.https?
277 # ...
278 # end
279 def https?
280 @https
281 end
282
283 # Set the host name to use in the next request.
284 #
9326222 @dhh Use example.com as standard (closes #4413) [anna]
dhh authored
285 # session.host! "www.example.com"
831a234 @tenderlove just use alias
tenderlove authored
286 alias :host! :host=
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
287
288 private
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
289 def _mock_session
290 @_mock_session ||= Rack::MockSession.new(@app, host)
291 end
0029d5e @brynary Integrating Rack::MockSession (from Rack::Test)
brynary authored
292
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
293 def process_with_kwargs(http_method, path, *args)
e260975 @eileencodes Use `args` instead of `*args` in `kwargs_request?` method
eileencodes authored
294 if kwarg_request?(args)
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
295 process(http_method, path, *args)
296 else
297 non_kwarg_request_warning if args.present?
298 process(http_method, path, { params: args[0], headers: args[1] })
299 end
300 end
301
b19999f @kirs Migrating xhr methods to keyword arguments syntax
kirs authored
302 REQUEST_KWARGS = %i(params headers env xhr)
e260975 @eileencodes Use `args` instead of `*args` in `kwargs_request?` method
eileencodes authored
303 def kwarg_request?(args)
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
304 args[0].respond_to?(:keys) && args[0].keys.any? { |k| REQUEST_KWARGS.include?(k) }
305 end
306
307 def non_kwarg_request_warning
308 ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
899e10f @tgxworld Correct module name in deprecation message.
tgxworld authored
309 ActionDispatch::IntegrationTest HTTP request methods will accept only
aca4c82 @tgxworld Improve deprecation message.
tgxworld authored
310 the following keyword arguments in future Rails versions:
311 #{REQUEST_KWARGS.join(', ')}
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
312
313 Examples:
314
315 get '/profile',
316 params: { id: 1 },
317 headers: { 'X-Extra-Header' => '123' },
6213332 @arthurnn Add missing comma
arthurnn authored
318 env: { 'action_dispatch.custom' => 'custom' },
aca4c82 @tgxworld Improve deprecation message.
tgxworld authored
319 xhr: true
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
320 MSG
321 end
322
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
323 # Performs the actual request.
b19999f @kirs Migrating xhr methods to keyword arguments syntax
kirs authored
324 def process(method, path, params: nil, headers: nil, env: nil, xhr: false)
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
325 if path =~ %r{://}
326 location = URI.parse(path)
327 https! URI::HTTPS === location if location.scheme
b28fc68 @pixeltrix Ensure port is set when passed via the process method
pixeltrix authored
328 host! "#{location.host}:#{location.port}" if location.host
9bac470 @josh Group integration test helpers and delegate other helpers to request …
josh authored
329 path = location.query ? "#{location.path}?#{location.query}" : location.path
330 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
331
29f13be @spastorino port is appended twice to HTTP_HOST when host already has the port
spastorino authored
332 hostname, port = host.split(':')
de9b338 @tenderlove fixing bug with rails use of rack-test
tenderlove authored
333
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
334 request_env = {
00d1a57 @josh Start moving TestRequest and TestResponse into ActionDispatch
josh authored
335 :method => method,
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
336 :params => params,
ebec9d4 @josh Make integration test runner more Rack friendly and clean out old CGI…
josh authored
337
29f13be @spastorino port is appended twice to HTTP_HOST when host already has the port
spastorino authored
338 "SERVER_NAME" => hostname,
56de4e9 @spastorino Fix the precedence issue here
spastorino authored
339 "SERVER_PORT" => port || (https? ? "443" : "80"),
ebec9d4 @josh Make integration test runner more Rack friendly and clean out old CGI…
josh authored
340 "HTTPS" => https? ? "on" : "off",
341 "rack.url_scheme" => https? ? "https" : "http",
342
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
343 "REQUEST_URI" => path,
29f13be @spastorino port is appended twice to HTTP_HOST when host already has the port
spastorino authored
344 "HTTP_HOST" => host,
fe94ba1 @dhh Added access to remote_addr in integration tests (closes #4266) [Chad…
dhh authored
345 "REMOTE_ADDR" => remote_addr,
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
346 "CONTENT_TYPE" => "application/x-www-form-urlencoded",
997e22c @josevalim Add a test which ensures action_dispatch.show_exceptions is properly …
josevalim authored
347 "HTTP_ACCEPT" => accept
dd2ed32 @josh Start to integrate some of the features in Rack::Test.
josh authored
348 }
b19999f @kirs Migrating xhr methods to keyword arguments syntax
kirs authored
349
350 if xhr
351 headers ||= {}
352 headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
353 headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
354 end
355
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
356 # this modifies the passed request_env directly
357 if headers.present?
358 Http::Headers.new(request_env).merge!(headers)
359 end
360 if env.present?
361 Http::Headers.new(request_env).merge!(env)
362 end
5e5e343 @josh Back off rack 1.1-pre and bundle in the new testing goodies
josh authored
363
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
364 session = Rack::Test::Session.new(_mock_session)
ab8bf9e @wycats * Change the object used in routing constraints to be an instance of
wycats authored
365
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
366 # NOTE: rack-test v0.5 doesn't build a default uri correctly
367 # Make sure requested path is always a full uri
baf14ae @kirs Switch to kwargs in ActionController::TestCase and ActionDispatch::In…
kirs authored
368 session.request(build_full_uri(path, request_env), request_env)
6940c0d @josh Unify functional and integration tests cookie helpers
josh authored
369
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
370 @request_count += 1
a79790e @josh rack-test 0.4.2 has rack 1.1.pre goodies, we'll use it instead
josh authored
371 @request = ActionDispatch::Request.new(session.last_request.env)
570c54c @josh Fix cookie access in integration tests with other host names
josh authored
372 response = _mock_session.last_response
f6e293e @jeremy Fix default headers in test responses
jeremy authored
373 @response = ActionDispatch::TestResponse.from_response(response)
6940c0d @josh Unify functional and integration tests cookie helpers
josh authored
374 @html_document = nil
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
375 @url_options = nil
97a178b @jnewland Decorate responses from Rack Middleware and Rails Metal for the purpo…
jnewland authored
376
909443e @josh Expose last controller in rack env["action_controller.instance"]
josh authored
377 @controller = session.last_request.env['action_controller.instance']
378
b19999f @kirs Migrating xhr methods to keyword arguments syntax
kirs authored
379 response.status
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
380 end
4fd144d @tgxworld Form full URI as string to be parsed in Rack::Test.
tgxworld authored
381
382 def build_full_uri(path, env)
383 "#{env['rack.url_scheme']}://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{path}"
384 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
385 end
386
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
387 module Runner
0e15f07 Get modules back into integration tests
Carlhuda authored
388 include ActionDispatch::Assertions
389
0acd4a5 @eileencodes Skip url_helpers instead of caching, speed up integration tests
eileencodes authored
390 APP_SESSIONS = {}
391
d5e55e9 @eileencodes Revert "Revert integration test refactoring that caused app test regr…
eileencodes authored
392 attr_reader :app
393
394 def before_setup
395 @app = nil
396 @integration_session = nil
2e4a01b @eileencodes Call super last in before_setup
eileencodes authored
397 super
d5e55e9 @eileencodes Revert "Revert integration test refactoring that caused app test regr…
eileencodes authored
398 end
399
400 def integration_session
401 @integration_session ||= create_session(app)
303567e @tenderlove lazily create the integration session
tenderlove authored
402 end
403
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
404 # Reset the current session. This is useful for testing multiple sessions
405 # in a single test case.
406 def reset!
0acd4a5 @eileencodes Skip url_helpers instead of caching, speed up integration tests
eileencodes authored
407 @integration_session = create_session(app)
408 end
409
410 def create_session(app)
411 klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
412 # If the app is a Rails app, make url_helpers available on the session
413 # This makes app.url_for and app.foo_path available in the console
414 if app.respond_to?(:routes)
415 include app.routes.url_helpers
416 include app.routes.mounted_helpers
417 end
418 }
419 klass.new(app)
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
420 end
421
76f5a9a @tgxworld Remove session to allow `with_routing` to be called twice.
tgxworld authored
422 def remove! # :nodoc:
423 @integration_session = nil
424 end
425
c9d75e0 @rafaelfranca Revert "Integration tests support the OPTIONS http method"
rafaelfranca authored
426 %w(get post patch put head delete cookies assigns
71c4ff0 @josh Delegate xhr helper method to integration session
josh authored
427 xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
428 define_method(method) do |*args|
c3e8d15 @calvincorreli Fix for assigns(:..) resetting template assertions
calvincorreli authored
429 # reset the html_document variable, except for cookies/assigns calls
430 unless method == 'cookies' || method == 'assigns'
431 @html_document = nil
432 reset_template_assertion
433 end
434
53b91b1 @miloops Avoid uninitialized variable warning, reuse @integration_session.
miloops authored
435 integration_session.__send__(method, *args).tap do
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
436 copy_session_variables!
437 end
438 end
439 end
440
441 # Open a new session instance. If a block is given, the new session is
442 # yielded to the block before being returned.
443 #
444 # session = open_session do |sess|
445 # sess.extend(CustomAssertions)
446 # end
447 #
448 # By default, a single session is automatically created for you, but you
449 # can use this method to open multiple sessions that ought to be tested
450 # simultaneously.
70312d2 @tgxworld Remove unused parameter.
tgxworld authored
451 def open_session
15c31c7 @wycats open_session can just return the a dup of the current context.
wycats authored
452 dup.tap do |session|
453 yield session if block_given?
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
454 end
455 end
456
457 # Copy the instance variables from the current session instance into the
458 # test instance.
459 def copy_session_variables! #:nodoc:
b03b09d @tenderlove remove meta programming
tenderlove authored
460 @controller = @integration_session.controller
461 @response = @integration_session.response
462 @request = @integration_session.request
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
463 end
464
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
465 def default_url_options
466 integration_session.default_url_options
467 end
8760add Get URL helpers working again in integration tests.
Carlhuda authored
468
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
469 def default_url_options=(options)
470 integration_session.default_url_options = options
8760add Get URL helpers working again in integration tests.
Carlhuda authored
471 end
472
5c86286 @svenfuchs add respond_to? to ActionDispatch::Integration::Runner
svenfuchs authored
473 def respond_to?(method, include_private = false)
da583df @josevalim Remove bazillion warnings from AP suite.
josevalim authored
474 integration_session.respond_to?(method, include_private) || super
5c86286 @svenfuchs add respond_to? to ActionDispatch::Integration::Runner
svenfuchs authored
475 end
476
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
477 # Delegate unhandled messages to the current session instance.
478 def method_missing(sym, *args, &block)
53b91b1 @miloops Avoid uninitialized variable warning, reuse @integration_session.
miloops authored
479 if integration_session.respond_to?(sym)
480 integration_session.__send__(sym, *args, &block).tap do
3de8b44 @oggy Make IntegrationTest::Runner propagate method_missing to ancestors.
oggy authored
481 copy_session_variables!
482 end
483 else
484 super
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
485 end
486 end
487 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
488 end
489
07054fe @jfirebaugh Fix grammar, formatting, and cross references
jfirebaugh authored
490 # An integration test spans multiple controllers and actions,
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
491 # tying them all together to ensure they work together as expected. It tests
492 # more completely than either unit or functional tests do, exercising the
493 # entire stack, from the dispatcher to the database.
494 #
591e87f @tilsammans Expanded routing documentation with current best practices
tilsammans authored
495 # At its simplest, you simply extend <tt>IntegrationTest</tt> and write your tests
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
496 # using the get/post methods:
497 #
fe5f660 @dhh Dont encourage __FILE__ bullshit
dhh authored
498 # require "test_helper"
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
499 #
7fc1edd @carlosantoniodasilva Remove deprecated stuff in ActionController
carlosantoniodasilva authored
500 # class ExampleTest < ActionDispatch::IntegrationTest
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
501 # fixtures :people
502 #
503 # def test_login
504 # # get the login page
505 # get "/login"
506 # assert_equal 200, status
507 #
508 # # post the login and follow through to the home page
fbb1185 @y-yagi update integration test example as is not output deprecation warning …
y-yagi authored
509 # post "/login", params: { username: people(:jamis).username,
510 # password: people(:jamis).password }
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
511 # follow_redirect!
512 # assert_equal 200, status
513 # assert_equal "/home", path
514 # end
515 # end
516 #
517 # However, you can also have multiple session instances open per test, and
518 # even extend those instances with assertions and methods to create a very
519 # powerful testing DSL that is specific for your application. You can even
591e87f @tilsammans Expanded routing documentation with current best practices
tilsammans authored
520 # reference any named routes you happen to have defined.
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
521 #
fe5f660 @dhh Dont encourage __FILE__ bullshit
dhh authored
522 # require "test_helper"
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
523 #
7fc1edd @carlosantoniodasilva Remove deprecated stuff in ActionController
carlosantoniodasilva authored
524 # class AdvancedTest < ActionDispatch::IntegrationTest
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
525 # fixtures :people, :rooms
526 #
527 # def test_login_and_speak
528 # jamis, david = login(:jamis), login(:david)
529 # room = rooms(:office)
530 #
531 # jamis.enter(room)
532 # jamis.speak(room, "anybody home?")
533 #
534 # david.enter(room)
535 # david.speak(room, "hello!")
536 # end
537 #
538 # private
539 #
540 # module CustomAssertions
541 # def enter(room)
542 # # reference a named route, for maximum internal consistency!
d20a529 @AvnerCohen 1.9 hash syntax changes to docs
AvnerCohen authored
543 # get(room_url(id: room.id))
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
544 # assert(...)
545 # ...
546 # end
547 #
548 # def speak(room, message)
fbb1185 @y-yagi update integration test example as is not output deprecation warning …
y-yagi authored
549 # post "/say/#{room.id}", xhr: true, params: { message: message }
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
550 # assert(...)
551 # ...
552 # end
553 # end
554 #
555 # def login(who)
556 # open_session do |sess|
557 # sess.extend(CustomAssertions)
558 # who = people(who)
fbb1185 @y-yagi update integration test example as is not output deprecation warning …
y-yagi authored
559 # sess.post "/login", params: { username: who.username,
560 # password: who.password }
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
561 # assert(...)
562 # end
563 # end
564 # end
241ccae @zzak Move longer form example from integration guide to api reference, bel…
zzak authored
565 #
566 # Another longer example would be:
567 #
568 # A simple integration test that exercises multiple controllers:
569 #
570 # require 'test_helper'
571 #
572 # class UserFlowsTest < ActionDispatch::IntegrationTest
573 # test "login and browse site" do
574 # # login via https
575 # https!
576 # get "/login"
577 # assert_response :success
578 #
fbb1185 @y-yagi update integration test example as is not output deprecation warning …
y-yagi authored
579 # post "/login", params: { username: users(:david).username, password: users(:david).password }
580 # follow_redirect!
241ccae @zzak Move longer form example from integration guide to api reference, bel…
zzak authored
581 # assert_equal '/welcome', path
582 # assert_equal 'Welcome david!', flash[:notice]
583 #
584 # https!(false)
585 # get "/articles/all"
586 # assert_response :success
587 # assert assigns(:articles)
588 # end
589 # end
590 #
591 # As you can see the integration test involves multiple controllers and
592 # exercises the entire stack from database to dispatcher. In addition you can
593 # have multiple session instances open simultaneously in a test and extend
594 # those instances with assertion methods to create a very powerful testing
595 # DSL (domain-specific language) just for your application.
596 #
597 # Here's an example of multiple sessions and custom DSL in an integration test
598 #
599 # require 'test_helper'
600 #
601 # class UserFlowsTest < ActionDispatch::IntegrationTest
602 # test "login and browse site" do
603 # # User david logs in
604 # david = login(:david)
605 # # User guest logs in
606 # guest = login(:guest)
607 #
608 # # Both are now available in different sessions
609 # assert_equal 'Welcome david!', david.flash[:notice]
610 # assert_equal 'Welcome guest!', guest.flash[:notice]
611 #
612 # # User david can browse site
613 # david.browses_site
614 # # User guest can browse site as well
615 # guest.browses_site
616 #
617 # # Continue with other assertions
618 # end
619 #
620 # private
621 #
622 # module CustomDsl
623 # def browses_site
624 # get "/products/all"
625 # assert_response :success
626 # assert assigns(:products)
627 # end
628 # end
629 #
630 # def login(user)
631 # open_session do |sess|
632 # sess.extend(CustomDsl)
633 # u = users(user)
634 # sess.https!
fbb1185 @y-yagi update integration test example as is not output deprecation warning …
y-yagi authored
635 # sess.post "/login", params: { username: u.username, password: u.password }
241ccae @zzak Move longer form example from integration guide to api reference, bel…
zzak authored
636 # assert_equal '/welcome', sess.path
637 # sess.https!(false)
638 # end
639 # end
640 # end
641 #
642 # Consult the Rails Testing Guide for more.
643
eab7120 @jeremy Performance: integration test benchmarking and profiling. [Jeremy Ke…
jeremy authored
644 class IntegrationTest < ActiveSupport::TestCase
8231460 @jeremy Factor Integration::Runner behavior out of IntegrationTest. Introduce…
jeremy authored
645 include Integration::Runner
0e15f07 Get modules back into integration tests
Carlhuda authored
646 include ActionController::TemplateAssertions
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
647 include ActionDispatch::Routing::UrlFor
14866fa @josh Allow setting a default application for all integration tests
josh authored
648
649 @@app = nil
650
651 def self.app
5f3b9de @lest remove Rails application fallback from AD::IntegrationTest
lest authored
652 @@app || ActionDispatch.test_app
14866fa @josh Allow setting a default application for all integration tests
josh authored
653 end
654
655 def self.app=(app)
656 @@app = app
657 end
658
659 def app
660 super || self.class.app
661 end
e306ca3 @pixeltrix Refactor the handling of default_url_options in integration tests
pixeltrix authored
662
663 def url_options
664 integration_session.url_options
665 end
5ffc36d @kaspth Add document_root_element to ActionDispatch::IntegrationTest so asser…
kaspth authored
666
667 def document_root_element
1b9e85d @rafaelfranca Make sure assert_select can assert body tag
rafaelfranca authored
668 html_document.root
5ffc36d @kaspth Add document_root_element to ActionDispatch::IntegrationTest so asser…
kaspth authored
669 end
9507f5d @jamis Add ActionController::IntegrationTest to allow high-level testing of …
jamis authored
670 end
0ee1cb2 @jeremy Ruby 1.9 compat, consistent load paths
jeremy authored
671 end
Something went wrong with that request. Please try again.