actionpack 7.0.8.1 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -500
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +119 -106
  7. data/lib/abstract_controller/caching/fragments.rb +51 -52
  8. data/lib/abstract_controller/caching.rb +2 -0
  9. data/lib/abstract_controller/callbacks.rb +94 -67
  10. data/lib/abstract_controller/collector.rb +6 -6
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +121 -91
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
  16. data/lib/abstract_controller/rendering.rb +14 -13
  17. data/lib/abstract_controller/translation.rb +12 -30
  18. data/lib/abstract_controller/url_for.rb +9 -5
  19. data/lib/abstract_controller.rb +8 -0
  20. data/lib/action_controller/api/api_rendering.rb +2 -0
  21. data/lib/action_controller/api.rb +78 -73
  22. data/lib/action_controller/base.rb +199 -141
  23. data/lib/action_controller/caching.rb +16 -11
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +21 -16
  26. data/lib/action_controller/log_subscriber.rb +19 -5
  27. data/lib/action_controller/metal/allow_browser.rb +123 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  29. data/lib/action_controller/metal/conditional_get.rb +187 -174
  30. data/lib/action_controller/metal/content_security_policy.rb +26 -25
  31. data/lib/action_controller/metal/cookies.rb +4 -2
  32. data/lib/action_controller/metal/data_streaming.rb +65 -54
  33. data/lib/action_controller/metal/default_headers.rb +6 -2
  34. data/lib/action_controller/metal/etag_with_flash.rb +4 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +18 -14
  36. data/lib/action_controller/metal/exceptions.rb +19 -9
  37. data/lib/action_controller/metal/flash.rb +12 -10
  38. data/lib/action_controller/metal/head.rb +20 -16
  39. data/lib/action_controller/metal/helpers.rb +64 -67
  40. data/lib/action_controller/metal/http_authentication.rb +214 -200
  41. data/lib/action_controller/metal/implicit_render.rb +21 -17
  42. data/lib/action_controller/metal/instrumentation.rb +22 -12
  43. data/lib/action_controller/metal/live.rb +125 -92
  44. data/lib/action_controller/metal/logging.rb +6 -4
  45. data/lib/action_controller/metal/mime_responds.rb +151 -142
  46. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  47. data/lib/action_controller/metal/params_wrapper.rb +58 -58
  48. data/lib/action_controller/metal/permissions_policy.rb +14 -13
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +110 -84
  51. data/lib/action_controller/metal/renderers.rb +50 -49
  52. data/lib/action_controller/metal/rendering.rb +103 -82
  53. data/lib/action_controller/metal/request_forgery_protection.rb +279 -161
  54. data/lib/action_controller/metal/rescue.rb +12 -8
  55. data/lib/action_controller/metal/streaming.rb +174 -132
  56. data/lib/action_controller/metal/strong_parameters.rb +598 -473
  57. data/lib/action_controller/metal/testing.rb +2 -0
  58. data/lib/action_controller/metal/url_for.rb +23 -14
  59. data/lib/action_controller/metal.rb +145 -61
  60. data/lib/action_controller/railtie.rb +25 -9
  61. data/lib/action_controller/railties/helpers.rb +2 -0
  62. data/lib/action_controller/renderer.rb +105 -66
  63. data/lib/action_controller/template_assertions.rb +4 -2
  64. data/lib/action_controller/test_case.rb +157 -128
  65. data/lib/action_controller.rb +17 -3
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +28 -29
  69. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +69 -49
  71. data/lib/action_dispatch/http/filter_parameters.rb +27 -12
  72. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  73. data/lib/action_dispatch/http/headers.rb +23 -21
  74. data/lib/action_dispatch/http/mime_negotiation.rb +37 -48
  75. data/lib/action_dispatch/http/mime_type.rb +60 -30
  76. data/lib/action_dispatch/http/mime_types.rb +5 -1
  77. data/lib/action_dispatch/http/parameters.rb +12 -10
  78. data/lib/action_dispatch/http/permissions_policy.rb +32 -34
  79. data/lib/action_dispatch/http/rack_cache.rb +4 -0
  80. data/lib/action_dispatch/http/request.rb +132 -79
  81. data/lib/action_dispatch/http/response.rb +136 -103
  82. data/lib/action_dispatch/http/upload.rb +19 -15
  83. data/lib/action_dispatch/http/url.rb +75 -73
  84. data/lib/action_dispatch/journey/formatter.rb +19 -6
  85. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  88. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  89. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  90. data/lib/action_dispatch/journey/parser.rb +4 -3
  91. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  92. data/lib/action_dispatch/journey/path/pattern.rb +18 -15
  93. data/lib/action_dispatch/journey/route.rb +12 -9
  94. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  95. data/lib/action_dispatch/journey/router.rb +13 -10
  96. data/lib/action_dispatch/journey/routes.rb +6 -4
  97. data/lib/action_dispatch/journey/scanner.rb +4 -2
  98. data/lib/action_dispatch/journey/visitors.rb +2 -0
  99. data/lib/action_dispatch/journey.rb +2 -0
  100. data/lib/action_dispatch/log_subscriber.rb +25 -0
  101. data/lib/action_dispatch/middleware/actionable_exceptions.rb +7 -6
  102. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  103. data/lib/action_dispatch/middleware/callbacks.rb +4 -0
  104. data/lib/action_dispatch/middleware/cookies.rb +192 -194
  105. data/lib/action_dispatch/middleware/debug_exceptions.rb +36 -27
  106. data/lib/action_dispatch/middleware/debug_locks.rb +18 -13
  107. data/lib/action_dispatch/middleware/debug_view.rb +9 -2
  108. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
  109. data/lib/action_dispatch/middleware/executor.rb +9 -1
  110. data/lib/action_dispatch/middleware/flash.rb +65 -46
  111. data/lib/action_dispatch/middleware/host_authorization.rb +22 -17
  112. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -8
  113. data/lib/action_dispatch/middleware/reloader.rb +9 -5
  114. data/lib/action_dispatch/middleware/remote_ip.rb +88 -83
  115. data/lib/action_dispatch/middleware/request_id.rb +15 -8
  116. data/lib/action_dispatch/middleware/server_timing.rb +8 -6
  117. data/lib/action_dispatch/middleware/session/abstract_store.rb +7 -0
  118. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -7
  119. data/lib/action_dispatch/middleware/session/cookie_store.rb +32 -25
  120. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -3
  121. data/lib/action_dispatch/middleware/show_exceptions.rb +42 -28
  122. data/lib/action_dispatch/middleware/ssl.rb +60 -45
  123. data/lib/action_dispatch/middleware/stack.rb +15 -9
  124. data/lib/action_dispatch/middleware/static.rb +40 -34
  125. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  126. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  127. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  130. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +47 -38
  139. data/lib/action_dispatch/railtie.rb +12 -4
  140. data/lib/action_dispatch/request/session.rb +39 -27
  141. data/lib/action_dispatch/request/utils.rb +10 -3
  142. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  143. data/lib/action_dispatch/routing/inspector.rb +59 -9
  144. data/lib/action_dispatch/routing/mapper.rb +686 -639
  145. data/lib/action_dispatch/routing/polymorphic_routes.rb +70 -61
  146. data/lib/action_dispatch/routing/redirection.rb +52 -38
  147. data/lib/action_dispatch/routing/route_set.rb +106 -62
  148. data/lib/action_dispatch/routing/routes_proxy.rb +16 -19
  149. data/lib/action_dispatch/routing/url_for.rb +131 -122
  150. data/lib/action_dispatch/routing.rb +152 -150
  151. data/lib/action_dispatch/system_test_case.rb +91 -81
  152. data/lib/action_dispatch/system_testing/browser.rb +27 -19
  153. data/lib/action_dispatch/system_testing/driver.rb +16 -22
  154. data/lib/action_dispatch/system_testing/server.rb +2 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +53 -31
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +9 -7
  158. data/lib/action_dispatch/testing/assertions/response.rb +36 -26
  159. data/lib/action_dispatch/testing/assertions/routing.rb +203 -95
  160. data/lib/action_dispatch/testing/assertions.rb +5 -1
  161. data/lib/action_dispatch/testing/integration.rb +240 -229
  162. data/lib/action_dispatch/testing/request_encoder.rb +6 -1
  163. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  164. data/lib/action_dispatch/testing/test_process.rb +14 -9
  165. data/lib/action_dispatch/testing/test_request.rb +4 -2
  166. data/lib/action_dispatch/testing/test_response.rb +34 -19
  167. data/lib/action_dispatch.rb +52 -21
  168. data/lib/action_pack/gem_version.rb +5 -3
  169. data/lib/action_pack/version.rb +3 -1
  170. data/lib/action_pack.rb +18 -17
  171. metadata +91 -32
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module SystemTesting
5
7
  class Browser # :nodoc:
