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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +279 -603
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -297
- data/lib/abstract_controller/asset_paths.rb +4 -2
- data/lib/abstract_controller/base.rb +82 -52
- data/lib/abstract_controller/caching/fragments.rb +166 -0
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/abstract_controller/callbacks.rb +117 -103
- data/lib/abstract_controller/collector.rb +18 -7
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +65 -38
- data/lib/abstract_controller/logger.rb +3 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
- data/lib/abstract_controller/rendering.rb +77 -129
- data/lib/abstract_controller/translation.rb +21 -3
- data/lib/abstract_controller/url_for.rb +9 -7
- data/lib/abstract_controller.rb +12 -13
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/api.rb +149 -0
- data/lib/action_controller/base.rb +81 -40
- data/lib/action_controller/caching.rb +22 -62
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +30 -18
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +190 -47
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +3 -3
- data/lib/action_controller/metal/data_streaming.rb +40 -65
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
- data/lib/action_controller/metal/exceptions.rb +19 -12
- data/lib/action_controller/metal/flash.rb +42 -9
- data/lib/action_controller/metal/force_ssl.rb +79 -19
- data/lib/action_controller/metal/head.rb +35 -10
- data/lib/action_controller/metal/helpers.rb +31 -21
- data/lib/action_controller/metal/http_authentication.rb +182 -134
- data/lib/action_controller/metal/implicit_render.rb +62 -8
- data/lib/action_controller/metal/instrumentation.rb +28 -26
- data/lib/action_controller/metal/live.rb +312 -0
- data/lib/action_controller/metal/mime_responds.rb +159 -163
- data/lib/action_controller/metal/parameter_encoding.rb +51 -0
- data/lib/action_controller/metal/params_wrapper.rb +146 -93
- data/lib/action_controller/metal/redirecting.rb +80 -56
- data/lib/action_controller/metal/renderers.rb +119 -47
- data/lib/action_controller/metal/rendering.rb +89 -32
- data/lib/action_controller/metal/request_forgery_protection.rb +373 -41
- data/lib/action_controller/metal/rescue.rb +9 -16
- data/lib/action_controller/metal/streaming.rb +39 -45
- data/lib/action_controller/metal/strong_parameters.rb +1086 -0
- data/lib/action_controller/metal/testing.rb +8 -29
- data/lib/action_controller/metal/url_for.rb +43 -32
- data/lib/action_controller/metal.rb +112 -106
- data/lib/action_controller/railtie.rb +56 -18
- data/lib/action_controller/railties/helpers.rb +24 -0
- data/lib/action_controller/renderer.rb +117 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +402 -347
- data/lib/action_controller.rb +31 -30
- data/lib/action_dispatch/http/cache.rb +133 -34
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +40 -24
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +117 -16
- data/lib/action_dispatch/http/mime_negotiation.rb +98 -33
- data/lib/action_dispatch/http/mime_type.rb +198 -146
- data/lib/action_dispatch/http/mime_types.rb +22 -7
- data/lib/action_dispatch/http/parameter_filter.rb +61 -49
- data/lib/action_dispatch/http/parameters.rb +94 -51
- data/lib/action_dispatch/http/rack_cache.rb +4 -3
- data/lib/action_dispatch/http/request.rb +262 -117
- data/lib/action_dispatch/http/response.rb +400 -86
- data/lib/action_dispatch/http/upload.rb +66 -29
- data/lib/action_dispatch/http/url.rb +232 -60
- data/lib/action_dispatch/journey/formatter.rb +189 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
- data/lib/action_dispatch/journey/nodes/node.rb +140 -0
- data/lib/action_dispatch/journey/parser.rb +199 -0
- data/lib/action_dispatch/journey/parser.y +50 -0
- data/lib/action_dispatch/journey/parser_extras.rb +31 -0
- data/lib/action_dispatch/journey/path/pattern.rb +199 -0
- data/lib/action_dispatch/journey/route.rb +203 -0
- data/lib/action_dispatch/journey/router/utils.rb +102 -0
- data/lib/action_dispatch/journey/router.rb +156 -0
- data/lib/action_dispatch/journey/routes.rb +82 -0
- data/lib/action_dispatch/journey/scanner.rb +64 -0
- data/lib/action_dispatch/journey/visitors.rb +268 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/journey.rb +7 -0
- data/lib/action_dispatch/middleware/callbacks.rb +17 -13
- data/lib/action_dispatch/middleware/cookies.rb +494 -162
- data/lib/action_dispatch/middleware/debug_exceptions.rb +176 -53
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +103 -38
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +128 -91
- data/lib/action_dispatch/middleware/public_exceptions.rb +43 -16
- data/lib/action_dispatch/middleware/reloader.rb +6 -83
- data/lib/action_dispatch/middleware/remote_ip.rb +151 -49
- data/lib/action_dispatch/middleware/request_id.rb +19 -15
- data/lib/action_dispatch/middleware/session/abstract_store.rb +38 -34
- data/lib/action_dispatch/middleware/session/cache_store.rb +14 -9
- data/lib/action_dispatch/middleware/session/cookie_store.rb +94 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -4
- data/lib/action_dispatch/middleware/show_exceptions.rb +36 -61
- data/lib/action_dispatch/middleware/ssl.rb +150 -0
- data/lib/action_dispatch/middleware/stack.rb +33 -41
- data/lib/action_dispatch/middleware/static.rb +92 -48
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +134 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
- data/lib/action_dispatch/railtie.rb +29 -8
- data/lib/action_dispatch/request/session.rb +234 -0
- data/lib/action_dispatch/request/utils.rb +78 -0
- data/lib/action_dispatch/routing/endpoint.rb +17 -0
- data/lib/action_dispatch/routing/inspector.rb +225 -0
- data/lib/action_dispatch/routing/mapper.rb +1329 -582
- data/lib/action_dispatch/routing/polymorphic_routes.rb +237 -94
- data/lib/action_dispatch/routing/redirection.rb +120 -50
- data/lib/action_dispatch/routing/route_set.rb +545 -322
- data/lib/action_dispatch/routing/routes_proxy.rb +37 -7
- data/lib/action_dispatch/routing/url_for.rb +103 -34
- data/lib/action_dispatch/routing.rb +66 -99
- data/lib/action_dispatch/system_test_case.rb +147 -0
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +59 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +47 -0
- data/lib/action_dispatch/testing/assertions/response.rb +53 -42
- data/lib/action_dispatch/testing/assertions/routing.rb +79 -74
- data/lib/action_dispatch/testing/assertions.rb +15 -9
- data/lib/action_dispatch/testing/integration.rb +361 -207
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +28 -19
- data/lib/action_dispatch/testing/test_request.rb +30 -33
- data/lib/action_dispatch/testing/test_response.rb +35 -11
- data/lib/action_dispatch.rb +42 -32
- data/lib/action_pack/gem_version.rb +17 -0
- data/lib/action_pack/version.rb +7 -7
- data/lib/action_pack.rb +4 -2
- metadata +116 -175
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/fragments.rb +0 -127
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/integration_test.rb +0 -2
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/deprecated.rb +0 -3
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/hide_actions.rb +0 -41
- data/lib/action_controller/metal/rack_delegation.rb +0 -26
- data/lib/action_controller/metal/responder.rb +0 -286
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_controller/record_identifier.rb +0 -85
- data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_controller/vendor/html-scanner.rb +0 -20
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/params_parser.rb +0 -75
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -37
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -435
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -138
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/base.rb +0 -220
- data/lib/action_view/buffers.rb +0 -43
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/flows.rb +0 -79
- data/lib/action_view/helpers/active_model_helper.rb +0 -50
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
- data/lib/action_view/helpers/cache_helper.rb +0 -64
- data/lib/action_view/helpers/capture_helper.rb +0 -203
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1062
- data/lib/action_view/helpers/debug_helper.rb +0 -40
- data/lib/action_view/helpers/form_helper.rb +0 -1486
- data/lib/action_view/helpers/form_options_helper.rb +0 -658
- data/lib/action_view/helpers/form_tag_helper.rb +0 -685
- data/lib/action_view/helpers/javascript_helper.rb +0 -110
- data/lib/action_view/helpers/number_helper.rb +0 -622
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -111
- data/lib/action_view/helpers/rendering_helper.rb +0 -92
- data/lib/action_view/helpers/sanitize_helper.rb +0 -259
- data/lib/action_view/helpers/tag_helper.rb +0 -167
- data/lib/action_view/helpers/text_helper.rb +0 -426
- data/lib/action_view/helpers/translation_helper.rb +0 -91
- data/lib/action_view/helpers/url_helper.rb +0 -693
- data/lib/action_view/helpers.rb +0 -60
- data/lib/action_view/locale/en.yml +0 -160
- data/lib/action_view/log_subscriber.rb +0 -28
- data/lib/action_view/lookup_context.rb +0 -258
- data/lib/action_view/path_set.rb +0 -101
- data/lib/action_view/railtie.rb +0 -55
- data/lib/action_view/renderer/abstract_renderer.rb +0 -41
- data/lib/action_view/renderer/partial_renderer.rb +0 -415
- data/lib/action_view/renderer/renderer.rb +0 -61
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
- data/lib/action_view/renderer/template_renderer.rb +0 -95
- data/lib/action_view/template/error.rb +0 -128
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -125
- data/lib/action_view/template/handlers.rb +0 -50
- data/lib/action_view/template/resolver.rb +0 -298
- data/lib/action_view/template/text.rb +0 -30
- data/lib/action_view/template.rb +0 -337
- data/lib/action_view/test_case.rb +0 -246
- data/lib/action_view/testing/resolvers.rb +0 -49
- data/lib/action_view.rb +0 -84
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/railtie.rb +0 -62
- 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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
# #
|
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
|
-
|
31
|
+
message ||= generate_response_message(type)
|
30
32
|
|
31
|
-
if
|
32
|
-
|
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
|
-
|
36
|
+
assert_equal AssertionResponse.new(type).code, @response.response_code, message
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
42
|
-
#
|
43
|
-
# This match can be partial, such that <tt>assert_redirected_to(:
|
44
|
-
# match the redirection of <tt>redirect_to(:
|
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
|
-
# #
|
49
|
-
# assert_redirected_to :
|
44
|
+
# # Asserts that the redirection was to the "index" action on the WeblogController
|
45
|
+
# assert_redirected_to controller: "weblog", action: "index"
|
50
46
|
#
|
51
|
-
# #
|
47
|
+
# # Asserts that the redirection was to the named route login_url
|
52
48
|
# assert_redirected_to login_url
|
53
49
|
#
|
54
|
-
# #
|
50
|
+
# # Asserts that the redirection was to the URL for @customer
|
55
51
|
# assert_redirected_to @customer
|
56
52
|
#
|
57
|
-
|
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
|
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
|
-
|
65
|
-
|
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
|
-
|
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
|
86
|
-
|
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
|
90
|
-
unless @
|
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]
|
92
101
|
end
|
102
|
+
|
103
|
+
AssertionResponse.new(code_or_name).code_and_name
|
93
104
|
end
|
94
105
|
end
|
95
106
|
end
|