actionpack 5.0.0.1 → 5.0.1.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.

Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +195 -0
  3. data/README.rdoc +1 -1
  4. data/lib/abstract_controller/callbacks.rb +3 -1
  5. data/lib/action_controller/metal/data_streaming.rb +1 -0
  6. data/lib/action_controller/metal/etag_with_template_digest.rb +7 -1
  7. data/lib/action_controller/metal/force_ssl.rb +1 -1
  8. data/lib/action_controller/metal/implicit_render.rb +1 -1
  9. data/lib/action_controller/metal/live.rb +6 -1
  10. data/lib/action_controller/metal/renderers.rb +0 -2
  11. data/lib/action_controller/metal/rendering.rb +1 -1
  12. data/lib/action_controller/metal/request_forgery_protection.rb +3 -3
  13. data/lib/action_controller/metal/strong_parameters.rb +53 -15
  14. data/lib/action_controller/test_case.rb +39 -21
  15. data/lib/action_dispatch.rb +1 -0
  16. data/lib/action_dispatch/http/headers.rb +1 -1
  17. data/lib/action_dispatch/http/mime_negotiation.rb +2 -2
  18. data/lib/action_dispatch/http/parameters.rb +8 -1
  19. data/lib/action_dispatch/http/request.rb +0 -12
  20. data/lib/action_dispatch/http/response.rb +15 -8
  21. data/lib/action_dispatch/journey/formatter.rb +3 -1
  22. data/lib/action_dispatch/journey/parser.rb +2 -0
  23. data/lib/action_dispatch/journey/parser_extras.rb +4 -2
  24. data/lib/action_dispatch/journey/route.rb +5 -3
  25. data/lib/action_dispatch/journey/router.rb +3 -1
  26. data/lib/action_dispatch/journey/visitors.rb +3 -1
  27. data/lib/action_dispatch/middleware/cookies.rb +3 -3
  28. data/lib/action_dispatch/middleware/debug_exceptions.rb +5 -1
  29. data/lib/action_dispatch/middleware/debug_locks.rb +122 -0
  30. data/lib/action_dispatch/middleware/exception_wrapper.rb +2 -2
  31. data/lib/action_dispatch/middleware/ssl.rb +14 -5
  32. data/lib/action_dispatch/middleware/static.rb +3 -3
  33. data/lib/action_dispatch/routing/mapper.rb +74 -61
  34. data/lib/action_dispatch/routing/redirection.rb +0 -1
  35. data/lib/action_dispatch/testing/integration.rb +150 -196
  36. data/lib/action_dispatch/testing/request_encoder.rb +53 -0
  37. data/lib/action_dispatch/testing/test_process.rb +2 -1
  38. data/lib/action_dispatch/testing/test_request.rb +1 -1
  39. data/lib/action_dispatch/testing/test_response.rb +7 -2
  40. data/lib/action_pack/gem_version.rb +2 -2
  41. metadata +13 -12
@@ -46,7 +46,7 @@ module ActionDispatch
46
46
  end
47
47
 
48
48
  def call(env)
49
- serve ActionDispatch::Request.new env
49
+ serve(Rack::Request.new(env))
50
50
  end
51
51
 
52
52
  def serve(request)
@@ -82,7 +82,7 @@ module ActionDispatch
82
82
  end
83
83
 
84
84
  def gzip_encoding_accepted?(request)
85
- request.accept_encoding =~ /\bgzip\b/i
85
+ request.accept_encoding.any? { |enc, quality| enc =~ /\bgzip\b/i }
86
86
  end
87
87
 
88
88
  def gzip_file_path(path)
@@ -123,7 +123,7 @@ module ActionDispatch
123
123
  end
124
124
 
125
125
  def call(env)
126
- req = ActionDispatch::Request.new env
126
+ req = Rack::Request.new env
127
127
 
128
128
  if req.get? || req.head?
129
129
  path = req.path_info.chomp('/'.freeze)
@@ -716,11 +716,7 @@ module ActionDispatch
716
716
  def map_method(method, args, &block)
717
717
  options = args.extract_options!
718
718
  options[:via] = method
719
- if options.key?(:defaults)
720
- defaults(options.delete(:defaults)) { match(*args, options, &block) }
721
- else
722
- match(*args, options, &block)
723
- end
719
+ match(*args, options, &block)
724
720
  self
