actionpack 4.2.8 → 5.2.4.2

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 (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +285 -444
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -7
  5. data/lib/abstract_controller.rb +12 -5
  6. data/lib/abstract_controller/asset_paths.rb +2 -0
  7. data/lib/abstract_controller/base.rb +45 -49
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +78 -15
  10. data/lib/abstract_controller/callbacks.rb +47 -31
  11. data/lib/abstract_controller/collector.rb +8 -11
  12. data/lib/abstract_controller/error.rb +6 -0
  13. data/lib/abstract_controller/helpers.rb +25 -25
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +4 -2
  16. data/lib/abstract_controller/rendering.rb +42 -41
  17. data/lib/abstract_controller/translation.rb +10 -7
  18. data/lib/abstract_controller/url_for.rb +2 -0
  19. data/lib/action_controller.rb +29 -21
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/api/api_rendering.rb +16 -0
  22. data/lib/action_controller/base.rb +27 -19
  23. data/lib/action_controller/caching.rb +14 -57
  24. data/lib/action_controller/form_builder.rb +50 -0
  25. data/lib/action_controller/log_subscriber.rb +10 -15
  26. data/lib/action_controller/metal.rb +98 -83
  27. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  28. data/lib/action_controller/metal/conditional_get.rb +118 -44
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +3 -3
  31. data/lib/action_controller/metal/data_streaming.rb +27 -46
  32. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
  34. data/lib/action_controller/metal/exceptions.rb +8 -14
  35. data/lib/action_controller/metal/flash.rb +4 -3
  36. data/lib/action_controller/metal/force_ssl.rb +23 -21
  37. data/lib/action_controller/metal/head.rb +21 -19
  38. data/lib/action_controller/metal/helpers.rb +24 -14
  39. data/lib/action_controller/metal/http_authentication.rb +64 -57
  40. data/lib/action_controller/metal/implicit_render.rb +62 -8
  41. data/lib/action_controller/metal/instrumentation.rb +19 -21
  42. data/lib/action_controller/metal/live.rb +90 -106
  43. data/lib/action_controller/metal/mime_responds.rb +33 -46
  44. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  45. data/lib/action_controller/metal/params_wrapper.rb +61 -53
  46. data/lib/action_controller/metal/redirecting.rb +49 -28
  47. data/lib/action_controller/metal/renderers.rb +87 -44
  48. data/lib/action_controller/metal/rendering.rb +72 -50
  49. data/lib/action_controller/metal/request_forgery_protection.rb +203 -92
  50. data/lib/action_controller/metal/rescue.rb +9 -16
  51. data/lib/action_controller/metal/streaming.rb +12 -10
  52. data/lib/action_controller/metal/strong_parameters.rb +582 -165
  53. data/lib/action_controller/metal/testing.rb +2 -17
  54. data/lib/action_controller/metal/url_for.rb +19 -10
  55. data/lib/action_controller/railtie.rb +28 -10
  56. data/lib/action_controller/railties/helpers.rb +2 -0
  57. data/lib/action_controller/renderer.rb +117 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +280 -411
  60. data/lib/action_dispatch.rb +27 -19
  61. data/lib/action_dispatch/http/cache.rb +93 -47
  62. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  63. data/lib/action_dispatch/http/filter_parameters.rb +26 -20
  64. data/lib/action_dispatch/http/filter_redirect.rb +10 -11
  65. data/lib/action_dispatch/http/headers.rb +55 -22
  66. data/lib/action_dispatch/http/mime_negotiation.rb +60 -41
  67. data/lib/action_dispatch/http/mime_type.rb +134 -121
  68. data/lib/action_dispatch/http/mime_types.rb +20 -6
  69. data/lib/action_dispatch/http/parameter_filter.rb +25 -11
  70. data/lib/action_dispatch/http/parameters.rb +98 -39
  71. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  72. data/lib/action_dispatch/http/request.rb +200 -118
  73. data/lib/action_dispatch/http/response.rb +225 -110
  74. data/lib/action_dispatch/http/upload.rb +12 -6
  75. data/lib/action_dispatch/http/url.rb +110 -28
  76. data/lib/action_dispatch/journey.rb +7 -5
  77. data/lib/action_dispatch/journey/formatter.rb +55 -32
  78. data/lib/action_dispatch/journey/gtg/builder.rb +7 -5
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -16
  81. data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
  82. data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +3 -1
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -48
  85. data/lib/action_dispatch/journey/nodes/node.rb +18 -6
  86. data/lib/action_dispatch/journey/parser.rb +23 -22
  87. data/lib/action_dispatch/journey/parser.y +3 -2
  88. data/lib/action_dispatch/journey/parser_extras.rb +12 -4
  89. data/lib/action_dispatch/journey/path/pattern.rb +50 -44
  90. data/lib/action_dispatch/journey/route.rb +106 -28
  91. data/lib/action_dispatch/journey/router.rb +35 -23
  92. data/lib/action_dispatch/journey/router/utils.rb +20 -11
  93. data/lib/action_dispatch/journey/routes.rb +18 -16
  94. data/lib/action_dispatch/journey/scanner.rb +18 -15
  95. data/lib/action_dispatch/journey/visitors.rb +99 -52
  96. data/lib/action_dispatch/middleware/callbacks.rb +1 -2
  97. data/lib/action_dispatch/middleware/cookies.rb +304 -193
  98. data/lib/action_dispatch/middleware/debug_exceptions.rb +152 -57
  99. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  100. data/lib/action_dispatch/middleware/exception_wrapper.rb +68 -69
  101. data/lib/action_dispatch/middleware/executor.rb +21 -0
  102. data/lib/action_dispatch/middleware/flash.rb +78 -54
  103. data/lib/action_dispatch/middleware/public_exceptions.rb +27 -25
  104. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  105. data/lib/action_dispatch/middleware/remote_ip.rb +41 -31
  106. data/lib/action_dispatch/middleware/request_id.rb +17 -9
  107. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -25
  108. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  109. data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -67
  110. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  111. data/lib/action_dispatch/middleware/show_exceptions.rb +26 -22
  112. data/lib/action_dispatch/middleware/ssl.rb +114 -36
  113. data/lib/action_dispatch/middleware/stack.rb +31 -44
  114. data/lib/action_dispatch/middleware/static.rb +57 -50
  115. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
  116. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
  117. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  123. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  124. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -64
  125. data/lib/action_dispatch/railtie.rb +19 -11
  126. data/lib/action_dispatch/request/session.rb +106 -59
  127. data/lib/action_dispatch/request/utils.rb +67 -24
  128. data/lib/action_dispatch/routing.rb +17 -18
  129. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  130. data/lib/action_dispatch/routing/inspector.rb +58 -67
  131. data/lib/action_dispatch/routing/mapper.rb +734 -447
  132. data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -139
  133. data/lib/action_dispatch/routing/redirection.rb +36 -26
  134. data/lib/action_dispatch/routing/route_set.rb +321 -291
  135. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  136. data/lib/action_dispatch/routing/url_for.rb +65 -25
  137. data/lib/action_dispatch/system_test_case.rb +147 -0
  138. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  139. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  140. data/lib/action_dispatch/system_testing/server.rb +31 -0
  141. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  142. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  143. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  144. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  145. data/lib/action_dispatch/testing/assertions.rb +6 -4
  146. data/lib/action_dispatch/testing/assertions/response.rb +45 -20
  147. data/lib/action_dispatch/testing/assertions/routing.rb +30 -26
  148. data/lib/action_dispatch/testing/integration.rb +347 -209
  149. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  150. data/lib/action_dispatch/testing/test_process.rb +28 -22
  151. data/lib/action_dispatch/testing/test_request.rb +27 -34
  152. data/lib/action_dispatch/testing/test_response.rb +35 -7
  153. data/lib/action_pack.rb +4 -2
  154. data/lib/action_pack/gem_version.rb +5 -3
  155. data/lib/action_pack/version.rb +3 -1
  156. metadata +56 -39
  157. data/lib/action_controller/metal/hide_actions.rb +0 -40
  158. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  159. data/lib/action_controller/middleware.rb +0 -39
  160. data/lib/action_controller/model_naming.rb +0 -12
  161. data/lib/action_dispatch/journey/backwards.rb +0 -5
  162. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  163. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  164. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  165. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  166. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module SystemTesting
5
+ class Server # :nodoc:
6
+ class << self
7
+ attr_accessor :silence_puma
8
+ end
9
+
10
+ self.silence_puma = false
11
+
12
+ def run
13
+ setup
14
+ end
15
+
16
+ private
17
+ def setup
18
+ set_server
19
+ set_port
20
+ end
21
+
22
+ def set_server
23
+ Capybara.server = :puma, { Silent: self.class.silence_puma } if Capybara.server == Capybara.servers[:default]
24
+ end
25
+
26
+ def set_port
27
+ Capybara.always_include_port = true
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module SystemTesting
5
+ module TestHelpers
6
+ # Screenshot helper for system testing.
7
+ module ScreenshotHelper
8
+ # Takes a screenshot of the current page in the browser.
9
+ #
10
+ # +take_screenshot+ can be used at any point in your system tests to take
11
+ # a screenshot of the current state. This can be useful for debugging or
12
+ # automating visual testing.
13
+ #
14
+ # The screenshot will be displayed in your console, if supported.
15
+ #
16
+ # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT+ environment variable to
17
+ # control the output. Possible values are:
18
+ # * [+simple+ (default)] Only displays the screenshot path.
19
+ # This is the default value.
20
+ # * [+inline+] Display the screenshot in the terminal using the
21
+ # iTerm image protocol (https://iterm2.com/documentation-images.html).
22
+ # * [+artifact+] Display the screenshot in the terminal, using the terminal
23
+ # artifact format (https://buildkite.github.io/terminal/inline-images/).
24
+ def take_screenshot
25
+ save_image
26
+ puts display_image
27
+ end
28
+
29
+ # Takes a screenshot of the current page in the browser if the test
30
+ # failed.
31
+ #
32
+ # +take_failed_screenshot+ is included in <tt>application_system_test_case.rb</tt>
33
+ # that is generated with the application. To take screenshots when a test
34
+ # fails add +take_failed_screenshot+ to the teardown block before clearing
35
+ # sessions.
36
+ def take_failed_screenshot
37
+ take_screenshot if failed? && supports_screenshot?
38
+ end
39
+
40
+ private
41
+ def image_name
42
+ failed? ? "failures_#{method_name}" : method_name
43
+ end
44
+
45
+ def image_path
46
+ @image_path ||= absolute_image_path.relative_path_from(Pathname.pwd).to_s
47
+ end
48
+
49
+ def absolute_image_path
50
+ Rails.root.join("tmp/screenshots/#{image_name}.png")
51
+ end
52
+
53
+ def save_image
54
+ page.save_screenshot(absolute_image_path)
55
+ end
56
+
57
+ def output_type
58
+ # Environment variables have priority
59
+ output_type = ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] || ENV["CAPYBARA_INLINE_SCREENSHOT"]
60
+
61
+ # Default to outputting a path to the screenshot
62
+ output_type ||= "simple"
63
+
64
+ output_type
65
+ end
66
+
67
+ def display_image
68
+ message = "[Screenshot]: #{image_path}\n".dup
69
+
70
+ case output_type
71
+ when "artifact"
72
+ message << "\e]1338;url=artifact://#{absolute_image_path}\a\n"
73
+ when "inline"
74
+ name = inline_base64(File.basename(absolute_image_path))
75
+ image = inline_base64(File.read(absolute_image_path))
76
+ message << "\e]1337;File=name=#{name};height=400px;inline=1:#{image}\a\n"
77
+ end
78
+
79
+ message
80
+ end
81
+
82
+ def inline_base64(path)
83
+ Base64.encode64(path).gsub("\n", "")
84
+ end
85
+
86
+ def failed?
87
+ !passed? && !skipped?
88
+ end
89
+
90
+ def supports_screenshot?
91
+ Capybara.current_driver != :rack_test
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module SystemTesting
5
+ module TestHelpers
6
+ module SetupAndTeardown # :nodoc:
7
+ DEFAULT_HOST = "http://127.0.0.1"
8
+
9
+ def host!(host)
10
+ super
11
+ Capybara.app_host = host
12
+ end
13
+
14
+ def before_setup
15
+ host! DEFAULT_HOST
16
+ super
17
+ end
18
+
19
+ def after_teardown
20
+ begin
21
+ take_failed_screenshot
22
+ ensure
23
+ Capybara.reset_sessions!
24
+ end
25
+ ensure
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module SystemTesting
5
+ module TestHelpers
6
+ module UndefMethods # :nodoc:
7
+ extend ActiveSupport::Concern
8
+ included do
9
+ METHODS = %i(get post put patch delete).freeze
10
+
11
+ METHODS.each do |verb|
12
+ undef_method verb
13
+ end
14
+
15
+ def method_missing(method, *args, &block)
16
+ if METHODS.include?(method)
17
+ raise NoMethodError, "System tests cannot make direct requests via ##{method}; use #visit and #click_on instead. See http://www.rubydoc.info/github/teamcapybara/capybara/master#The_DSL for more information."
18
+ else
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ # This is a class that abstracts away an asserted response. It purposely
5
+ # does not inherit from Response because it doesn't need it. That means it
6
+ # does not have headers or a body.
7
+ class AssertionResponse
8
+ attr_reader :code, :name
9
+
10
+ GENERIC_RESPONSE_CODES = { # :nodoc:
11
+ success: "2XX",
12
+ missing: "404",
13
+ redirect: "3XX",
14
+ error: "5XX"
15
+ }
16
+
17
+ # Accepts a specific response status code as an Integer (404) or String
18
+ # ('404') or a response status range as a Symbol pseudo-code (:success,
19
+ # indicating any 200-299 status code).
20
+ def initialize(code_or_name)
21
+ if code_or_name.is_a?(Symbol)
22
+ @name = code_or_name
23
+ @code = code_from_name(code_or_name)
24
+ else
25
+ @name = name_from_code(code_or_name)
26
+ @code = code_or_name
27
+ end
28
+
29
+ raise ArgumentError, "Invalid response name: #{name}" if @code.nil?
30
+ raise ArgumentError, "Invalid response code: #{code}" if @name.nil?
31
+ end
32
+
33
+ def code_and_name
34
+ "#{code}: #{name}"
35
+ end
36
+
37
+ private
38
+
39
+ def code_from_name(name)
40
+ GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name]
41
+ end
42
+
43
+ def name_from_code(code)
44
+ GENERIC_RESPONSE_CODES.invert[code] || Rack::Utils::HTTP_STATUS_CODES[code]
45
+ end
46
+ end
47
+ end
@@ -1,9 +1,11 @@
1
- require 'rails-dom-testing'
1
+ # frozen_string_literal: true
2
+
3
+ require "rails-dom-testing"
2
4
 
