actionpack 3.2.22.5 → 5.2.4

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 (271) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +279 -603
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -297
  5. data/lib/abstract_controller/asset_paths.rb +4 -2
  6. data/lib/abstract_controller/base.rb +82 -52
  7. data/lib/abstract_controller/caching/fragments.rb +166 -0
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +117 -103
  10. data/lib/abstract_controller/collector.rb +18 -7
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +65 -38
  13. data/lib/abstract_controller/logger.rb +3 -2
  14. data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
  15. data/lib/abstract_controller/rendering.rb +77 -129
  16. data/lib/abstract_controller/translation.rb +21 -3
  17. data/lib/abstract_controller/url_for.rb +9 -7
  18. data/lib/abstract_controller.rb +12 -13
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/base.rb +81 -40
  22. data/lib/action_controller/caching.rb +22 -62
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +30 -18
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +190 -47
  27. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  28. data/lib/action_controller/metal/cookies.rb +3 -3
  29. data/lib/action_controller/metal/data_streaming.rb +40 -65
  30. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  31. data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
  32. data/lib/action_controller/metal/exceptions.rb +19 -12
  33. data/lib/action_controller/metal/flash.rb +42 -9
  34. data/lib/action_controller/metal/force_ssl.rb +79 -19
  35. data/lib/action_controller/metal/head.rb +35 -10
  36. data/lib/action_controller/metal/helpers.rb +31 -21
  37. data/lib/action_controller/metal/http_authentication.rb +182 -134
  38. data/lib/action_controller/metal/implicit_render.rb +62 -8
  39. data/lib/action_controller/metal/instrumentation.rb +28 -26
  40. data/lib/action_controller/metal/live.rb +312 -0
  41. data/lib/action_controller/metal/mime_responds.rb +159 -163
  42. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  43. data/lib/action_controller/metal/params_wrapper.rb +146 -93
  44. data/lib/action_controller/metal/redirecting.rb +80 -56
  45. data/lib/action_controller/metal/renderers.rb +119 -47
  46. data/lib/action_controller/metal/rendering.rb +89 -32
  47. data/lib/action_controller/metal/request_forgery_protection.rb +373 -41
  48. data/lib/action_controller/metal/rescue.rb +9 -16
  49. data/lib/action_controller/metal/streaming.rb +39 -45
  50. data/lib/action_controller/metal/strong_parameters.rb +1086 -0
  51. data/lib/action_controller/metal/testing.rb +8 -29
  52. data/lib/action_controller/metal/url_for.rb +43 -32
  53. data/lib/action_controller/metal.rb +112 -106
  54. data/lib/action_controller/railtie.rb +56 -18
  55. data/lib/action_controller/railties/helpers.rb +24 -0
  56. data/lib/action_controller/renderer.rb +117 -0
  57. data/lib/action_controller/template_assertions.rb +11 -0
  58. data/lib/action_controller/test_case.rb +402 -347
  59. data/lib/action_controller.rb +31 -30
  60. data/lib/action_dispatch/http/cache.rb +133 -34
  61. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  62. data/lib/action_dispatch/http/filter_parameters.rb +40 -24
  63. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  64. data/lib/action_dispatch/http/headers.rb +117 -16
  65. data/lib/action_dispatch/http/mime_negotiation.rb +98 -33
  66. data/lib/action_dispatch/http/mime_type.rb +198 -146
  67. data/lib/action_dispatch/http/mime_types.rb +22 -7
  68. data/lib/action_dispatch/http/parameter_filter.rb +61 -49
  69. data/lib/action_dispatch/http/parameters.rb +94 -51
  70. data/lib/action_dispatch/http/rack_cache.rb +4 -3
  71. data/lib/action_dispatch/http/request.rb +262 -117
  72. data/lib/action_dispatch/http/response.rb +400 -86
  73. data/lib/action_dispatch/http/upload.rb +66 -29
  74. data/lib/action_dispatch/http/url.rb +232 -60
  75. data/lib/action_dispatch/journey/formatter.rb +189 -0
  76. data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
  77. data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
  78. data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
  79. data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
  80. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  81. data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
  82. data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
  83. data/lib/action_dispatch/journey/nodes/node.rb +140 -0
  84. data/lib/action_dispatch/journey/parser.rb +199 -0
  85. data/lib/action_dispatch/journey/parser.y +50 -0
  86. data/lib/action_dispatch/journey/parser_extras.rb +31 -0
  87. data/lib/action_dispatch/journey/path/pattern.rb +199 -0
  88. data/lib/action_dispatch/journey/route.rb +203 -0
  89. data/lib/action_dispatch/journey/router/utils.rb +102 -0
  90. data/lib/action_dispatch/journey/router.rb +156 -0
  91. data/lib/action_dispatch/journey/routes.rb +82 -0
  92. data/lib/action_dispatch/journey/scanner.rb +64 -0
  93. data/lib/action_dispatch/journey/visitors.rb +268 -0
  94. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  95. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  96. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  97. data/lib/action_dispatch/journey.rb +7 -0
  98. data/lib/action_dispatch/middleware/callbacks.rb +17 -13
  99. data/lib/action_dispatch/middleware/cookies.rb +494 -162
  100. data/lib/action_dispatch/middleware/debug_exceptions.rb +176 -53
  101. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  102. data/lib/action_dispatch/middleware/exception_wrapper.rb +103 -38
  103. data/lib/action_dispatch/middleware/executor.rb +21 -0
  104. data/lib/action_dispatch/middleware/flash.rb +128 -91
  105. data/lib/action_dispatch/middleware/public_exceptions.rb +43 -16
  106. data/lib/action_dispatch/middleware/reloader.rb +6 -83
  107. data/lib/action_dispatch/middleware/remote_ip.rb +151 -49
  108. data/lib/action_dispatch/middleware/request_id.rb +19 -15
  109. data/lib/action_dispatch/middleware/session/abstract_store.rb +38 -34
  110. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -9
  111. data/lib/action_dispatch/middleware/session/cookie_store.rb +94 -44
  112. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -4
  113. data/lib/action_dispatch/middleware/show_exceptions.rb +36 -61
  114. data/lib/action_dispatch/middleware/ssl.rb +150 -0
  115. data/lib/action_dispatch/middleware/stack.rb +33 -41
  116. data/lib/action_dispatch/middleware/static.rb +92 -48
  117. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  122. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  123. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +134 -5
  128. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  136. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  137. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
  138. data/lib/action_dispatch/railtie.rb +29 -8
  139. data/lib/action_dispatch/request/session.rb +234 -0
  140. data/lib/action_dispatch/request/utils.rb +78 -0
  141. data/lib/action_dispatch/routing/endpoint.rb +17 -0
  142. data/lib/action_dispatch/routing/inspector.rb +225 -0
  143. data/lib/action_dispatch/routing/mapper.rb +1329 -582
  144. data/lib/action_dispatch/routing/polymorphic_routes.rb +237 -94
  145. data/lib/action_dispatch/routing/redirection.rb +120 -50
  146. data/lib/action_dispatch/routing/route_set.rb +545 -322
  147. data/lib/action_dispatch/routing/routes_proxy.rb +37 -7
  148. data/lib/action_dispatch/routing/url_for.rb +103 -34
  149. data/lib/action_dispatch/routing.rb +66 -99
  150. data/lib/action_dispatch/system_test_case.rb +147 -0
  151. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  152. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  153. data/lib/action_dispatch/system_testing/server.rb +31 -0
  154. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  156. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  158. data/lib/action_dispatch/testing/assertions/response.rb +53 -42
  159. data/lib/action_dispatch/testing/assertions/routing.rb +79 -74
  160. data/lib/action_dispatch/testing/assertions.rb +15 -9
  161. data/lib/action_dispatch/testing/integration.rb +361 -207
  162. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  163. data/lib/action_dispatch/testing/test_process.rb +28 -19
  164. data/lib/action_dispatch/testing/test_request.rb +30 -33
  165. data/lib/action_dispatch/testing/test_response.rb +35 -11
  166. data/lib/action_dispatch.rb +42 -32
  167. data/lib/action_pack/gem_version.rb +17 -0
  168. data/lib/action_pack/version.rb +7 -7
  169. data/lib/action_pack.rb +4 -2
  170. metadata +116 -175
  171. data/lib/abstract_controller/layouts.rb +0 -423
  172. data/lib/abstract_controller/view_paths.rb +0 -96
  173. data/lib/action_controller/caching/actions.rb +0 -185
  174. data/lib/action_controller/caching/fragments.rb +0 -127
  175. data/lib/action_controller/caching/pages.rb +0 -187
  176. data/lib/action_controller/caching/sweeping.rb +0 -97
  177. data/lib/action_controller/deprecated/integration_test.rb +0 -2
  178. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  179. data/lib/action_controller/deprecated.rb +0 -3
  180. data/lib/action_controller/metal/compatibility.rb +0 -65
  181. data/lib/action_controller/metal/hide_actions.rb +0 -41
  182. data/lib/action_controller/metal/rack_delegation.rb +0 -26
  183. data/lib/action_controller/metal/responder.rb +0 -286
  184. data/lib/action_controller/metal/session_management.rb +0 -14
  185. data/lib/action_controller/middleware.rb +0 -39
  186. data/lib/action_controller/railties/paths.rb +0 -25
  187. data/lib/action_controller/record_identifier.rb +0 -85
  188. data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
  189. data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
  190. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
  191. data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
  192. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
  193. data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
  194. data/lib/action_controller/vendor/html-scanner.rb +0 -20
  195. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  196. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  197. data/lib/action_dispatch/middleware/head.rb +0 -18
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -75
  199. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  200. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
  201. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
  202. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
  203. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
  204. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
  205. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
  206. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
  207. data/lib/action_dispatch/testing/assertions/dom.rb +0 -37
  208. data/lib/action_dispatch/testing/assertions/selector.rb +0 -435
  209. data/lib/action_dispatch/testing/assertions/tag.rb +0 -138
  210. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  211. data/lib/action_view/asset_paths.rb +0 -142
  212. data/lib/action_view/base.rb +0 -220
  213. data/lib/action_view/buffers.rb +0 -43
  214. data/lib/action_view/context.rb +0 -36
  215. data/lib/action_view/flows.rb +0 -79
  216. data/lib/action_view/helpers/active_model_helper.rb +0 -50
  217. data/lib/action_view/helpers/asset_paths.rb +0 -7
  218. data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
  219. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  220. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  221. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  222. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  223. data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
  224. data/lib/action_view/helpers/cache_helper.rb +0 -64
  225. data/lib/action_view/helpers/capture_helper.rb +0 -203
  226. data/lib/action_view/helpers/controller_helper.rb +0 -25
  227. data/lib/action_view/helpers/csrf_helper.rb +0 -32
  228. data/lib/action_view/helpers/date_helper.rb +0 -1062
  229. data/lib/action_view/helpers/debug_helper.rb +0 -40
  230. data/lib/action_view/helpers/form_helper.rb +0 -1486
  231. data/lib/action_view/helpers/form_options_helper.rb +0 -658
  232. data/lib/action_view/helpers/form_tag_helper.rb +0 -685
  233. data/lib/action_view/helpers/javascript_helper.rb +0 -110
  234. data/lib/action_view/helpers/number_helper.rb +0 -622
  235. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  236. data/lib/action_view/helpers/record_tag_helper.rb +0 -111
  237. data/lib/action_view/helpers/rendering_helper.rb +0 -92
  238. data/lib/action_view/helpers/sanitize_helper.rb +0 -259
  239. data/lib/action_view/helpers/tag_helper.rb +0 -167
  240. data/lib/action_view/helpers/text_helper.rb +0 -426
  241. data/lib/action_view/helpers/translation_helper.rb +0 -91
  242. data/lib/action_view/helpers/url_helper.rb +0 -693
  243. data/lib/action_view/helpers.rb +0 -60
  244. data/lib/action_view/locale/en.yml +0 -160
  245. data/lib/action_view/log_subscriber.rb +0 -28
  246. data/lib/action_view/lookup_context.rb +0 -258
  247. data/lib/action_view/path_set.rb +0 -101
  248. data/lib/action_view/railtie.rb +0 -55
  249. data/lib/action_view/renderer/abstract_renderer.rb +0 -41
  250. data/lib/action_view/renderer/partial_renderer.rb +0 -415
  251. data/lib/action_view/renderer/renderer.rb +0 -61
  252. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
  253. data/lib/action_view/renderer/template_renderer.rb +0 -95
  254. data/lib/action_view/template/error.rb +0 -128
  255. data/lib/action_view/template/handlers/builder.rb +0 -26
  256. data/lib/action_view/template/handlers/erb.rb +0 -125
  257. data/lib/action_view/template/handlers.rb +0 -50
  258. data/lib/action_view/template/resolver.rb +0 -298
  259. data/lib/action_view/template/text.rb +0 -30
  260. data/lib/action_view/template.rb +0 -337
  261. data/lib/action_view/test_case.rb +0 -246
  262. data/lib/action_view/testing/resolvers.rb +0 -49
  263. data/lib/action_view.rb +0 -84
  264. data/lib/sprockets/assets.rake +0 -99
  265. data/lib/sprockets/bootstrap.rb +0 -37
  266. data/lib/sprockets/compressors.rb +0 -83
  267. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  268. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  269. data/lib/sprockets/helpers.rb +0 -6
  270. data/lib/sprockets/railtie.rb +0 -62
  271. data/lib/sprockets/static_compiler.rb +0 -56
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem "capybara", ">= 2.15"
4
+
5
+ require "capybara/dsl"
6
+ require "capybara/minitest"
7
+ require "action_controller"
8
+ require "action_dispatch/system_testing/driver"
9
+ require "action_dispatch/system_testing/browser"
10
+ require "action_dispatch/system_testing/server"
11
+ require "action_dispatch/system_testing/test_helpers/screenshot_helper"
12
+ require "action_dispatch/system_testing/test_helpers/setup_and_teardown"
13
+ require "action_dispatch/system_testing/test_helpers/undef_methods"
14
+
15
+ module ActionDispatch
16
+ # = System Testing
17
+ #
18
+ # System tests let you test applications in the browser. Because system
19
+ # tests use a real browser experience, you can test all of your JavaScript
20
+ # easily from your test suite.
21
+ #
22
+ # To create a system test in your application, extend your test class
23
+ # from <tt>ApplicationSystemTestCase</tt>. System tests use Capybara as a
24
+ # base and allow you to configure the settings through your
25
+ # <tt>application_system_test_case.rb</tt> file that is generated with a new
26
+ # application or scaffold.
27
+ #
28
+ # Here is an example system test:
29
+ #
30
+ # require 'application_system_test_case'
31
+ #
32
+ # class Users::CreateTest < ApplicationSystemTestCase
33
+ # test "adding a new user" do
34
+ # visit users_path
35
+ # click_on 'New User'
36
+ #
37
+ # fill_in 'Name', with: 'Arya'
38
+ # click_on 'Create User'
39
+ #
40
+ # assert_text 'Arya'
41
+ # end
42
+ # end
43
+ #
44
+ # When generating an application or scaffold, an +application_system_test_case.rb+
45
+ # file will also be generated containing the base class for system testing.
46
+ # This is where you can change the driver, add Capybara settings, and other
47
+ # configuration for your system tests.
48
+ #
49
+ # require "test_helper"
50
+ #
51
+ # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
52
+ # driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
53
+ # end
54
+ #
55
+ # By default, <tt>ActionDispatch::SystemTestCase</tt> is driven by the
56
+ # Selenium driver, with the Chrome browser, and a browser size of 1400x1400.
57
+ #
58
+ # Changing the driver configuration options is easy. Let's say you want to use
59
+ # the Firefox browser instead of Chrome. In your +application_system_test_case.rb+
60
+ # file add the following:
61
+ #
62
+ # require "test_helper"
63
+ #
64
+ # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
65
+ # driven_by :selenium, using: :firefox
66
+ # end
67
+ #
68
+ # +driven_by+ has a required argument for the driver name. The keyword
69
+ # arguments are +:using+ for the browser and +:screen_size+ to change the
70
+ # size of the browser screen. These two options are not applicable for
71
+ # headless drivers and will be silently ignored if passed.
72
+ #
73
+ # Headless browsers such as headless Chrome and headless Firefox are also supported.
74
+ # You can use these browsers by setting the +:using+ argument to +:headless_chrome+ or +:headless_firefox+.
75
+ #
76
+ # To use a headless driver, like Poltergeist, update your Gemfile to use
77
+ # Poltergeist instead of Selenium and then declare the driver name in the
78
+ # +application_system_test_case.rb+ file. In this case, you would leave out
79
+ # the +:using+ option because the driver is headless, but you can still use
80
+ # +:screen_size+ to change the size of the browser screen, also you can use
81
+ # +:options+ to pass options supported by the driver. Please refer to your
82
+ # driver documentation to learn about supported options.
83
+ #
84
+ # require "test_helper"
85
+ # require "capybara/poltergeist"
86
+ #
87
+ # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
88
+ # driven_by :poltergeist, screen_size: [1400, 1400], options:
89
+ # { js_errors: true }
90
+ # end
91
+ #
92
+ # Because <tt>ActionDispatch::SystemTestCase</tt> is a shim between Capybara
93
+ # and Rails, any driver that is supported by Capybara is supported by system
94
+ # tests as long as you include the required gems and files.
95
+ class SystemTestCase < IntegrationTest
96
+ include Capybara::DSL
97
+ include Capybara::Minitest::Assertions
98
+ include SystemTesting::TestHelpers::SetupAndTeardown
99
+ include SystemTesting::TestHelpers::ScreenshotHelper
100
+ include SystemTesting::TestHelpers::UndefMethods
101
+
102
+ def initialize(*) # :nodoc:
103
+ super
104
+ self.class.driver.use
105
+ end
106
+
107
+ def self.start_application # :nodoc:
108
+ Capybara.app = Rack::Builder.new do
109
+ map "/" do
110
+ run Rails.application
111
+ end
112
+ end
113
+
114
+ SystemTesting::Server.new.run
115
+ end
116
+
117
+ class_attribute :driver, instance_accessor: false
118
+
119
+ # System Test configuration options
120
+ #
121
+ # The default settings are Selenium, using Chrome, with a screen size
122
+ # of 1400x1400.
123
+ #
124
+ # Examples:
125
+ #
126
+ # driven_by :poltergeist
127
+ #
128
+ # driven_by :selenium, screen_size: [800, 800]
129
+ #
130
+ # driven_by :selenium, using: :chrome
131
+ #
132
+ # driven_by :selenium, using: :headless_chrome
133
+ #
134
+ # driven_by :selenium, using: :firefox
135
+ #
136
+ # driven_by :selenium, using: :headless_firefox
137
+ def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {})
138
+ self.driver = SystemTesting::Driver.new(driver, using: using, screen_size: screen_size, options: options)
139
+ end
140
+
141
+ driven_by :selenium
142
+
143
+ ActiveSupport.run_load_hooks(:action_dispatch_system_test_case, self)
144
+ end
145
+
146
+ SystemTestCase.start_application
147
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module SystemTesting
5
+ class Browser # :nodoc:
6
+ attr_reader :name
7
+
8
+ def initialize(name)
9
+ @name = name
10
+ end
11
+
12
+ def type
13
+ case name
14
+ when :headless_chrome
15
+ :chrome
16
+ when :headless_firefox
17
+ :firefox
18
+ else
19
+ name
20
+ end
21
+ end
22
+
23
+ def options
24
+ case name
25
+ when :headless_chrome
26
+ headless_chrome_browser_options
27
+ when :headless_firefox
28
+ headless_firefox_browser_options
29
+ end
30
+ end
31
+
32
+ private
33
+ def headless_chrome_browser_options
34
+ options = Selenium::WebDriver::Chrome::Options.new
35
+ options.args << "--headless"
36
+ options.args << "--disable-gpu" if Gem.win_platform?
37
+
38
+ options
39
+ end
40
+
41
+ def headless_firefox_browser_options
42
+ options = Selenium::WebDriver::Firefox::Options.new
43
+ options.args << "-headless"
44
+
45
+ options
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module SystemTesting
5
+ class Driver # :nodoc:
6
+ def initialize(name, **options)
7
+ @name = name
8
+ @browser = Browser.new(options[:using])
9
+ @screen_size = options[:screen_size]
10
+ @options = options[:options]
11
+ end
12
+
13
+ def use
14
+ register if registerable?
15
+
16
+ setup
17
+ end
18
+
19
+ private
20
+ def registerable?
21
+ [:selenium, :poltergeist, :webkit].include?(@name)
22
+ end
23
+
24
+ def register
25
+ Capybara.register_driver @name do |app|
26
+ case @name
27
+ when :selenium then register_selenium(app)
28
+ when :poltergeist then register_poltergeist(app)
29
+ when :webkit then register_webkit(app)
30
+ end
31
+ end
32
+ end
33
+
34
+ def browser_options
35
+ @options.merge(options: @browser.options).compact
36
+ end
37
+
38
+ def register_selenium(app)
39
+ Capybara::Selenium::Driver.new(app, { browser: @browser.type }.merge(browser_options)).tap do |driver|
40
+ driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
41
+ end
42
+ end
43
+
44
+ def register_poltergeist(app)
45
+ Capybara::Poltergeist::Driver.new(app, @options.merge(window_size: @screen_size))
46
+ end
47
+
48
+ def register_webkit(app)
49
+ Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver|
50
+ driver.resize_window_to(driver.current_window_handle, *@screen_size)
51
+ end
52
+ end
53
+
54
+ def setup
55
+ Capybara.current_driver = @name
56
+ end
57
+ end
58
+ end
59
+ end
@@ -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,14 +1,19 @@
1
- require 'active_support/core_ext/object/inclusion'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActionDispatch
4
4
  module Assertions