725
721
  end
726
722
  end
@@ -1258,11 +1254,11 @@ module ActionDispatch
1258
1254
  # the plural):
1259
1255
  #
1260
1256
  # GET /profile/new
1261
- # POST /profile
1262
1257
  # GET /profile
1263
1258
  # GET /profile/edit
1264
1259
  # PATCH/PUT /profile
1265
1260
  # DELETE /profile
1261
+ # POST /profile
1266
1262
  #
1267
1263
  # === Options
1268
1264
  # Takes same options as +resources+.
@@ -1280,15 +1276,15 @@ module ActionDispatch
1280
1276
 
1281
1277
  concerns(options[:concerns]) if options[:concerns]
1282
1278
 
1283
- collection do
1284
- post :create
1285
- end if parent_resource.actions.include?(:create)
1286
-
1287
1279
  new do
1288
1280
  get :new
1289
1281
  end if parent_resource.actions.include?(:new)
1290
1282
 
1291
1283
  set_member_mappings_for_resource
1284
+
1285
+ collection do
1286
+ post :create
1287
+ end if parent_resource.actions.include?(:create)
1292
1288
  end
1293
1289
  end
1294
1290
 
@@ -1566,11 +1562,17 @@ module ActionDispatch
1566
1562
  # match 'path' => 'controller#action', via: patch
1567
1563
  # match 'path', to: 'controller#action', via: :post
1568
1564
  # match 'path', 'otherpath', on: :member, via: :get
1569
- def match(path, *rest)
1565
+ def match(path, *rest, &block)
1570
1566
  if rest.empty? && Hash === path
1571
1567
  options = path
1572
1568
  path, to = options.find { |name, _value| name.is_a?(String) }
1573
1569
 
1570
+ if path.nil?
1571
+ ActiveSupport::Deprecation.warn 'Omitting the route path is deprecated. '\
1572
+ 'Specify the path with a String or a Symbol instead.'
1573
+ path = ''
1574
+ end
1575
+
1574
1576
  case to
1575
1577
  when Symbol
1576
1578
  options[:action] = to
@@ -1591,55 +1593,11 @@ module ActionDispatch
1591
1593
  paths = [path] + rest
1592
1594
  end
1593
1595
 
1594
- if options[:on] && !VALID_ON_OPTIONS.include?(options[:on])
1595
- raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
1596
- end
1597
-
1598
- if @scope[:to]
1599
- options[:to] ||= @scope[:to]
1600
- end
1601
-
1602
- if @scope[:controller] && @scope[:action]
1603
- options[:to] ||= "#{@scope[:controller]}##{@scope[:action]}"
1604
- end
1605
-
1606
- controller = options.delete(:controller) || @scope[:controller]
1607
- option_path = options.delete :path
1608
- to = options.delete :to
1609
- via = Mapping.check_via Array(options.delete(:via) {
1610
- @scope[:via]
1611
- })
1612
- formatted = options.delete(:format) { @scope[:format] }
1613
- anchor = options.delete(:anchor) { true }
1614
- options_constraints = options.delete(:constraints) || {}
1615
-
1616
- path_types = paths.group_by(&:class)
1617
- path_types.fetch(String, []).each do |_path|
1618
- route_options = options.dup
1619
- if _path && option_path
1620
- ActiveSupport::Deprecation.warn <<-eowarn
1621
- Specifying strings for both :path and the route path is deprecated. Change things like this:
1622
-
1623
- match #{_path.inspect}, :path => #{option_path.inspect}
1624
-
1625
- to this:
1626
-
1627
- match #{option_path.inspect}, :as => #{_path.inspect}, :action => #{path.inspect}
1628
- eowarn
1629
- route_options[:action] = _path
1630
- route_options[:as] = _path
1631
- _path = option_path
1632
- end
1633
- to = get_to_from_path(_path, to, route_options[:action])
1634
- decomposed_match(_path, controller, route_options, _path, to, via, formatted, anchor, options_constraints)
1635
- end
1636
-
1637
- path_types.fetch(Symbol, []).each do |action|
1638
- route_options = options.dup
1639
- decomposed_match(action, controller, route_options, option_path, to, via, formatted, anchor, options_constraints)
1596
+ if options.key?(:defaults)
1597
+ defaults(options.delete(:defaults)) { map_match(paths, options, &block) }
1598
+ else
1599
+ map_match(paths, options, &block)
1640
1600
  end