3
5
  module ActionDispatch
4
6
  module Assertions
5
- autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response'
6
- autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing'
7
+ autoload :ResponseAssertions, "action_dispatch/testing/assertions/response"
8
+ autoload :RoutingAssertions, "action_dispatch/testing/assertions/routing"
7
9
 
8
10
  extend ActiveSupport::Concern
9
11
 
@@ -12,7 +14,7 @@ module ActionDispatch
12
14
  include Rails::Dom::Testing::Assertions
13
15
 
14
16
  def html_document
15
- @html_document ||= if @response.content_type.to_s =~ /xml$/
17
+ @html_document ||= if @response.content_type.to_s.end_with?("xml")
16
18
  Nokogiri::XML::Document.parse(@response.body)
17
19
  else
18
20
  Nokogiri::HTML::Document.parse(@response.body)
@@ -1,8 +1,16 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module ActionDispatch
3
4
  module Assertions
4
5
  # A small suite of assertions that test responses from \Rails applications.
5
6
  module ResponseAssertions
7
+ RESPONSE_PREDICATES = { # :nodoc:
8
+ success: :successful?,
9
+ missing: :not_found?,
10
+ redirect: :redirection?,
11
+ error: :server_error?,
12
+ }
13
+
6
14
  # Asserts that the response is one of the following types:
7
15
  #
8
16
  # * <tt>:success</tt> - Status code was in the 200-299 range
@@ -14,45 +22,37 @@ module ActionDispatch
14
22
  # or its symbolic equivalent <tt>assert_response(:not_implemented)</tt>.
15
23
  # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list.
16
24
  #
17
- # # assert that the response was a redirection
25
+ # # Asserts that the response was a redirection
18
26
  # assert_response :redirect
19
27
  #
20
- # # assert that the response code was status code 401 (unauthorized)
28
+ # # Asserts that the response code was status code 401 (unauthorized)
21
29
  # assert_response 401
22
30
  def assert_response(type, message = nil)
23
- message ||= "Expected response to be a <#{type}>, but was <#{@response.response_code}>"
31
+ message ||= generate_response_message(type)
24
32
 
25
- if Symbol === type
26
- if [:success, :missing, :redirect, :error].include?(type)
27
- assert @response.send("#{type}?"), message
28
- else
29
- code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type]
30
- if code.nil?
31
- raise ArgumentError, "Invalid response type :#{type}"
32
- end
33
- assert_equal code, @response.response_code, message
34
- end
33
+ if RESPONSE_PREDICATES.keys.include?(type)
34
+ assert @response.send(RESPONSE_PREDICATES[type]), message
35
35
  else
