capybara 3.3.0 → 3.40.0
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.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/History.md +803 -13
- data/License.txt +1 -1
- data/README.md +257 -84
- data/lib/capybara/config.rb +25 -9
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +17 -3
- data/lib/capybara/driver/node.rb +31 -6
- data/lib/capybara/dsl.rb +9 -7
- data/lib/capybara/helpers.rb +31 -7
- data/lib/capybara/minitest/spec.rb +180 -88
- data/lib/capybara/minitest.rb +262 -149
- data/lib/capybara/node/actions.rb +202 -116
- data/lib/capybara/node/base.rb +34 -19
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +10 -12
- data/lib/capybara/node/element.rb +269 -115
- data/lib/capybara/node/finders.rb +99 -77
- data/lib/capybara/node/matchers.rb +327 -151
- data/lib/capybara/node/simple.rb +48 -13
- data/lib/capybara/node/whitespace_normalizer.rb +81 -0
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +8 -9
- data/lib/capybara/queries/base_query.rb +23 -16
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +1 -0
- data/lib/capybara/queries/selector_query.rb +587 -130
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +6 -2
- data/lib/capybara/queries/text_query.rb +28 -14
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +92 -25
- data/lib/capybara/rack_test/driver.rb +16 -7
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +68 -41
- data/lib/capybara/rack_test/node.rb +106 -39
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/registration_container.rb +41 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +66 -0
- data/lib/capybara/result.rb +75 -52
- data/lib/capybara/rspec/features.rb +7 -7
- data/lib/capybara/rspec/matcher_proxies.rb +39 -18
- data/lib/capybara/rspec/matchers/base.rb +113 -0
- data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
- data/lib/capybara/rspec/matchers/compound.rb +88 -0
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
- data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +33 -0
- data/lib/capybara/rspec/matchers/have_title.rb +29 -0
- data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
- data/lib/capybara/rspec/matchers/match_style.rb +43 -0
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +141 -339
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/selector/builders/css_builder.rb +84 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
- data/lib/capybara/selector/css.rb +27 -25
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +55 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +280 -0
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +73 -25
- data/lib/capybara/selector/filters/base.rb +24 -5
- data/lib/capybara/selector/filters/expression_filter.rb +3 -3
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +16 -2
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +85 -348
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +474 -447
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +255 -143
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +93 -11
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +110 -0
- data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +76 -0
- data/lib/capybara/selenium/node.rb +436 -134
- data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +56 -19
- data/lib/capybara/server/checker.rb +9 -3
- data/lib/capybara/server/middleware.rb +28 -12
- data/lib/capybara/server.rb +33 -10
- data/lib/capybara/session/config.rb +34 -10
- data/lib/capybara/session/matchers.rb +23 -16
- data/lib/capybara/session.rb +230 -170
- data/lib/capybara/spec/public/jquery.js +5 -5
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +121 -8
- data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +127 -40
- data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
- data/lib/capybara/spec/session/assert_current_path_spec.rb +21 -18
- data/lib/capybara/spec/session/assert_selector_spec.rb +52 -58
- data/lib/capybara/spec/session/assert_style_spec.rb +7 -7
- data/lib/capybara/spec/session/assert_text_spec.rb +74 -50
- data/lib/capybara/spec/session/assert_title_spec.rb +12 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
- data/lib/capybara/spec/session/body_spec.rb +6 -6
- data/lib/capybara/spec/session/check_spec.rb +102 -47
- data/lib/capybara/spec/session/choose_spec.rb +58 -32
- data/lib/capybara/spec/session/click_button_spec.rb +219 -163
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -23
- data/lib/capybara/spec/session/click_link_spec.rb +77 -54
- data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
- data/lib/capybara/spec/session/current_url_spec.rb +38 -29
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
- data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +8 -8
- data/lib/capybara/spec/session/element/match_css_spec.rb +16 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +68 -56
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
- data/lib/capybara/spec/session/fill_in_spec.rb +101 -46
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
- data/lib/capybara/spec/session/find_field_spec.rb +32 -30
- data/lib/capybara/spec/session/find_link_spec.rb +31 -21
- data/lib/capybara/spec/session/find_spec.rb +244 -141
- data/lib/capybara/spec/session/first_spec.rb +43 -43
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +30 -18
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +45 -18
- data/lib/capybara/spec/session/go_back_spec.rb +1 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
- data/lib/capybara/spec/session/has_button_spec.rb +94 -13
- data/lib/capybara/spec/session/has_css_spec.rb +272 -132
- data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +137 -58
- data/lib/capybara/spec/session/has_link_spec.rb +44 -4
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +31 -31
- data/lib/capybara/spec/session/has_select_spec.rb +84 -50
- data/lib/capybara/spec/session/has_selector_spec.rb +111 -71
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +181 -4
- data/lib/capybara/spec/session/has_text_spec.rb +101 -53
- data/lib/capybara/spec/session/has_title_spec.rb +19 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
- data/lib/capybara/spec/session/headers_spec.rb +1 -1
- data/lib/capybara/spec/session/html_spec.rb +13 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
- data/lib/capybara/spec/session/node_spec.rb +894 -142
- data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +63 -35
- data/lib/capybara/spec/session/response_code_spec.rb +1 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +37 -37
- data/lib/capybara/spec/session/save_screenshot_spec.rb +10 -10
- data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/scroll_spec.rb +119 -0
- data/lib/capybara/spec/session/select_spec.rb +85 -85
- data/lib/capybara/spec/session/selectors_spec.rb +49 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +25 -24
- data/lib/capybara/spec/session/title_spec.rb +7 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +33 -21
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +68 -49
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +20 -16
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +6 -2
- data/lib/capybara/spec/session/window/window_spec.rb +62 -63
- data/lib/capybara/spec/session/window/windows_spec.rb +5 -1
- data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
- data/lib/capybara/spec/session/within_spec.rb +79 -42
- data/lib/capybara/spec/spec_helper.rb +41 -53
- data/lib/capybara/spec/test_app.rb +132 -43
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +139 -42
- data/lib/capybara/spec/views/frame_child.erb +4 -3
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +47 -0
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +21 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +67 -0
- data/lib/capybara/spec/views/with_animation.erb +39 -4
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +37 -9
- data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +26 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +1 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +19 -25
- data/lib/capybara.rb +126 -111
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +56 -44
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +8 -8
- data/spec/dsl_spec.rb +79 -52
- data/spec/filter_set_spec.rb +9 -9
- data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
- data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
- data/spec/minitest_spec.rb +45 -7
- data/spec/minitest_spec_spec.rb +87 -64
- data/spec/per_session_config_spec.rb +6 -6
- data/spec/rack_test_spec.rb +172 -116
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +80 -72
- data/spec/rspec/features_spec.rb +21 -16
- data/spec/rspec/scenarios_spec.rb +10 -6
- data/spec/rspec/shared_spec_matchers.rb +407 -365
- data/spec/rspec/views_spec.rb +3 -3
- data/spec/rspec_matchers_spec.rb +35 -10
- data/spec/rspec_spec.rb +63 -41
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +334 -89
- data/spec/selenium_spec_chrome.rb +176 -62
- data/spec/selenium_spec_chrome_remote.rb +54 -14
- data/spec/selenium_spec_edge.rb +41 -8
- data/spec/selenium_spec_firefox.rb +228 -0
- data/spec/selenium_spec_firefox_remote.rb +94 -0
- data/spec/selenium_spec_ie.rb +129 -11
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +171 -97
- data/spec/session_spec.rb +34 -18
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +344 -80
- data/spec/spec_helper.rb +124 -2
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +326 -28
- data/lib/capybara/rspec/compound.rb +0 -94
- data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -31
- data/lib/capybara/selenium/nodes/marionette_node.rb +0 -31
- data/lib/capybara/spec/session/has_style_spec.rb +0 -25
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
- data/spec/selenium_spec_marionette.rb +0 -167
|
@@ -3,41 +3,78 @@
|
|
|
3
3
|
module Capybara
|
|
4
4
|
class Server
|
|
5
5
|
class AnimationDisabler
|
|
6
|
+
def self.selector_for(css_or_bool)
|
|
7
|
+
case css_or_bool
|
|
8
|
+
when String
|
|
9
|
+
css_or_bool
|
|
10
|
+
when true
|
|
11
|
+
'*'
|
|
12
|
+
else
|
|
13
|
+
raise CapybaraError, 'Capybara.disable_animation supports either a String (the css selector to disable) or a boolean'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
6
17
|
def initialize(app)
|
|
7
18
|
@app = app
|
|
19
|
+
@disable_css_markup = format(DISABLE_CSS_MARKUP_TEMPLATE,
|
|
20
|
+
selector: self.class.selector_for(Capybara.disable_animation))
|
|
21
|
+
@disable_js_markup = +DISABLE_JS_MARKUP_TEMPLATE
|
|
8
22
|
end
|
|
9
23
|
|
|
10
24
|
def call(env)
|
|
11
|
-
|
|
12
|
-
return [
|
|
13
|
-
response = Rack::Response.new([], @status, @headers)
|
|
25
|
+
status, headers, body = @app.call(env)
|
|
26
|
+
return [status, headers, body] unless html_content?(headers)
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
|
|
28
|
+
nonces = directive_nonces(headers).transform_values { |nonce| "nonce=\"#{nonce}\"" if nonce && !nonce.empty? }
|
|
29
|
+
response = Rack::Response.new([], status, headers)
|
|
30
|
+
|
|
31
|
+
body.each { |html| response.write insert_disable(html, nonces) }
|
|
32
|
+
body.close if body.respond_to?(:close)
|
|
17
33
|
|
|
18
34
|
response.finish
|
|
19
35
|
end
|
|
20
36
|
|
|
21
37
|
private
|
|
22
38
|
|
|
23
|
-
|
|
24
|
-
|
|
39
|
+
attr_reader :disable_css_markup, :disable_js_markup
|
|
40
|
+
|
|
41
|
+
def html_content?(headers)
|
|
42
|
+
/html/.match?(headers['Content-Type']) # rubocop:todo Performance/StringInclude
|
|
25
43
|
end
|
|
26
44
|
|
|
27
|
-
def insert_disable(html)
|
|
28
|
-
html.sub(%r{(</head>)},
|
|
45
|
+
def insert_disable(html, nonces)
|
|
46
|
+
html.sub(%r{(</head>)}, "<style #{nonces['style-src']}>#{disable_css_markup}</style>\\1")
|
|
47
|
+
.sub(%r{(</body>)}, "<script #{nonces['script-src']}>#{disable_js_markup}</script>\\1")
|
|
29
48
|
end
|
|
30
49
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
def directive_nonces(headers)
|
|
51
|
+
headers.fetch('Content-Security-Policy', '')
|
|
52
|
+
.split(';')
|
|
53
|
+
.map(&:split) # rubocop:disable Style/MapToHash
|
|
54
|
+
.to_h do |s|
|
|
55
|
+
[
|
|
56
|
+
s[0], s[1..].filter_map do |value|
|
|
57
|
+
/^'nonce-(?<nonce>.+)'/ =~ value
|
|
58
|
+
nonce
|
|
59
|
+
end[0]
|
|
60
|
+
]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
DISABLE_CSS_MARKUP_TEMPLATE = <<~CSS
|
|
65
|
+
%<selector>s, %<selector>s::before, %<selector>s::after {
|
|
66
|
+
transition: none !important;
|
|
67
|
+
animation-duration: 0s !important;
|
|
68
|
+
animation-delay: 0s !important;
|
|
69
|
+
scroll-behavior: auto !important;
|
|
70
|
+
}
|
|
71
|
+
CSS
|
|
72
|
+
|
|
73
|
+
DISABLE_JS_MARKUP_TEMPLATE = <<~SCRIPT
|
|
74
|
+
//<![CDATA[
|
|
75
|
+
(typeof jQuery !== 'undefined') && (jQuery.fx.off = true);
|
|
76
|
+
//]]>
|
|
77
|
+
SCRIPT
|
|
41
78
|
end
|
|
42
79
|
end
|
|
43
80
|
end
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
module Capybara
|
|
4
4
|
class Server
|
|
5
5
|
class Checker
|
|
6
|
+
TRY_HTTPS_ERRORS = [EOFError, Net::ReadTimeout, Errno::ECONNRESET].freeze
|
|
7
|
+
|
|
6
8
|
def initialize(host, port)
|
|
7
9
|
@host, @port = host, port
|
|
8
10
|
@ssl = false
|
|
@@ -10,7 +12,7 @@ module Capybara
|
|
|
10
12
|
|
|
11
13
|
def request(&block)
|
|
12
14
|
ssl? ? https_request(&block) : http_request(&block)
|
|
13
|
-
rescue
|
|
15
|
+
rescue *TRY_HTTPS_ERRORS
|
|
14
16
|
res = https_request(&block)
|
|
15
17
|
@ssl = true
|
|
16
18
|
res
|
|
@@ -23,11 +25,15 @@ module Capybara
|
|
|
23
25
|
private
|
|
24
26
|
|
|
25
27
|
def http_request(&block)
|
|
26
|
-
|
|
28
|
+
make_request(read_timeout: 2, &block)
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def https_request(&block)
|
|
30
|
-
|
|
32
|
+
make_request(**ssl_options, &block)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def make_request(**options, &block)
|
|
36
|
+
Net::HTTP.start(@host, @port, options.merge(max_retries: 0), &block)
|
|
31
37
|
end
|
|
32
38
|
|
|
33
39
|
def ssl_options
|
|
@@ -4,23 +4,29 @@ module Capybara
|
|
|
4
4
|
class Server
|
|
5
5
|
class Middleware
|
|
6
6
|
class Counter
|
|
7
|
-
attr_reader :value
|
|
8
|
-
|
|
9
7
|
def initialize
|
|
10
|
-
@value =
|
|
8
|
+
@value = []
|
|
11
9
|
@mutex = Mutex.new
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
def increment
|
|
15
|
-
@mutex.synchronize { @value
|
|
12
|
+
def increment(uri)
|
|
13
|
+
@mutex.synchronize { @value.push(uri) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def decrement(uri)
|
|
17
|
+
@mutex.synchronize { @value.delete_at(@value.index(uri) || - 1) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def positive?
|
|
21
|
+
@mutex.synchronize { @value.length.positive? }
|
|
16
22
|
end
|
|
17
23
|
|
|
18
|
-
def
|
|
19
|
-
@mutex.synchronize { @value
|
|
24
|
+
def value
|
|
25
|
+
@mutex.synchronize { @value.dup }
|
|
20
26
|
end
|
|
21
27
|
end
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
attr_reader :error
|
|
24
30
|
|
|
25
31
|
def initialize(app, server_errors, extra_middleware = [])
|
|
26
32
|
@app = app
|
|
@@ -31,22 +37,32 @@ module Capybara
|
|
|
31
37
|
@server_errors = server_errors
|
|
32
38
|
end
|
|
33
39
|
|
|
40
|
+
def pending_requests
|
|
41
|
+
@counter.value
|
|
42
|
+
end
|
|
43
|
+
|
|
34
44
|
def pending_requests?
|
|
35
|
-
@counter.
|
|
45
|
+
@counter.positive?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def clear_error
|
|
49
|
+
@error = nil
|
|
36
50
|
end
|
|
37
51
|
|
|
38
52
|
def call(env)
|
|
39
|
-
if env[
|
|
53
|
+
if env['PATH_INFO'] == '/__identify__'
|
|
40
54
|
[200, {}, [@app.object_id.to_s]]
|
|
41
55
|
else
|
|
42
|
-
|
|
56
|
+
request_uri = env['REQUEST_URI']
|
|
57
|
+
@counter.increment(request_uri)
|
|
58
|
+
|
|
43
59
|
begin
|
|
44
60
|
@extended_app.call(env)
|
|
45
61
|
rescue *@server_errors => e
|
|
46
62
|
@error ||= e
|
|
47
63
|
raise e
|
|
48
64
|
ensure
|
|
49
|
-
@counter.decrement
|
|
65
|
+
@counter.decrement(request_uri)
|
|
50
66
|
end
|
|
51
67
|
end
|
|
52
68
|
end
|
data/lib/capybara/server.rb
CHANGED
|
@@ -8,6 +8,7 @@ require 'capybara/server/animation_disabler'
|
|
|
8
8
|
require 'capybara/server/checker'
|
|
9
9
|
|
|
10
10
|
module Capybara
|
|
11
|
+
# @api private
|
|
11
12
|
class Server
|
|
12
13
|
class << self
|
|
13
14
|
def ports
|
|
@@ -17,8 +18,15 @@ module Capybara
|
|
|
17
18
|
|
|
18
19
|
attr_reader :app, :port, :host
|
|
19
20
|
|
|
20
|
-
def initialize(app,
|
|
21
|
-
|
|
21
|
+
def initialize(app,
|
|
22
|
+
*deprecated_options,
|
|
23
|
+
port: Capybara.server_port,
|
|
24
|
+
host: Capybara.server_host,
|
|
25
|
+
reportable_errors: Capybara.server_errors,
|
|
26
|
+
extra_middleware: [])
|
|
27
|
+
unless deprecated_options.empty?
|
|
28
|
+
warn 'Positional arguments, other than the application, to Server#new are deprecated, please use keyword arguments'
|
|
29
|
+
end
|
|
22
30
|
@app = app
|
|
23
31
|
@extra_middleware = extra_middleware
|
|
24
32
|
@server_thread = nil # suppress warnings
|
|
@@ -31,7 +39,7 @@ module Capybara
|
|
|
31
39
|
end
|
|
32
40
|
|
|
33
41
|
def reset_error!
|
|
34
|
-
middleware.
|
|
42
|
+
middleware.clear_error
|
|
35
43
|
end
|
|
36
44
|
|
|
37
45
|
def error
|
|
@@ -44,19 +52,19 @@ module Capybara
|
|
|
44
52
|
|
|
45
53
|
def responsive?
|
|
46
54
|
return false if @server_thread&.join(0)
|
|
55
|
+
|
|
47
56
|
res = @checker.request { |http| http.get('/__identify__') }
|
|
48
57
|
|
|
49
|
-
if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
rescue SystemCallError
|
|
58
|
+
res.body == app.object_id.to_s if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
|
|
59
|
+
rescue SystemCallError, Net::ReadTimeout, OpenSSL::SSL::SSLError
|
|
53
60
|
false
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
def wait_for_pending_requests
|
|
57
64
|
timer = Capybara::Helpers.timer(expire_in: 60)
|
|
58
65
|
while pending_requests?
|
|
59
|
-
raise "Requests did not finish in 60 seconds" if timer.expired?
|
|
66
|
+
raise "Requests did not finish in 60 seconds: #{middleware.pending_requests}" if timer.expired?
|
|
67
|
+
|
|
60
68
|
sleep 0.01
|
|
61
69
|
end
|
|
62
70
|
end
|
|
@@ -71,7 +79,8 @@ module Capybara
|
|
|
71
79
|
|
|
72
80
|
timer = Capybara::Helpers.timer(expire_in: 60)
|
|
73
81
|
until responsive?
|
|
74
|
-
raise
|
|
82
|
+
raise 'Rack application timed out during boot' if timer.expired?
|
|
83
|
+
|
|
75
84
|
@server_thread.join(0.1)
|
|
76
85
|
end
|
|
77
86
|
end
|
|
@@ -79,6 +88,10 @@ module Capybara
|
|
|
79
88
|
self
|
|
80
89
|
end
|
|
81
90
|
|
|
91
|
+
def base_url
|
|
92
|
+
"http#{'s' if using_ssl?}://#{host}:#{port}"
|
|
93
|
+
end
|
|
94
|
+
|
|
82
95
|
private
|
|
83
96
|
|
|
84
97
|
def middleware
|
|
@@ -95,7 +108,17 @@ module Capybara
|
|
|
95
108
|
|
|
96
109
|
def find_available_port(host)
|
|
97
110
|
server = TCPServer.new(host, 0)
|
|
98
|
-
server.addr[1]
|
|
111
|
+
port = server.addr[1]
|
|
112
|
+
server.close
|
|
113
|
+
|
|
114
|
+
# Workaround issue where some platforms (mac, ???) when passed a host
|
|
115
|
+
# of '0.0.0.0' will return a port that is only available on one of the
|
|
116
|
+
# ip addresses that resolves to, but the next binding to that port requires
|
|
117
|
+
# that port to be available on all ips
|
|
118
|
+
server = TCPServer.new(host, port)
|
|
119
|
+
port
|
|
120
|
+
rescue Errno::EADDRINUSE
|
|
121
|
+
retry
|
|
99
122
|
ensure
|
|
100
123
|
server&.close
|
|
101
124
|
end
|
|
@@ -7,7 +7,8 @@ module Capybara
|
|
|
7
7
|
OPTIONS = %i[always_include_port run_server default_selector default_max_wait_time ignore_hidden_elements
|
|
8
8
|
automatic_reload match exact exact_text raise_server_errors visible_text_only
|
|
9
9
|
automatic_label_click enable_aria_label save_path asset_host default_host app_host
|
|
10
|
-
server_host server_port server_errors default_set_options disable_animation
|
|
10
|
+
server_host server_port server_errors default_set_options disable_animation test_id
|
|
11
|
+
predicates_wait default_normalize_ws w3c_click_offset enable_aria_role default_retry_interval].freeze
|
|
11
12
|
|
|
12
13
|
attr_accessor(*OPTIONS)
|
|
13
14
|
|
|
@@ -20,6 +21,8 @@ module Capybara
|
|
|
20
21
|
# See {Capybara.configure}
|
|
21
22
|
# @!method default_max_wait_time
|
|
22
23
|
# See {Capybara.configure}
|
|
24
|
+
# @!method default_retry_interval
|
|
25
|
+
# See {Capybara.configure}
|
|
23
26
|
# @!method ignore_hidden_elements
|
|
24
27
|
# See {Capybara.configure}
|
|
25
28
|
# @!method automatic_reload
|
|
@@ -36,6 +39,8 @@ module Capybara
|
|
|
36
39
|
# See {Capybara.configure}
|
|
37
40
|
# @!method enable_aria_label
|
|
38
41
|
# See {Capybara.configure}
|
|
42
|
+
# @!method enable_aria_role
|
|
43
|
+
# See {Capybara.configure}
|
|
39
44
|
# @!method save_path
|
|
40
45
|
# See {Capybara.configure}
|
|
41
46
|
# @!method asset_host
|
|
@@ -54,6 +59,12 @@ module Capybara
|
|
|
54
59
|
# See {Capybara.configure}
|
|
55
60
|
# @!method disable_animation
|
|
56
61
|
# See {Capybara.configure}
|
|
62
|
+
# @!method test_id
|
|
63
|
+
# See {Capybara.configure}
|
|
64
|
+
# @!method default_normalize_ws
|
|
65
|
+
# See {Capybara.configure}
|
|
66
|
+
# @!method w3c_click_offset
|
|
67
|
+
# See {Capybara.configure}
|
|
57
68
|
|
|
58
69
|
remove_method :server_host
|
|
59
70
|
|
|
@@ -72,20 +83,33 @@ module Capybara
|
|
|
72
83
|
|
|
73
84
|
remove_method :app_host=
|
|
74
85
|
def app_host=(url)
|
|
75
|
-
|
|
86
|
+
unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
|
|
87
|
+
raise ArgumentError, "Capybara.app_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}."
|
|
88
|
+
end
|
|
89
|
+
|
|
76
90
|
@app_host = url
|
|
77
91
|
end
|
|
78
92
|
|
|
79
93
|
remove_method :default_host=
|
|
80
94
|
def default_host=(url)
|
|
81
|
-
|
|
95
|
+
unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
|
|
96
|
+
raise ArgumentError, "Capybara.default_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}."
|
|
97
|
+
end
|
|
98
|
+
|
|
82
99
|
@default_host = url
|
|
83
100
|
end
|
|
84
101
|
|
|
85
|
-
remove_method :
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
remove_method :test_id=
|
|
103
|
+
##
|
|
104
|
+
#
|
|
105
|
+
# Set an attribute to be optionally matched against the locator for builtin selector types.
|
|
106
|
+
# This attribute will be checked by builtin selector types whenever id would normally be checked.
|
|
107
|
+
# If `nil` then it will be ignored.
|
|
108
|
+
#
|
|
109
|
+
# @param [String, Symbol, nil] id Name of the attribute to use as the test id
|
|
110
|
+
#
|
|
111
|
+
def test_id=(id)
|
|
112
|
+
@test_id = id&.to_sym
|
|
89
113
|
end
|
|
90
114
|
|
|
91
115
|
def initialize_copy(other)
|
|
@@ -95,9 +119,9 @@ module Capybara
|
|
|
95
119
|
end
|
|
96
120
|
|
|
97
121
|
class ReadOnlySessionConfig < SimpleDelegator
|
|
98
|
-
SessionConfig::OPTIONS.each do |
|
|
99
|
-
define_method "#{
|
|
100
|
-
raise
|
|
122
|
+
SessionConfig::OPTIONS.each do |option|
|
|
123
|
+
define_method "#{option}=" do |_|
|
|
124
|
+
raise 'Per session settings are only supported when Capybara.threadsafe == true'
|
|
101
125
|
end
|
|
102
126
|
end
|
|
103
127
|
end
|
|
@@ -6,21 +6,23 @@ module Capybara
|
|
|
6
6
|
# Asserts that the page has the given path.
|
|
7
7
|
# By default, if passed a full url this will compare against the full url,
|
|
8
8
|
# if passed a path only the path+query portion will be compared, if passed a regexp
|
|
9
|
-
# the comparison will depend on the :url option
|
|
9
|
+
# the comparison will depend on the :url option (path+query by default)
|
|
10
10
|
#
|
|
11
11
|
# @!macro current_path_query_params
|
|
12
12
|
# @overload $0(string, **options)
|
|
13
13
|
# @param string [String] The string that the current 'path' should equal
|
|
14
14
|
# @overload $0(regexp, **options)
|
|
15
15
|
# @param regexp [Regexp] The regexp that the current 'path' should match to
|
|
16
|
-
# @option options [Boolean] :url (true if `string`
|
|
16
|
+
# @option options [Boolean] :url (true if `string` is a full url, otherwise false) Whether the comparison should be done against the full current url or just the path
|
|
17
17
|
# @option options [Boolean] :ignore_query (false) Whether the query portion of the current url/path should be ignored
|
|
18
18
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for the current url/path to eq/match given string/regexp argument
|
|
19
19
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
20
20
|
# @return [true]
|
|
21
21
|
#
|
|
22
|
-
def assert_current_path(path, **options)
|
|
23
|
-
_verify_current_path(path, options)
|
|
22
|
+
def assert_current_path(path, **options, &optional_filter_block)
|
|
23
|
+
_verify_current_path(path, optional_filter_block, **options) do |query|
|
|
24
|
+
raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
|
|
25
|
+
end
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
##
|
|
@@ -33,8 +35,10 @@ module Capybara
|
|
|
33
35
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
34
36
|
# @return [true]
|
|
35
37
|
#
|
|
36
|
-
def assert_no_current_path(path, **options)
|
|
37
|
-
_verify_current_path(path, options)
|
|
38
|
+
def assert_no_current_path(path, **options, &optional_filter_block)
|
|
39
|
+
_verify_current_path(path, optional_filter_block, **options) do |query|
|
|
40
|
+
raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)
|
|
41
|
+
end
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
##
|
|
@@ -46,10 +50,8 @@ module Capybara
|
|
|
46
50
|
# @macro current_path_query_params
|
|
47
51
|
# @return [Boolean]
|
|
48
52
|
#
|
|
49
|
-
def has_current_path?(path, **options)
|
|
50
|
-
assert_current_path(path, options)
|
|
51
|
-
rescue Capybara::ExpectationNotMet
|
|
52
|
-
false
|
|
53
|
+
def has_current_path?(path, **options, &optional_filter_block)
|
|
54
|
+
make_predicate(options) { assert_current_path(path, **options, &optional_filter_block) }
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
##
|
|
@@ -61,20 +63,25 @@ module Capybara
|
|
|
61
63
|
# @macro current_path_query_params
|
|
62
64
|
# @return [Boolean]
|
|
63
65
|
#
|
|
64
|
-
def has_no_current_path?(path, **options)
|
|
65
|
-
assert_no_current_path(path, options)
|
|
66
|
-
rescue Capybara::ExpectationNotMet
|
|
67
|
-
false
|
|
66
|
+
def has_no_current_path?(path, **options, &optional_filter_block)
|
|
67
|
+
make_predicate(options) { assert_no_current_path(path, **options, &optional_filter_block) }
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
private
|
|
71
71
|
|
|
72
|
-
def _verify_current_path(path, options)
|
|
73
|
-
query = Capybara::Queries::CurrentPathQuery.new(path, options)
|
|
72
|
+
def _verify_current_path(path, filter_block, **options)
|
|
73
|
+
query = Capybara::Queries::CurrentPathQuery.new(path, **options, &filter_block)
|
|
74
74
|
document.synchronize(query.wait) do
|
|
75
75
|
yield(query)
|
|
76
76
|
end
|
|
77
77
|
true
|
|
78
78
|
end
|
|
79
|
+
|
|
80
|
+
def make_predicate(options)
|
|
81
|
+
options[:wait] = 0 unless options.key?(:wait) || config.predicates_wait
|
|
82
|
+
yield
|
|
83
|
+
rescue Capybara::ExpectationNotMet
|
|
84
|
+
false
|
|
85
|
+
end
|
|
79
86
|
end
|
|
80
87
|
end
|