1641
-
1642
- self
1643
1601
  end
1644
1602
 
1645
1603
  def get_to_from_path(path, to, action)
@@ -1915,6 +1873,7 @@ to this:
1915
1873
  def api_only?
1916
1874
  @set.api_only?
1917
1875
  end
1876
+
1918
1877
  private
1919
1878
 
1920
1879
  def path_scope(path)
@@ -1924,9 +1883,63 @@ to this:
1924
1883
  @scope = @scope.parent
1925
1884
  end
1926
1885
 
1886
+ def map_match(paths, options)
1887
+ if options[:on] && !VALID_ON_OPTIONS.include?(options[:on])
1888
+ raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
1889
+ end
1890
+
1891
+ if @scope[:to]
1892
+ options[:to] ||= @scope[:to]
1893
+ end
1894
+
1895
+ if @scope[:controller] && @scope[:action]
1896
+ options[:to] ||= "#{@scope[:controller]}##{@scope[:action]}"
1897
+ end
1898
+
1899
+ controller = options.delete(:controller) || @scope[:controller]
1900
+ option_path = options.delete :path
1901
+ to = options.delete :to
1902
+ via = Mapping.check_via Array(options.delete(:via) {
1903
+ @scope[:via]
1904
+ })
1905
+ formatted = options.delete(:format) { @scope[:format] }
1906
+ anchor = options.delete(:anchor) { true }
1907
+ options_constraints = options.delete(:constraints) || {}
1908
+
1909
+ path_types = paths.group_by(&:class)
1910
+ path_types.fetch(String, []).each do |_path|
1911
+ route_options = options.dup
1912
+ if _path && option_path
1913
+ ActiveSupport::Deprecation.warn <<-eowarn
1914
+ Specifying strings for both :path and the route path is deprecated. Change things like this:
1915
+
1916
+ match #{_path.inspect}, :path => #{option_path.inspect}
1917
+
1918
+ to this:
1919
+
1920
+ match #{option_path.inspect}, :as => #{_path.inspect}, :action => #{_path.inspect}
1921
+ eowarn
1922
+ route_options[:action] = _path
1923
+ route_options[:as] = _path
1924
+ _path = option_path
1925
+ end
1926
+ to = get_to_from_path(_path, to, route_options[:action])
1927
+ decomposed_match(_path, controller, route_options, _path, to, via, formatted, anchor, options_constraints)
1928
+ end
1929
+
1930
+ path_types.fetch(Symbol, []).each do |action|
1931
+ route_options = options.dup
1932
+ decomposed_match(action, controller, route_options, option_path, to, via, formatted, anchor, options_constraints)
1933
+ end
1934
+
1935
+ self
1936
+ end
1937
+
1927
1938
  def match_root_route(options)
1928
- name = has_named_route?(:root) ? nil : :root
1929
- match '/', { :as => name, :via => :get }.merge!(options)
1939
+ name = has_named_route?(name_for_action(:root, nil)) ? nil : :root
1940
+ args = ["/", { as: name, via: :get }.merge!(options)]
1941
+
1942
+ match(*args)
1930
1943
  end
1931
1944
  end
1932
1945
 
@@ -22,7 +22,6 @@ module ActionDispatch
22
22
  end
23
23
 
24
24
  def serve(req)
25
- req.check_path_parameters!
26
25
  uri = URI.parse(path(req.path_parameters, req))
27
26
 
28
27
  unless uri.host
@@ -6,65 +6,40 @@ require 'active_support/core_ext/string/strip'
6
6
  require 'rack/test'
7
7
  require 'minitest'
8
8
 
9
+ require 'action_dispatch/testing/request_encoder'
10
+
9
11
  module ActionDispatch
10
12
  module Integration #:nodoc:
11
13
  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.