36
- assert_equal type, @response.response_code, message
36
+ assert_equal AssertionResponse.new(type).code, @response.response_code, message
37
37
  end
38
38
  end
39
39
 
40
- # Assert that the redirection options passed in match those of the redirect called in the latest action.
40
+ # Asserts that the redirection options passed in match those of the redirect called in the latest action.
41
41
  # This match can be partial, such that <tt>assert_redirected_to(controller: "weblog")</tt> will also
42
42
  # match the redirection of <tt>redirect_to(controller: "weblog", action: "show")</tt> and so on.
43
43
  #
44
- # # assert that the redirection was to the "index" action on the WeblogController
44
+ # # Asserts that the redirection was to the "index" action on the WeblogController
45
45
  # assert_redirected_to controller: "weblog", action: "index"
46
46
  #
47
- # # assert that the redirection was to the named route login_url
47
+ # # Asserts that the redirection was to the named route login_url
48
48
  # assert_redirected_to login_url
49
49
  #
50
- # # assert that the redirection was to the url for @customer
50
+ # # Asserts that the redirection was to the URL for @customer
51
51
  # assert_redirected_to @customer
52
52
  #
53
- # # asserts that the redirection matches the regular expression
53
+ # # Asserts that the redirection matches the regular expression
54
54
  # assert_redirected_to %r(\Ahttp://example.org)