6
- attr_reader :name, :options
8
+ attr_reader :name
7
9
 
8
10
  def initialize(name)
9
11
  @name = name
@@ -21,35 +23,32 @@ module ActionDispatch
21
23
  end
22
24
  end
23
25
 
26
+ def options
27
+ @options ||=
28
+ case type
29
+ when :chrome
30
+ ::Selenium::WebDriver::Chrome::Options.new
31
+ when :firefox
32
+ ::Selenium::WebDriver::Firefox::Options.new
33
+ end
34
+ end
35
+
24
36
  def configure
25
- initialize_options
26
- yield options if block_given? && options
37
+ yield options if block_given?
27
38
  end
28
39
 
29
- # driver_path can be configured as a proc.
30
- # proc to update web drivers. Running this proc early allows us to only
31
- # update the webdriver once and avoid race conditions when using
32
- # parallel tests.
40
+ # driver_path is lazily initialized by default. Eagerly set it to avoid race
41
+ # conditions when using parallel tests.
33
42
  def preload
34
43
  case type
35
44
  when :chrome
36
- ::Selenium::WebDriver::Chrome::Service.driver_path&.call
45
+ resolve_driver_path(::Selenium::WebDriver::Chrome)
37
46
  when :firefox
38
- ::Selenium::WebDriver::Firefox::Service.driver_path&.call
47
+ resolve_driver_path(::Selenium::WebDriver::Firefox)
39
48
  end