5
5
  # A small suite of assertions that test responses from \Rails applications.
6
6
  module ResponseAssertions
7
- extend ActiveSupport::Concern
7
+ RESPONSE_PREDICATES = { # :nodoc:
8
+ success: :successful?,
9
+ missing: :not_found?,
10
+ redirect: :redirection?,
11
+ error: :server_error?,
12
+ }
8
13
 
9
14
  # Asserts that the response is one of the following types:
10
15
  #
11
- # * <tt>:success</tt> - Status code was 200
16
+ # * <tt>:success</tt> - Status code was in the 200-299 range
12
17
  # * <tt>:redirect</tt> - Status code was in the 300-399 range
13
18
  # * <tt>:missing</tt> - Status code was 404
14
19
  # * <tt>:error</tt> - Status code was in the 500-599 range
@@ -17,53 +22,45 @@ module ActionDispatch
17
22
  # or its symbolic equivalent <tt>assert_response(:not_implemented)</tt>.
18
23
  # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list.
19
24
  #
20
- # ==== Examples
21
- #
22
- # # assert that the response was a redirection
25
+ # # Asserts that the response was a redirection
23
26
  # assert_response :redirect
24
27
  #
25
- # # assert that the response code was status code 401 (unauthorized)
28
+ # # Asserts that the response code was status code 401 (unauthorized)
26
29
  # assert_response 401