55
- def assert_redirected_to(options = {}, message=nil)
55
+ def assert_redirected_to(options = {}, message = nil)
56
56
  assert_response(:redirect, message)
57
57
  return true if options === @response.location
58
58
 
@@ -77,6 +77,31 @@ module ActionDispatch
77
77
  handle._compute_redirect_to_location(@request, fragment)
78
78
  end
79
79
  end
80
+
81
+ def generate_response_message(expected, actual = @response.response_code)
82
+ "Expected response to be a <#{code_with_name(expected)}>,"\
83
+ " but was a <#{code_with_name(actual)}>"
84
+ .dup.concat(location_if_redirected).concat(response_body_if_short)
85
+ end
86
+
87
+ def response_body_if_short
88
+ return "" if @response.body.size > 500
89
+ "\nResponse body: #{@response.body}"
90
+ end
91
+
92
+ def location_if_redirected
93
+ return "" unless @response.redirection? && @response.location.present?
94
+ location = normalize_argument_to_redirection(@response.location)
95
+ " redirect to <#{location}>"
96
+ end
97
+
98
+ def code_with_name(code_or_name)
99
+ if RESPONSE_PREDICATES.values.include?("#{code_or_name}?".to_sym)
100
+ code_or_name = RESPONSE_PREDICATES.invert["#{code_or_name}?".to_sym]
101
+ end
102
+
103
+ AssertionResponse.new(code_or_name).code_and_name
104
+ end
80
105
  end