40
49
  end
41
50
 
42
51
  private
43
- def initialize_options
44
- @options ||=
45
- case type
46
- when :chrome
47
- ::Selenium::WebDriver::Chrome::Options.new
48
- when :firefox
49
- ::Selenium::WebDriver::Firefox::Options.new
50
- end
51
- end
52
-
53
52
  def set_default_options
54
53
  case name
55
54
  when :headless_chrome
@@ -71,6 +70,15 @@ module ActionDispatch
71
70
  capabilities.add_argument("-headless")
72
71
  end
73
72
  end
73
+
74
+ def resolve_driver_path(namespace)
75
+ # The path method has been deprecated in 4.20.0
76
+ if Gem::Version.new(::Selenium::WebDriver::VERSION) >= Gem::Version.new("4.20.0")
77
+ namespace::Service.driver_path = ::Selenium::WebDriver::DriverFinder.new(options, namespace::Service.new).driver_path
78
+ else
79
+ namespace::Service.driver_path = ::Selenium::WebDriver::DriverFinder.path(options, namespace::Service)
80
+ end
81
+ end
74
82
  end
75
83
  end
76
84
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module SystemTesting
5
7
  class Driver # :nodoc:
@@ -12,19 +14,11 @@ module ActionDispatch
12
14
  @name = @options.delete(:name) || driver_type
13
15
  @capabilities = capabilities
14
16
 
15
- if [:poltergeist, :webkit].include?(driver_type)
16
- ActiveSupport::Deprecation.warn <<~MSG.squish
17
- Poltergeist and capybara-webkit are not maintained already.
18
- Driver registration of :poltergeist or :webkit is deprecated and will be removed in Rails 7.1.
19
- You can still use :selenium, and also :cuprite is available for alternative to Poltergeist.
20
- MSG
21
- end
22
-
23
17
  if driver_type == :selenium
24
18
  gem "selenium-webdriver", ">= 4.0.0"
25
19
  require "selenium/webdriver"
26
20
  @browser = Browser.new(options[:using])
27
- @browser.preload
21
+ @browser.preload unless @options[:browser] == :remote
28
22
  else
29
23
  @browser = nil
30
24
  end
@@ -38,7 +32,7 @@ module ActionDispatch
38
32
 
39
33
  private
40
34
  def registerable?
41
- [:selenium, :poltergeist, :webkit, :cuprite, :rack_test].include?(@driver_type)
35
+ [:selenium, :cuprite, :rack_test, :playwright].include?(@driver_type)
42
36
  end
43
37
 
44
38
  def register
@@ -47,10 +41,9 @@ module ActionDispatch
47
41
  Capybara.register_driver name do |app|
48
42
  case @driver_type
49
43
  when :selenium then register_selenium(app)
50
- when :poltergeist then register_poltergeist(app)
51
- when :webkit then register_webkit(app)
52
44
  when :cuprite then register_cuprite(app)
53
45
  when :rack_test then register_rack_test(app)