27
- #
28
30
  def assert_response(type, message = nil)
29
- validate_request!
31
+ message ||= generate_response_message(type)
30
32
 
31
- if type.in?([:success, :missing, :redirect, :error]) && @response.send("#{type}?")
32
- assert_block("") { true } # to count the assertion
33
- elsif type.is_a?(Fixnum) && @response.response_code == type
34
- assert_block("") { true } # to count the assertion
35
- elsif type.is_a?(Symbol) && @response.response_code == Rack::Utils::SYMBOL_TO_STATUS_CODE[type]
36
- assert_block("") { true } # to count the assertion
33
+ if RESPONSE_PREDICATES.keys.include?(type)
34
+ assert @response.send(RESPONSE_PREDICATES[type]), message
37
35
  else
38
- flunk(build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code))
36
+ assert_equal AssertionResponse.new(type).code, @response.response_code, message
39
37
  end
40
38
  end
41
39
 
42
- # Assert that the redirection options passed in match those of the redirect called in the latest action.
43
- # This match can be partial, such that <tt>assert_redirected_to(:controller => "weblog")</tt> will also
44
- # match the redirection of <tt>redirect_to(:controller => "weblog", :action => "show")</tt> and so on.
45
- #
46
- # ==== Examples
40
+ # Asserts that the redirection options passed in match those of the redirect called in the latest action.
41
+ # This match can be partial, such that <tt>assert_redirected_to(controller: "weblog")</tt> will also
42
+ # match the redirection of <tt>redirect_to(controller: "weblog", action: "show")</tt> and so on.
47
43
  #