81
106
  end
82
107
  end
@@ -1,7 +1,9 @@
1
- require 'uri'
2
- require 'active_support/core_ext/hash/indifferent_access'
3
- require 'active_support/core_ext/string/access'
4
- require 'action_controller/metal/exceptions'
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+ require "active_support/core_ext/hash/indifferent_access"
5
+ require "active_support/core_ext/string/access"
6
+ require "action_controller/metal/exceptions"
5
7
 
6
8
  module ActionDispatch
7
9
  module Assertions
@@ -14,14 +16,14 @@ module ActionDispatch
14
16
  # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
15
17
  # and a :method containing the required HTTP verb.
16
18
  #
17
- # # assert that POSTing to /items will call the create action on ItemsController
19
+ # # Asserts that POSTing to /items will call the create action on ItemsController
18
20
  # assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
19
21
  #
20
22
  # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
21
- # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
22
- # extras argument, appending the query string on the path directly will not work. For example:
23
+ # to assert that values in the query string will end up in the params hash correctly. To test query strings you must use the extras
24
+ # argument because appending the query string on the path directly will not work. For example:
23
25
  #
24
- # # assert that a path of '/items/list/1?view=print' returns the correct options
26
+ # # Asserts that a path of '/items/list/1?view=print' returns the correct options
25
27
  # assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" })
26
28
  #
27
29
  # The +message+ parameter allows you to pass in an error message that is displayed upon failure.
@@ -37,7 +39,7 @@ module ActionDispatch
37
39
  #
38
40
  # # Test a custom route
39
41
  # assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
40
- def assert_recognizes(expected_options, path, extras={}, msg=nil)
42
+ def assert_recognizes(expected_options, path, extras = {}, msg = nil)
41
43
  if path.is_a?(Hash) && path[:method].to_s == "all"
42
44
  [:get, :post, :put, :delete].each do |method|
43
45
  assert_recognizes(expected_options, path.merge(method: method), extras, msg)
@@ -75,19 +77,20 @@ module ActionDispatch
75
77
  #
76
78
  # # Asserts that the generated route gives us our custom route
77
79
  # assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
78
- def assert_generates(expected_path, options, defaults={}, extras={}, message=nil)
80
+ def assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil)
79
81
  if expected_path =~ %r{://}
80
82
  fail_on(URI::InvalidURIError, message) do
81
83
  uri = URI.parse(expected_path)
82
84
  expected_path = uri.path.to_s.empty? ? "/" : uri.path
83
85
  end
84
86
  else
85
- expected_path = "/#{expected_path}" unless expected_path.first == '/'
87
+ expected_path = "/#{expected_path}" unless expected_path.first == "/"
86
88
  end
87
89
  # Load routes.rb if it hasn't been loaded.
88
90
 
89
- generated_path, extra_keys = @routes.generate_extras(options, defaults)
90
- found_extras = options.reject { |k, _| ! extra_keys.include? k }
91
+ options = options.clone
92
+ generated_path, query_string_keys = @routes.generate_extras(options, defaults)
93
+ found_extras = options.reject { |k, _| ! query_string_keys.include? k }
91
94
 
92
95
  msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras)