16
- # - +params+: The HTTP parameters that you want to pass. This may
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>).
21
- # - +headers+: Additional headers to pass, as a Hash. The headers will be
22
- # merged into the Rack env hash.
23
- # - +env+: Additional env to pass, as a Hash. The headers will be
24
- # merged into the Rack env hash.
25
- #
26
- # This method returns a Response object, which one can use to
27
- # inspect the details of the response. Furthermore, if this method was
28
- # called from an ActionDispatch::IntegrationTest object, then that
29
- # object's <tt>@response</tt> instance variable will point to the same
30
- # response object.
31
- #
32
- # You can also perform POST, PATCH, PUT, DELETE, and HEAD requests with
33
- # +#post+, +#patch+, +#put+, +#delete+, and +#head+.
34
- #
35
- # Example:
36
- #
37
- # get '/feed', params: { since: 201501011400 }
38
- # post '/profile', headers: { "X-Test-Header" => "testvalue" }
39
14
  def get(path, *args)
40
15
  process_with_kwargs(:get, path, *args)
41
16
  end
42
17
 
43
- # Performs a POST request with the given parameters. See +#get+ for more
18
+ # Performs a POST request with the given parameters. See +#process+ for more
44
19
  # details.
45
20
  def post(path, *args)
46
21
  process_with_kwargs(:post, path, *args)
47
22
  end
48
23
 
49
- # Performs a PATCH request with the given parameters. See +#get+ for more
24
+ # Performs a PATCH request with the given parameters. See +#process+ for more
50
25
  # details.
51
26
  def patch(path, *args)
52
27
  process_with_kwargs(:patch, path, *args)
53
28
  end
54
29
 
55
- # Performs a PUT request with the given parameters. See +#get+ for more
30
+ # Performs a PUT request with the given parameters. See +#process+ for more
56
31
  # details.
57
32
  def put(path, *args)
58
33
  process_with_kwargs(:put, path, *args)
59
34
  end
60
35
 
61
- # Performs a DELETE request with the given parameters. See +#get+ for
36
+ # Performs a DELETE request with the given parameters. See +#process+ for
62
37
  # more details.
63
38
  def delete(path, *args)
64
39
  process_with_kwargs(:delete, path, *args)
65
40
  end
66
41
 
67
- # Performs a HEAD request with the given parameters. See +#get+ for more
42
+ # Performs a HEAD request with the given parameters. See +#process+ for more
68
43
  # details.
69
44
  def head(path, *args)
70
45
  process_with_kwargs(:head, path, *args)
@@ -79,26 +54,14 @@ module ActionDispatch
79
54
  #
80
55
  # Example:
81
56
  #