46
+ when :playwright then register_playwright(app)
54
47
  end
55
48
  end
56
49
  end
@@ -65,16 +58,6 @@ module ActionDispatch
65
58
  end
66
59
  end
67
60
 
68
- def register_poltergeist(app)
69
- Capybara::Poltergeist::Driver.new(app, @options.merge(window_size: @screen_size))
70
- end
71
-
72
- def register_webkit(app)
73
- Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver|
74
- driver.resize_window_to(driver.current_window_handle, *@screen_size)
75
- end
76
- end
77
-
78
61
  def register_cuprite(app)
79
62
  Capybara::Cuprite::Driver.new(app, @options.merge(window_size: @screen_size))
80
63
  end
@@ -83,6 +66,17 @@ module ActionDispatch
83
66
  Capybara::RackTest::Driver.new(app, respect_data_method: true, **@options)
84
67
  end
85
68
 
69
+ def register_playwright(app)
70
+ screen = { width: @screen_size[0], height: @screen_size[1] } if @screen_size
71
+ options = {
72
+ screen: screen,
73
+ viewport: screen,
74
+ **@options
75
+ }.compact
76
+
77
+ Capybara::Playwright::Driver.new(app, **options)
78
+ end
79
+
86
80
  def setup
87
81
  Capybara.current_driver = name
88
82
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module SystemTesting
5
7
  class Server # :nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module SystemTesting
5
7
  module TestHelpers
@@ -7,48 +9,58 @@ module ActionDispatch
7
9
  module ScreenshotHelper
8
10
  # Takes a screenshot of the current page in the browser.
9
11
  #
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. You can take multiple screenshots per test
13
- # to investigate changes at different points during your test. These will be
14
- # named with a sequential prefix (or 'failed' for failing tests)
12
+ # `take_screenshot` can be used at any point in your system tests to take a
13
+ # screenshot of the current state. This can be useful for debugging or
14
+ # automating visual testing. You can take multiple screenshots per test to
15
+ # investigate changes at different points during your test. These will be named
16
+ # with a sequential prefix (or 'failed' for failing tests)
17
+ #
18
+ # The default screenshots directory is `tmp/screenshots` but you can set a
19
+ # different one with `Capybara.save_path`
20
+ #
21
+ # You can use the `html` argument or set the
22
+ # `RAILS_SYSTEM_TESTING_SCREENSHOT_HTML` environment variable to save the HTML
23
+ # from the page that is being screenshotted so you can investigate the elements
24
+ # on the page at the time of the screenshot
15
25
  #
16
- # The screenshot will be displayed in your console, if supported.
26
+ # You can use the `screenshot` argument or set the
27
+ # `RAILS_SYSTEM_TESTING_SCREENSHOT` environment variable to control the output.
28
+ # Possible values are:
29
+ # `simple` (default)
30
+ # : Only displays the screenshot path. This is the default value.
17
31
  #
18
- # The default screenshots directory is +tmp/screenshots+ but you can set a different
19
- # one with +Capybara.save_path+
32
+ # `inline`
33
+ # : Display the screenshot in the terminal using the iTerm image protocol
34
+ # (https://iterm2.com/documentation-images.html).
20
35
  #
21
- # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT_HTML+ environment variable to
22
- # save the HTML from the page that is being screenshotted so you can investigate the
23
- # elements on the page at the time of the screenshot
36
+ # `artifact`
37
+ # : Display the screenshot in the terminal, using the terminal artifact
38
+ # format (https://buildkite.github.io/terminal-to-html/inline-images/).
24
39
  #
25
- # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT+ environment variable to
26
- # control the output. Possible values are:
27
- # * [+simple+ (default)] Only displays the screenshot path.
28
- # This is the default value.
29
- # * [+inline+] Display the screenshot in the terminal using the
30
- # iTerm image protocol (https://iterm2.com/documentation-images.html).
31
- # * [+artifact+] Display the screenshot in the terminal, using the terminal
32
- # artifact format (https://buildkite.github.io/terminal-to-html/inline-images/).
33
- def take_screenshot
40
+ #
41
+ def take_screenshot(html: false, screenshot: nil)
42
+ showing_html = html || html_from_env?
43
+
34
44
  increment_unique
35
- save_html if save_html?
45
+ save_html if showing_html
36
46
  save_image
37
- puts display_image
47
+ show display_image(html: showing_html, screenshot_output: screenshot)
38
48
  end
39
49
 