93
96
  assert_equal(extras, found_extras, msg)
@@ -104,21 +107,21 @@ module ActionDispatch
104
107
  # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
105
108
  # +message+ parameter allows you to specify a custom error message to display upon failure.
106
109
  #
107
- # # Assert a basic route: a controller with the default action (index)
110
+ # # Asserts a basic route: a controller with the default action (index)
108
111
  # assert_routing '/home', controller: 'home', action: 'index'
109
112
  #
110
113
  # # Test a route generated with a specific controller, action, and parameter (id)
111
114
  # assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23
112
115
  #
113
- # # Assert a basic route (controller + default action), with an error message if it fails
116
+ # # Asserts a basic route (controller + default action), with an error message if it fails
114
117
  # assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly'
115
118
  #
116
119
  # # Tests a route, providing a defaults hash
117
120
  # assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"}
118
121
  #
119
- # # Tests a route with a HTTP method
122
+ # # Tests a route with an HTTP method
120
123
  # assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" })
121
- def assert_routing(path, options, defaults={}, extras={}, message=nil)
124
+ def assert_routing(path, options, defaults = {}, extras = {}, message = nil)
122
125
  assert_recognizes(options, path, extras, message)
123
126
 
124
127
  controller, default_controller = options[:controller], defaults[:controller]
@@ -126,13 +129,12 @@ module ActionDispatch
126
129
  options[:controller] = "/#{controller}"
127
130
  end
128
131
 
129
- generate_options = options.dup.delete_if{ |k, _| defaults.key?(k) }
132
+ generate_options = options.dup.delete_if { |k, _| defaults.key?(k) }
130
133
  assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message)
131
134
  end
132
135
 
133
136
  # A helper to make it easier to test different route configurations.
134
- # This method temporarily replaces @routes
135
- # with a new RouteSet instance.
137
+ # This method temporarily replaces @routes with a new RouteSet instance.
136
138
  #
137
139
  # The new instance is yielded to the passed block. Typically the block
138
140
  # will create some routes using <tt>set.draw { match ... }</tt>:
@@ -150,9 +152,12 @@ module ActionDispatch
150
152
  old_controller, @controller = @controller, @controller.clone
151
153
  _routes = @routes
152
154
 
153
- @controller.singleton_class.send(:include, _routes.url_helpers)
154
- @controller.view_context_class = Class.new(@controller.view_context_class) do
155
- include _routes.url_helpers
155
+ @controller.singleton_class.include(_routes.url_helpers)
156
+
157
+ if @controller.respond_to? :view_context_class
158
+ @controller.view_context_class = Class.new(@controller.view_context_class) do
159
+ include _routes.url_helpers
160
+ end
156
161
  end
157
162
  end
158
163
  yield @routes
@@ -182,8 +187,7 @@ module ActionDispatch
182
187
  method = :get
183
188
  end
184
189
 
185
- # Assume given controller
186
- request = ActionController::TestRequest.new
190
+ request = ActionController::TestRequest.create @controller.class
187
191
 
188
192
  if path =~ %r{://}
189
193
  fail_on(URI::InvalidURIError, msg) do
@@ -201,7 +205,7 @@ module ActionDispatch
201
205
  request.request_method = method if method
202
206
 
203
207
  params = fail_on(ActionController::RoutingError, msg) do
204
- @routes.recognize_path(path, { :method => method, :extras => extras })
208
+ @routes.recognize_path(path, method: method, extras: extras)
205
209
  end
206
210
  request.path_parameters = params.with_indifferent_access
207
211