48
- # # assert that the redirection was to the "index" action on the WeblogController
49
- # assert_redirected_to :controller => "weblog", :action => "index"
44
+ # # Asserts that the redirection was to the "index" action on the WeblogController
45
+ # assert_redirected_to controller: "weblog", action: "index"
50
46
  #
51
- # # assert that the redirection was to the named route login_url
47
+ # # Asserts that the redirection was to the named route login_url
52
48
  # assert_redirected_to login_url
53
49
  #
54
- # # assert that the redirection was to the url for @customer
50
+ # # Asserts that the redirection was to the URL for @customer
55
51
  # assert_redirected_to @customer
56
52
  #
57
- def assert_redirected_to(options = {}, message=nil)
53
+ # # Asserts that the redirection matches the regular expression
54
+ # assert_redirected_to %r(\Ahttp://example.org)
55
+ def assert_redirected_to(options = {}, message = nil)
58
56
  assert_response(:redirect, message)
59
- return true if options == @response.location
57
+ return true if options === @response.location
60
58
 
61
59
  redirect_is = normalize_argument_to_redirection(@response.location)
62
60
  redirect_expected = normalize_argument_to_redirection(options)
63
61
 
64
- if redirect_is != redirect_expected
65
- flunk(build_message(message, "Expected response to be a redirect to <?> but was a redirect to <?>", redirect_expected, redirect_is))
66
- end
62
+ message ||= "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>"
63
+ assert_operator redirect_expected, :===, redirect_is, message
67
64
  end
68
65
 
69
66
  private
@@ -73,23 +70,37 @@ module ActionDispatch
73
70
  end
74
71
 
75
72
  def normalize_argument_to_redirection(fragment)
76
- case fragment
77
- when %r{^\w[A-Za-z\d+.-]*:.*}
73
+ if Regexp === fragment
78
74
  fragment
79
- when String
80
- @request.protocol + @request.host_with_port + fragment
81
- when :back
82
- raise RedirectBackError unless refer = @request.headers["Referer"]
83
- refer
84
75
  else
85
- @controller.url_for(fragment)
86
- end.gsub(/[\0\r\n]/, '')
76
+ handle = @controller || ActionController::Redirecting
77
+ handle._compute_redirect_to_location(@request, fragment)
78
+ end
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}"
87
90
  end
88
91
 
89
- def validate_request!
90
- unless @request.is_a?(ActionDispatch::Request)
91
- raise ArgumentError, "@request must be an ActionDispatch::Request"
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]
92
101
  end
102
+
103
+ AssertionResponse.new(code_or_name).code_and_name
93
104
  end
94
105
  end
95
106
  end