40
- # Takes a screenshot of the current page in the browser if the test
41
- # failed.
50
+ # Takes a screenshot of the current page in the browser if the test failed.
42
51
  #
43
- # +take_failed_screenshot+ is called during system test teardown.
52
+ # `take_failed_screenshot` is called during system test teardown.
44
53
  def take_failed_screenshot
45
- take_screenshot if failed? && supports_screenshot? && Capybara::Session.instance_created?
54
+ return unless failed? && supports_screenshot? && Capybara::Session.instance_created?
55
+
56
+ take_screenshot
57
+ metadata[:failure_screenshot_path] = relative_image_path if Minitest::Runnable.method_defined?(:metadata)
46
58
  end
47
59
 
48
60
  private
49
61
  attr_accessor :_screenshot_counter
50
62
 
51
- def save_html?
63
+ def html_from_env?
52
64
  ENV["RAILS_SYSTEM_TESTING_SCREENSHOT_HTML"] == "1"
53
65
  end
54
66
 
@@ -62,7 +74,7 @@ module ActionDispatch
62
74
  end
63
75
 
64
76
  def image_name
65
- sanitized_method_name = method_name.tr("/\\", "--")
77
+ sanitized_method_name = method_name.gsub(/[^\w]+/, "-")
66
78
  name = "#{unique}_#{sanitized_method_name}"
67
79
  name[0...225]
68
80
  end
@@ -87,10 +99,15 @@ module ActionDispatch
87
99
  "#{absolute_path}.png"
88
100
  end
89
101
 
102
+ def relative_image_path
103
+ "#{absolute_path.relative_path_from(Rails.root)}.png"
104
+ end
105
+
90
106
  def absolute_html_path
91
107
  "#{absolute_path}.html"
92
108
  end
93
109
 
110
+ # rubocop:disable Lint/Debugger
94
111
  def save_html
95
112
  page.save_page(absolute_html_path)
96
113
  end
@@ -98,6 +115,7 @@ module ActionDispatch
98
115
  def save_image
99
116
  page.save_screenshot(absolute_image_path)
100
117
  end
118
+ # rubocop:enable Lint/Debugger
101
119
 
102
120
  def output_type
103
121
  # Environment variables have priority
@@ -109,11 +127,15 @@ module ActionDispatch
109
127
  output_type
110
128
  end
111
129
 
112
- def display_image
130
+ def show(img)
131
+ puts img
132
+ end
133
+
134
+ def display_image(html:, screenshot_output:)
113
135
  message = +"[Screenshot Image]: #{image_path}\n"
114
- message << +"[Screenshot HTML]: #{html_path}\n" if save_html?
136
+ message << +"[Screenshot HTML]: #{html_path}\n" if html
115
137
 
116
- case output_type
138
+ case screenshot_output || output_type
117
139
  when "artifact"
118
140
  message << "\e]1338;url=artifact://#{absolute_image_path}\a\n"
119
141
  when "inline"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module SystemTesting
5
7
  module TestHelpers
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  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.
6
+ # This is a class that abstracts away an asserted response. It purposely does
7
+ # not inherit from Response because it doesn't need it. That means it does not
8
+ # have headers or a body.
7
9
  class AssertionResponse
8
10
  attr_reader :code, :name
9
11
 
@@ -14,9 +16,9 @@ module ActionDispatch
14
16
  error: "5XX"
15
17
  }
16
18
 
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).
19
+ # Accepts a specific response status code as an Integer (404) or String ('404')
20
+ # or a response status range as a Symbol pseudo-code (:success, indicating any
21
+ # 200-299 status code).
20
22
  def initialize(code_or_name)
21
23
  if code_or_name.is_a?(Symbol)
22
24
  @name = code_or_name
@@ -36,7 +38,7 @@ module ActionDispatch
36
38
 
37
39
  private
38
40
  def code_from_name(name)
39
- GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name]
41
+ GENERIC_RESPONSE_CODES[name] || Rack::Utils.status_code(name)
40
42
  end
41
43
 
42
44
  def name_from_code(code)
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Assertions
5
- # A small suite of assertions that test responses from \Rails applications.
7
+ # A small suite of assertions that test responses from Rails applications.
6
8
  module ResponseAssertions