82
- # xhr :get, '/feed', params: { since: 201501011400 }
83
- def xml_http_request(request_method, path, *args)
84
- if kwarg_request?(args)
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
-
57
+ # xhr :get, '/feed', since: 201501011400
58
+ def xml_http_request(request_method, path, parameters = nil, headers_or_env = nil)
96
59
  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`.
60
+ `xhr` and `xml_http_request` are deprecated and will be removed in Rails 5.1.
61
+ Switch to e.g. `post comments_path, params: { comment: { body: 'Honey bunny' } }, xhr: true`.
99
62
  MSG
100
63
 
101
- process(request_method, path, params: params, headers: headers, xhr: true)
64
+ process(request_method, path, params: parameters, headers: headers_or_env, xhr: true)
102
65
  end
103
66
  alias xhr :xml_http_request
104
67
 
@@ -177,7 +140,7 @@ module ActionDispatch
177
140
  DEFAULT_HOST = "www.example.com"
178
141
 
179
142
  include Minitest::Assertions
180
- include TestProcess, RequestHelpers, Assertions
143
+ include RequestHelpers, Assertions
181
144
 
182
145
  %w( status status_message headers body redirect? ).each do |method|
183
146
  delegate method, :to => :response, :allow_nil => true
@@ -281,6 +244,108 @@ module ActionDispatch
281
244
  @https
282
245
  end
283
246
 
247
+ # Performs the actual request.
248
+ #
249
+ # - +method+: The HTTP method (GET, POST, PATCH, PUT, DELETE, HEAD, OPTIONS)
250
+ # as a symbol.
251
+ # - +path+: The URI (as a String) on which you want to perform the
252
+ # request.
253
+ # - +params+: The HTTP parameters that you want to pass. This may
254
+ # be +nil+,
255
+ # a Hash, or a String that is appropriately encoded
256
+ # (<tt>application/x-www-form-urlencoded</tt> or
257
+ # <tt>multipart/form-data</tt>).
258
+ # - +headers+: Additional headers to pass, as a Hash. The headers will be
259
+ # merged into the Rack env hash.
260
+ # - +env+: Additional env to pass, as a Hash. The headers will be
261
+ # merged into the Rack env hash.
262
+ #
263
+ # This method is rarely used directly. Use +#get+, +#post+, or other standard
264
+ # HTTP methods in integration tests. +#process+ is only required when using a
265
+ # request method that doesn't have a method defined in the integrations tests.
266
+ #
267
+ # This method returns a Response object, which one can use to
268
+ # inspect the details of the response. Furthermore, if this method was
269
+ # called from an ActionDispatch::IntegrationTest object, then that
270
+ # object's <tt>@response</tt> instance variable will point to the same
271
+ # response object.
272
+ #
273
+ # Example:
274
+ #
275
+ # process :get, '/author', params: { since: 201501011400 }
276
+ def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
277
+ request_encoder = RequestEncoder.encoder(as)
278
+ headers ||= {}
279
+
280
+ if method == :get && as == :json && params
281
+ headers['X-Http-Method-Override'] = 'GET'
282
+ method = :post
283
+ end
284
+
285
+ if path =~ %r{://}
286
+ location = URI.parse(path)
287
+ https! URI::HTTPS === location if location.scheme
288
+ if url_host = location.host
289
+ default = Rack::Request::DEFAULT_PORTS[location.scheme]
290
+ url_host += ":#{location.port}" if default != location.port
291
+ host! url_host
292
+ end
293
+ path = location.query ? "#{location.path}?#{location.query}" : location.path
294
+ end
295
+
296
+ hostname, port = host.split(':')
297
+
298
+ request_env = {
299
+ :method => method,
300
+ :params => request_encoder.encode_params(params),
301
+
302
+ "SERVER_NAME" => hostname,
303
+ "SERVER_PORT" => port || (https? ? "443" : "80"),
304
+ "HTTPS" => https? ? "on" : "off",
305
+ "rack.url_scheme" => https? ? "https" : "http",
306
+
307
+ "REQUEST_URI" => path,
308
+ "HTTP_HOST" => host,
309
+ "REMOTE_ADDR" => remote_addr,
310
+ "CONTENT_TYPE" => request_encoder.content_type,
311
+ "HTTP_ACCEPT" => request_encoder.accept_header || accept
312
+ }
313
+
314
+ wrapped_headers = Http::Headers.from_hash({})
315
+ wrapped_headers.merge!(headers) if headers
316
+
317
+ if xhr
318
+ wrapped_headers["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
319
+ wrapped_headers["HTTP_ACCEPT"] ||= [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ")
320
+ end
321
+
322
+ # this modifies the passed request_env directly
323
+ if wrapped_headers.present?
324
+ Http::Headers.from_hash(request_env).merge!(wrapped_headers)
325
+ end
326
+ if env.present?
327
+ Http::Headers.from_hash(request_env).merge!(env)
328
+ end
329
+
330
+ session = Rack::Test::Session.new(_mock_session)
331
+
332
+ # NOTE: rack-test v0.5 doesn't build a default uri correctly
333
+ # Make sure requested path is always a full uri
334
+ session.request(build_full_uri(path, request_env), request_env)
335
+
336
+ @request_count += 1
337
+ @request = ActionDispatch::Request.new(session.last_request.env)
338
+ response = _mock_session.last_response
339
+ @response = ActionDispatch::TestResponse.from_response(response)
340
+ @response.request = @request
341
+ @html_document = nil
342
+ @url_options = nil
343
+
344
+ @controller = @request.controller_instance
345
+
346
+ response.status
347
+ end
348
+
284
349
  # Set the host name to use in the next request.
285
350
  #
286
351
  # session.host! "www.example.com"
@@ -307,144 +372,20 @@ module ActionDispatch
307
372
 
308
373
  def non_kwarg_request_warning
309
374
  ActiveSupport::Deprecation.warn(<<-MSG.strip_heredoc)
310
- ActionDispatch::IntegrationTest HTTP request methods will accept only
311
- the following keyword arguments in future Rails versions:
312
- #{REQUEST_KWARGS.join(', ')}
313
-
314
- Examples:
315
-
316
- get '/profile',
317
- params: { id: 1 },
318
- headers: { 'X-Extra-Header' => '123' },
319
- env: { 'action_dispatch.custom' => 'custom' },
320
- xhr: true,
321
- as: :json
322
- MSG
323
- end
324
-
325
- # Performs the actual request.
326
- def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
327
- request_encoder = RequestEncoder.encoder(as)
328
-
329
- if path =~ %r{://}
330
- location = URI.parse(path)
331
- https! URI::HTTPS === location if location.scheme
332
- if url_host = location.host
333
- default = Rack::Request::DEFAULT_PORTS[location.scheme]
334
- url_host += ":#{location.port}" if default != location.port
335
- host! url_host
336
- end
337
- path = request_encoder.append_format_to location.path
338
- path = location.query ? "#{path}?#{location.query}" : path
339
- else
340
- path = request_encoder.append_format_to path
341
- end
342
-
343
- hostname, port = host.split(':')
344
-
345
- request_env = {
346
- :method => method,
347
- :params => request_encoder.encode_params(params),
348
-
349
- "SERVER_NAME" => hostname,
350
- "SERVER_PORT" => port || (https? ? "443" : "80"),
351
- "HTTPS" => https? ? "on" : "off",
352
- "rack.url_scheme" => https? ? "https" : "http",
353
-
354
- "REQUEST_URI" => path,
355
- "HTTP_HOST" => host,
356
- "REMOTE_ADDR" => remote_addr,
357
- "CONTENT_TYPE" => request_encoder.content_type,
358
- "HTTP_ACCEPT" => accept
359
- }
360
-
361
- if xhr
362
- headers ||= {}
363
- headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
364
- headers['HTTP_ACCEPT'] ||= [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ')
365
- end
366
-
367
- # this modifies the passed request_env directly
368
- if headers.present?
369
- Http::Headers.from_hash(request_env).merge!(headers)
370
- end
371
- if env.present?
372
- Http::Headers.from_hash(request_env).merge!(env)
373
- end
374
-
375
- session = Rack::Test::Session.new(_mock_session)
376
-
377
- # NOTE: rack-test v0.5 doesn't build a default uri correctly
378
- # Make sure requested path is always a full uri
379
- session.request(build_full_uri(path, request_env), request_env)
380
-
381
- @request_count += 1
382
- @request = ActionDispatch::Request.new(session.last_request.env)
383
- response = _mock_session.last_response
384
- @response = ActionDispatch::TestResponse.from_response(response)
385
- @response.request = @request
386
- @response.response_parser = RequestEncoder.parser(@response.content_type)
387
- @html_document = nil
388
- @url_options = nil
375
+ Using positional arguments in integration tests has been deprecated,
376
+ in favor of keyword arguments, and will be removed in Rails 5.1.
389
377
 
390
- @controller = @request.controller_instance
378
+ Deprecated style:
379
+ get "/profile", { id: 1 }, { "X-Extra-Header" => "123" }
391
380
 
392
- response.status
381
+ New keyword style:
382
+ get "/profile", params: { id: 1 }, headers: { "X-Extra-Header" => "123" }
383
+ MSG
393
384
  end
394
385
 
395
386
  def build_full_uri(path, env)
396
387
  "#{env['rack.url_scheme']}://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{path}"
397
388
  end
398
-
399
- class RequestEncoder # :nodoc:
400
- @encoders = {}
401
-
402
- attr_reader :response_parser
403
-
404
- def initialize(mime_name, param_encoder, response_parser, url_encoded_form = false)
405
- @mime = Mime[mime_name]
406
-
407
- unless @mime
408
- raise ArgumentError, "Can't register a request encoder for " \
409
- "unregistered MIME Type: #{mime_name}. See `Mime::Type.register`."
410
- end
411
-
412
- @url_encoded_form = url_encoded_form
413
- @path_format = ".#{@mime.symbol}" unless @url_encoded_form
414
- @response_parser = response_parser || -> body { body }
415
- @param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
416
- end
417
-
418
- def append_format_to(path)
419
- path << @path_format unless @url_encoded_form
420
- path
421
- end
422
-
423
- def content_type
424
- @mime.to_s
425
- end
426
-
427
- def encode_params(params)
428
- @param_encoder.call(params)
429
- end
430
-
431
- def self.parser(content_type)
432
- mime = Mime::Type.lookup(content_type)
433
- encoder(mime ? mime.ref : nil).response_parser
434
- end
435
-
436
- def self.encoder(name)
437
- @encoders[name] || WWWFormEncoder
438
- end
439
-
440
- def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil)
441
- @encoders[mime_name] = new(mime_name, param_encoder, response_parser)
442
- end
443
-
444
- register_encoder :json, response_parser: -> body { JSON.parse(body) }
445
-
446
- WWWFormEncoder = new(:url_encoded_form, -> params { params }, nil, true)
447
- end
448
389
  end
449
390
 
450
391
  module Runner
@@ -512,6 +453,7 @@ module ActionDispatch
512
453
  # simultaneously.
513
454
  def open_session
514
455
  dup.tap do |session|
456
+ session.reset!
515
457
  yield session if block_given?
516
458
  end
517
459
  end
@@ -701,42 +643,50 @@ module ActionDispatch
701
643
  # end
702
644
  # end
703
645
  #
646
+ # See the {request helpers documentation}[rdoc-ref:ActionDispatch::Integration::RequestHelpers] for help on how to
647
+ # use +get+, etc.
648
+ #
649
+ # === Changing the request encoding
650
+ #
704
651
  # You can also test your JSON API easily by setting what the request should
705
652
  # be encoded as:
706
653
  #
707
- # require 'test_helper'
654
+ # require "test_helper"
708
655
  #
709
656
  # class ApiTest < ActionDispatch::IntegrationTest
710
- # test 'creates articles' do
657
+ # test "creates articles" do
711
658
  # assert_difference -> { Article.count } do
712
- # post articles_path, params: { article: { title: 'Ahoy!' } }, as: :json
659
+ # post articles_path, params: { article: { title: "Ahoy!" } }, as: :json
713
660
  # end
714
661
  #
715
662
  # assert_response :success
716
- # assert_equal({ id: Arcticle.last.id, title: 'Ahoy!' }, response.parsed_body)
663
+ # assert_equal({ id: Arcticle.last.id, title: "Ahoy!" }, response.parsed_body)
717
664
  # end
718
665
  # end
719
666
  #
720
- # The `as` option sets the format to JSON, sets the content type to
721
- # 'application/json' and encodes the parameters as JSON.
667
+ # The +as+ option passes an "application/json" Accept header (thereby setting
668
+ # the request format to JSON unless overridden), sets the content type to
669
+ # "application/json" and encodes the parameters as JSON.
722
670
  #
723
- # Calling `parsed_body` on the response parses the response body as what
724
- # the last request was encoded as. If the request wasn't encoded `as` something,
725
- # it's the same as calling `body`.
671
+ # Calling +parsed_body+ on the response parses the response body based on the
672
+ # last response MIME type.
726
673
  #
727
- # For any custom MIME Types you've registered, you can even add your own encoders with:
674
+ # Out of the box, only <tt>:json</tt> is supported. But for any custom MIME
675
+ # types you've registered, you can add your own encoders with:
728
676
  #
729
677
  # ActionDispatch::IntegrationTest.register_encoder :wibble,
730
678
  # param_encoder: -> params { params.to_wibble },
731
679
  # response_parser: -> body { body }
732
680
  #
733
- # Where `param_encoder` defines how the params should be encoded and
734
- # `response_parser` defines how the response body should be parsed through
735
- # `parsed_body`.
681
+ # Where +param_encoder+ defines how the params should be encoded and
682
+ # +response_parser+ defines how the response body should be parsed through
683
+ # +parsed_body+.
736
684
  #
737
685
  # Consult the Rails Testing Guide for more.
738
686
 
739
687
  class IntegrationTest < ActiveSupport::TestCase
688
+ include TestProcess
689
+
740
690
  module UrlOptions
741
691
  extend ActiveSupport::Concern
742
692
  def url_options
@@ -759,7 +709,11 @@ module ActionDispatch
759
709
 
760
710
  module ClassMethods
761
711
  def app
762
- defined?(@@app) ? @@app : ActionDispatch.test_app
712
+ if defined?(@@app) && @@app
713
+ @@app
714
+ else
715
+ ActionDispatch.test_app
716
+ end
763
717
  end
764
718
 
765
719
  def app=(app)
@@ -767,7 +721,7 @@ module ActionDispatch
767
721
  end
768
722
 
769
723
  def register_encoder(*args)
770
- Integration::Session::RequestEncoder.register_encoder(*args)
724
+ RequestEncoder.register_encoder(*args)
771
725
  end
772
726
  end
773
727