7
9
  RESPONSE_PREDICATES = { # :nodoc:
8
10
  success: :successful?,
@@ -13,24 +15,25 @@ module ActionDispatch
13
15
 
14
16
  # Asserts that the response is one of the following types:
15
17
  #
16
- # * <tt>:success</tt> - Status code was in the 200-299 range
17
- # * <tt>:redirect</tt> - Status code was in the 300-399 range
18
- # * <tt>:missing</tt> - Status code was 404
19
- # * <tt>:error</tt> - Status code was in the 500-599 range
18
+ # * `:success` - Status code was in the 200-299 range
19
+ # * `:redirect` - Status code was in the 300-399 range
20
+ # * `:missing` - Status code was 404
21
+ # * `:error` - Status code was in the 500-599 range
22
+ #
20
23
  #
21
- # You can also pass an explicit status number like <tt>assert_response(501)</tt>
22
- # or its symbolic equivalent <tt>assert_response(:not_implemented)</tt>.
23
- # See +Rack::Utils::SYMBOL_TO_STATUS_CODE+ for a full list.
24
+ # You can also pass an explicit status number like `assert_response(501)` or its
25
+ # symbolic equivalent `assert_response(:not_implemented)`. See
26
+ # `Rack::Utils::SYMBOL_TO_STATUS_CODE` for a full list.
24
27
  #
25
- # # Asserts that the response was a redirection
26
- # assert_response :redirect
28
+ # # Asserts that the response was a redirection
29
+ # assert_response :redirect
27
30
  #
28
- # # Asserts that the response code was status code 401 (unauthorized)
29
- # assert_response 401
31
+ # # Asserts that the response code was status code 401 (unauthorized)
32
+ # assert_response 401
30
33
  def assert_response(type, message = nil)
31
34
  message ||= generate_response_message(type)
32
35
 
33
- if RESPONSE_PREDICATES.keys.include?(type)
36
+ if RESPONSE_PREDICATES.key?(type)
34
37
  assert @response.public_send(RESPONSE_PREDICATES[type]), message
35
38
  else
36
39
  assert_equal AssertionResponse.new(type).code, @response.response_code, message
@@ -39,23 +42,30 @@ module ActionDispatch
39
42
 
40
43
  # Asserts that the response is a redirect to a URL matching the given options.
41
44
  #
42
- # # Asserts that the redirection was to the "index" action on the WeblogController
43
- # assert_redirected_to controller: "weblog", action: "index"
45
+ # # Asserts that the redirection was to the "index" action on the WeblogController
46
+ # assert_redirected_to controller: "weblog", action: "index"
44
47
  #
45
- # # Asserts that the redirection was to the named route login_url
46
- # assert_redirected_to login_url
48
+ # # Asserts that the redirection was to the named route login_url
49
+ # assert_redirected_to login_url
47
50
  #
48
- # # Asserts that the redirection was to the URL for @customer
49
- # assert_redirected_to @customer
51
+ # # Asserts that the redirection was to the URL for @customer
52
+ # assert_redirected_to @customer
50
53
  #
51
- # # Asserts that the redirection matches the regular expression
52
- # assert_redirected_to %r(\Ahttp://example.org)
53
- def assert_redirected_to(options = {}, message = nil)
54
- assert_response(:redirect, message)
55
- return true if options === @response.location
54
+ # # Asserts that the redirection matches the regular expression
55
+ # assert_redirected_to %r(\Ahttp://example.org)
56
+ #
57
+ # # Asserts that the redirection has the HTTP status code 301 (Moved
58
+ # # Permanently).
59
+ # assert_redirected_to "/some/path", status: :moved_permanently
60
+ def assert_redirected_to(url_options = {}, options = {}, message = nil)
61
+ options, message = {}, options unless options.is_a?(Hash)
62
+
63
+ status = options[:status] || :redirect
64
+ assert_response(status, message)
65
+ return true if url_options === @response.location
56
66
 
57
67
  redirect_is = normalize_argument_to_redirection(@response.location)
58
- redirect_expected = normalize_argument_to_redirection(options)
68
+ redirect_expected = normalize_argument_to_redirection(url_options)
59
69
 
60
70
  message ||= "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>"
61
71
  assert_operator redirect_expected, :===, redirect_is, message
@@ -93,7 +103,7 @@ module ActionDispatch
93
103
  end
94
104
 
95
105
  def code_with_name(code_or_name)
96
- if RESPONSE_PREDICATES.values.include?("#{code_or_name}?".to_sym)
106
+ if RESPONSE_PREDICATES.value?("#{code_or_name}?".to_sym)
97
107
  code_or_name = RESPONSE_PREDICATES.invert["#{code_or_name}?".to_sym]
98
108
  end
99
109