capybara 3.13.2 → 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 +587 -16
- data/README.md +240 -90
- data/lib/capybara/config.rb +24 -11
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +8 -0
- data/lib/capybara/driver/node.rb +20 -4
- data/lib/capybara/dsl.rb +5 -3
- data/lib/capybara/helpers.rb +25 -4
- data/lib/capybara/minitest/spec.rb +174 -90
- data/lib/capybara/minitest.rb +256 -142
- data/lib/capybara/node/actions.rb +123 -77
- data/lib/capybara/node/base.rb +20 -12
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +223 -117
- data/lib/capybara/node/finders.rb +81 -71
- data/lib/capybara/node/matchers.rb +271 -134
- data/lib/capybara/node/simple.rb +18 -5
- 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 +3 -2
- data/lib/capybara/queries/current_path_query.rb +15 -5
- data/lib/capybara/queries/selector_query.rb +364 -54
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +2 -2
- data/lib/capybara/queries/text_query.rb +13 -1
- data/lib/capybara/queries/title_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +76 -11
- data/lib/capybara/rack_test/driver.rb +10 -5
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +31 -9
- data/lib/capybara/rack_test/node.rb +74 -23
- 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 +44 -20
- data/lib/capybara/rspec/matcher_proxies.rb +13 -11
- data/lib/capybara/rspec/matchers/base.rb +31 -16
- data/lib/capybara/rspec/matchers/compound.rb +1 -1
- 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 +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +21 -21
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +4 -4
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +7 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +111 -68
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/selector/builders/css_builder.rb +11 -7
- data/lib/capybara/selector/builders/xpath_builder.rb +5 -3
- data/lib/capybara/selector/css.rb +11 -9
- 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_set.rb +19 -18
- data/lib/capybara/selector/filters/base.rb +11 -2
- data/lib/capybara/selector/filters/locator_filter.rb +13 -3
- data/lib/capybara/selector/regexp_disassembler.rb +11 -7
- data/lib/capybara/selector/selector.rb +50 -440
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +473 -482
- 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 +174 -62
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +74 -18
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +37 -3
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
- 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 +68 -45
- data/lib/capybara/selenium/extensions/html5_drag.rb +192 -22
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/node.rb +268 -72
- data/lib/capybara/selenium/nodes/chrome_node.rb +105 -9
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +51 -61
- 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 +1 -1
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +43 -21
- data/lib/capybara/server/checker.rb +6 -2
- data/lib/capybara/server/middleware.rb +25 -13
- data/lib/capybara/server.rb +20 -4
- data/lib/capybara/session/config.rb +15 -11
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/session.rb +162 -131
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +105 -6
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +89 -15
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
- data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
- data/lib/capybara/spec/session/attach_file_spec.rb +64 -31
- data/lib/capybara/spec/session/check_spec.rb +26 -4
- data/lib/capybara/spec/session/choose_spec.rb +14 -2
- data/lib/capybara/spec/session/click_button_spec.rb +109 -61
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/click_link_spec.rb +23 -1
- data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
- data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +46 -5
- data/lib/capybara/spec/session/find_link_spec.rb +10 -0
- data/lib/capybara/spec/session/find_spec.rb +80 -7
- data/lib/capybara/spec/session/first_spec.rb +2 -2
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
- data/lib/capybara/spec/session/has_button_spec.rb +81 -0
- data/lib/capybara/spec/session/has_css_spec.rb +45 -8
- data/lib/capybara/spec/session/has_current_path_spec.rb +22 -7
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +59 -1
- data/lib/capybara/spec/session/has_link_spec.rb +40 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
- data/lib/capybara/spec/session/has_select_spec.rb +42 -8
- data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +177 -0
- data/lib/capybara/spec/session/has_text_spec.rb +31 -3
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +6 -4
- data/lib/capybara/spec/session/node_spec.rb +697 -23
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +21 -7
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/scroll_spec.rb +9 -7
- data/lib/capybara/spec/session/select_spec.rb +5 -10
- data/lib/capybara/spec/session/selectors_spec.rb +24 -3
- data/lib/capybara/spec/session/uncheck_spec.rb +3 -3
- data/lib/capybara/spec/session/unselect_spec.rb +1 -1
- data/lib/capybara/spec/session/visit_spec.rb +20 -0
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +54 -57
- data/lib/capybara/spec/session/window/windows_spec.rb +2 -2
- data/lib/capybara/spec/session/within_spec.rb +36 -0
- data/lib/capybara/spec/spec_helper.rb +30 -19
- data/lib/capybara/spec/test_app.rb +122 -34
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +86 -8
- data/lib/capybara/spec/views/frame_child.erb +3 -2
- 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 +10 -10
- 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 +2 -1
- 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 +34 -6
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +7 -4
- 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 +14 -18
- data/lib/capybara.rb +91 -126
- data/spec/basic_node_spec.rb +30 -16
- data/spec/capybara_spec.rb +40 -28
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +3 -1
- data/spec/css_splitter_spec.rb +1 -1
- data/spec/dsl_spec.rb +33 -22
- data/spec/filter_set_spec.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_failure.rb +3 -3
- data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
- data/spec/minitest_spec.rb +24 -2
- data/spec/minitest_spec_spec.rb +60 -45
- data/spec/per_session_config_spec.rb +1 -1
- data/spec/rack_test_spec.rb +131 -98
- data/spec/regexp_dissassembler_spec.rb +53 -39
- data/spec/result_spec.rb +68 -66
- data/spec/rspec/features_spec.rb +9 -4
- data/spec/rspec/scenarios_spec.rb +6 -2
- data/spec/rspec/shared_spec_matchers.rb +137 -98
- data/spec/rspec_matchers_spec.rb +25 -0
- data/spec/rspec_spec.rb +23 -21
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +77 -21
- data/spec/selenium_spec_chrome.rb +141 -39
- data/spec/selenium_spec_chrome_remote.rb +32 -17
- data/spec/selenium_spec_edge.rb +36 -8
- data/spec/selenium_spec_firefox.rb +110 -68
- data/spec/selenium_spec_firefox_remote.rb +22 -15
- data/spec/selenium_spec_ie.rb +29 -22
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +153 -81
- data/spec/session_spec.rb +11 -4
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +179 -74
- data/spec/spec_helper.rb +80 -5
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +3 -1
- metadata +218 -30
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
data/lib/capybara.rb
CHANGED
@@ -5,6 +5,7 @@ require 'nokogiri'
|
|
5
5
|
require 'xpath'
|
6
6
|
require 'forwardable'
|
7
7
|
require 'capybara/config'
|
8
|
+
require 'capybara/registration_container'
|
8
9
|
|
9
10
|
module Capybara
|
10
11
|
class CapybaraError < StandardError; end
|
@@ -38,7 +39,7 @@ module Capybara
|
|
38
39
|
# See {Capybara.configure}
|
39
40
|
# @!method javascript_driver
|
40
41
|
# See {Capybara.configure}
|
41
|
-
# @!method
|
42
|
+
# @!method use_html5_parsing
|
42
43
|
# See {Capybara.configure}
|
43
44
|
Config::OPTIONS.each do |method|
|
44
45
|
def_delegators :config, method, "#{method}="
|
@@ -66,36 +67,49 @@ module Capybara
|
|
66
67
|
# config.app_host = 'http://www.google.com'
|
67
68
|
# end
|
68
69
|
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
70
|
+
# #### Configurable options
|
71
|
+
#
|
72
|
+
# - **use_html5_parsing** (Boolean = `false`) - When Nokogiri >= 1.12.0 or `nokogumbo` is installed, whether HTML5 parsing will be used for HTML strings.
|
73
|
+
# - **always_include_port** (Boolean = `false`) - Whether the Rack server's port should automatically be inserted into every visited URL
|
74
|
+
# unless another port is explicitly specified.
|
75
|
+
# - **app_host** (String, `nil`) - The default host to use when giving a relative URL to visit, must be a valid URL e.g. `http://www.example.com`.
|
76
|
+
# - **asset_host** (String = `nil`) - Where dynamic assets are hosted - will be prepended to relative asset locations if present.
|
77
|
+
# - **automatic_label_click** (Boolean = `false`) - Whether {Capybara::Node::Element#choose Element#choose}, {Capybara::Node::Element#check Element#check},
|
78
|
+
# {Capybara::Node::Element#uncheck Element#uncheck} will attempt to click the associated `<label>` element if the checkbox/radio button are non-visible.
|
79
|
+
# - **automatic_reload** (Boolean = `true`) - Whether to automatically reload elements as Capybara is waiting.
|
80
|
+
# - **default_max_wait_time** (Numeric = `2`) - The maximum number of seconds to wait for asynchronous processes to finish.
|
81
|
+
# - **default_normalize_ws** (Boolean = `false`) - Whether text predicates and matchers use normalize whitespace behavior.
|
82
|
+
# - **default_retry_interval** (Numeric = `0.01`) - The number of seconds to delay the next check in asynchronous processes.
|
83
|
+
# - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
|
84
|
+
# - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
|
85
|
+
# - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
|
86
|
+
# - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).
|
87
|
+
# - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions
|
88
|
+
# written using the `XPath#is` method.
|
89
|
+
# - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.
|
90
|
+
# - **ignore_hidden_elements** (Boolean = `true`) - Whether to ignore hidden elements on the page.
|
91
|
+
# - **match** (`:one`, `:first`, `:prefer_exact`, `:smart` = `:smart`) - The matching strategy to find nodes.
|
92
|
+
# - **predicates_wait** (Boolean = `true`) - Whether Capybara's predicate matchers use waiting behavior by default.
|
93
|
+
# - **raise_server_errors** (Boolean = `true`) - Should errors raised in the server be raised in the tests?
|
94
|
+
# - **reuse_server** (Boolean = `true`) - Whether to reuse the server thread between multiple sessions using the same app object.
|
95
|
+
# - **run_server** (Boolean = `true`) - Whether to start a Rack server for the given Rack app.
|
96
|
+
# - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},
|
97
|
+
# {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
|
98
|
+
# - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
|
99
|
+
# - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
|
100
|
+
# - **server_host** (String = "127.0.0.1") - The IP address Capybara will bind the application server to. If the test application is to be accessed from an external host, you will want to change this to "0.0.0.0" or to a more specific IP address that your test client can reach.
|
101
|
+
# - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
|
102
|
+
# and {configure raise_server_errors} is `true`.
|
103
|
+
# - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
|
104
|
+
# - **threadsafe** (Boolean = `false`) - Whether sessions can be configured individually.
|
105
|
+
# - **w3c_click_offset** (Boolean = 'true') - Whether click offsets should be from element center (true) or top left (false)
|
106
|
+
#
|
107
|
+
# #### DSL Options
|
108
|
+
#
|
109
|
+
# When using `capybara/dsl`, the following options are also available:
|
110
|
+
#
|
111
|
+
# - **default_driver** (Symbol = `:rack_test`) - The name of the driver to use by default.
|
112
|
+
# - **javascript_driver** (Symbol = `:selenium`) - The name of a driver to use for JavaScript enabled tests.
|
99
113
|
#
|
100
114
|
def configure
|
101
115
|
yield config
|
@@ -115,7 +129,7 @@ module Capybara
|
|
115
129
|
# @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
|
116
130
|
#
|
117
131
|
def register_driver(name, &block)
|
118
|
-
drivers
|
132
|
+
drivers.send(:register, name, block)
|
119
133
|
end
|
120
134
|
|
121
135
|
##
|
@@ -134,7 +148,7 @@ module Capybara
|
|
134
148
|
# @yieldparam host The host/ip to bind to
|
135
149
|
#
|
136
150
|
def register_server(name, &block)
|
137
|
-
servers
|
151
|
+
servers.send(:register, name.to_sym, block)
|
138
152
|
end
|
139
153
|
|
140
154
|
##
|
@@ -188,11 +202,11 @@ module Capybara
|
|
188
202
|
end
|
189
203
|
|
190
204
|
def drivers
|
191
|
-
@drivers ||=
|
205
|
+
@drivers ||= RegistrationContainer.new
|
192
206
|
end
|
193
207
|
|
194
208
|
def servers
|
195
|
-
@servers ||=
|
209
|
+
@servers ||= RegistrationContainer.new
|
196
210
|
end
|
197
211
|
|
198
212
|
# Wraps the given string, which should contain an HTML document or fragment
|
@@ -201,15 +215,13 @@ module Capybara
|
|
201
215
|
# any string containing HTML in the exact same way you would query the current document in a Capybara
|
202
216
|
# session.
|
203
217
|
#
|
204
|
-
#
|
205
|
-
#
|
218
|
+
# @example A single element
|
206
219
|
# node = Capybara.string('<a href="foo">bar</a>')
|
207
220
|
# anchor = node.first('a')
|
208
221
|
# anchor[:href] #=> 'foo'
|
209
222
|
# anchor.text #=> 'bar'
|
210
223
|
#
|
211
|
-
#
|
212
|
-
#
|
224
|
+
# @example Multiple elements
|
213
225
|
# node = Capybara.string <<-HTML
|
214
226
|
# <ul>
|
215
227
|
# <li id="home">Home</li>
|
@@ -248,7 +260,7 @@ module Capybara
|
|
248
260
|
#
|
249
261
|
def current_driver
|
250
262
|
if threadsafe
|
251
|
-
Thread.current
|
263
|
+
Thread.current.thread_variable_get :capybara_current_driver
|
252
264
|
else
|
253
265
|
@current_driver
|
254
266
|
end || default_driver
|
@@ -257,7 +269,7 @@ module Capybara
|
|
257
269
|
|
258
270
|
def current_driver=(name)
|
259
271
|
if threadsafe
|
260
|
-
Thread.current
|
272
|
+
Thread.current.thread_variable_set :capybara_current_driver, name
|
261
273
|
else
|
262
274
|
@current_driver = name
|
263
275
|
end
|
@@ -297,7 +309,7 @@ module Capybara
|
|
297
309
|
|
298
310
|
##
|
299
311
|
#
|
300
|
-
# The current Capybara::Session based on what is set as
|
312
|
+
# The current {Capybara::Session} based on what is set as {app} and {current_driver}.
|
301
313
|
#
|
302
314
|
# @return [Capybara::Session] The currently used session
|
303
315
|
#
|
@@ -324,7 +336,8 @@ module Capybara
|
|
324
336
|
#
|
325
337
|
def session_name
|
326
338
|
if threadsafe
|
327
|
-
Thread.current
|
339
|
+
Thread.current.thread_variable_get(:capybara_session_name) ||
|
340
|
+
Thread.current.thread_variable_set(:capybara_session_name, :default)
|
328
341
|
else
|
329
342
|
@session_name ||= :default
|
330
343
|
end
|
@@ -332,7 +345,7 @@ module Capybara
|
|
332
345
|
|
333
346
|
def session_name=(name)
|
334
347
|
if threadsafe
|
335
|
-
Thread.current
|
348
|
+
Thread.current.thread_variable_set :capybara_session_name, name
|
336
349
|
else
|
337
350
|
@session_name = name
|
338
351
|
end
|
@@ -340,9 +353,10 @@ module Capybara
|
|
340
353
|
|
341
354
|
##
|
342
355
|
#
|
343
|
-
# Yield a block using a specific session name or Capybara::Session instance.
|
356
|
+
# Yield a block using a specific session name or {Capybara::Session} instance.
|
344
357
|
#
|
345
|
-
def using_session(name_or_session)
|
358
|
+
def using_session(name_or_session, &block)
|
359
|
+
previous_session = current_session
|
346
360
|
previous_session_info = {
|
347
361
|
specified_session: specified_session,
|
348
362
|
session_name: session_name,
|
@@ -355,7 +369,12 @@ module Capybara
|
|
355
369
|
else
|
356
370
|
self.session_name = name_or_session
|
357
371
|
end
|
358
|
-
|
372
|
+
|
373
|
+
if block.arity.zero?
|
374
|
+
yield
|
375
|
+
else
|
376
|
+
yield current_session, previous_session
|
377
|
+
end
|
359
378
|
ensure
|
360
379
|
self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
|
361
380
|
self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
|
@@ -369,18 +388,21 @@ module Capybara
|
|
369
388
|
# @return [Nokogiri::HTML::Document] HTML document
|
370
389
|
#
|
371
390
|
def HTML(html) # rubocop:disable Naming/MethodName
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
# The Nokogumbo HTML5 parser already returns spec compliant contents
|
376
|
-
textarea['_capybara_raw_value'] = textarea.content
|
377
|
-
end
|
378
|
-
end
|
391
|
+
# Nokogiri >= 1.12.0 or Nokogumbo installed and allowed for use
|
392
|
+
html_parser, using_html5 = if defined?(Nokogiri::HTML5) && Capybara.use_html5_parsing
|
393
|
+
[Nokogiri::HTML5, true]
|
379
394
|
else
|
380
|
-
Nokogiri::
|
381
|
-
|
382
|
-
|
383
|
-
|
395
|
+
[defined?(Nokogiri::HTML4) ? Nokogiri::HTML4 : Nokogiri::HTML, false]
|
396
|
+
end
|
397
|
+
|
398
|
+
html_parser.parse(html).tap do |document|
|
399
|
+
document.xpath('//template').each do |template|
|
400
|
+
# template elements content is not part of the document
|
401
|
+
template.inner_html = ''
|
402
|
+
end
|
403
|
+
document.xpath('//textarea').each do |textarea|
|
404
|
+
# The Nokogiri HTML5 parser already returns spec compliant contents
|
405
|
+
textarea['_capybara_raw_value'] = using_html5 ? textarea.content : textarea.content.delete_prefix("\n")
|
384
406
|
end
|
385
407
|
end
|
386
408
|
end
|
@@ -403,7 +425,7 @@ module Capybara
|
|
403
425
|
|
404
426
|
def specified_session
|
405
427
|
if threadsafe
|
406
|
-
Thread.current
|
428
|
+
Thread.current.thread_variable_get :capybara_specified_session
|
407
429
|
else
|
408
430
|
@specified_session ||= nil
|
409
431
|
end
|
@@ -411,7 +433,7 @@ module Capybara
|
|
411
433
|
|
412
434
|
def specified_session=(session)
|
413
435
|
if threadsafe
|
414
|
-
Thread.current
|
436
|
+
Thread.current.thread_variable_set :capybara_specified_session, session
|
415
437
|
else
|
416
438
|
@specified_session = session
|
417
439
|
end
|
@@ -443,6 +465,7 @@ module Capybara
|
|
443
465
|
require 'capybara/queries/ancestor_query'
|
444
466
|
require 'capybara/queries/sibling_query'
|
445
467
|
require 'capybara/queries/style_query'
|
468
|
+
require 'capybara/queries/active_element_query'
|
446
469
|
|
447
470
|
require 'capybara/node/finders'
|
448
471
|
require 'capybara/node/matchers'
|
@@ -460,48 +483,14 @@ module Capybara
|
|
460
483
|
require 'capybara/rack_test/node'
|
461
484
|
require 'capybara/rack_test/form'
|
462
485
|
require 'capybara/rack_test/browser'
|
463
|
-
require 'capybara/rack_test/css_handlers
|
486
|
+
require 'capybara/rack_test/css_handlers'
|
464
487
|
|
465
488
|
require 'capybara/selenium/node'
|
466
489
|
require 'capybara/selenium/driver'
|
467
490
|
end
|
468
491
|
|
469
|
-
|
470
|
-
|
471
|
-
end
|
472
|
-
|
473
|
-
Capybara.register_server :webrick do |app, port, host, **options|
|
474
|
-
require 'rack/handler/webrick'
|
475
|
-
options = { Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log.new(nil, 0) }.merge(options)
|
476
|
-
Rack::Handler::WEBrick.run(app, options)
|
477
|
-
end
|
478
|
-
|
479
|
-
Capybara.register_server :puma do |app, port, host, **options|
|
480
|
-
begin
|
481
|
-
require 'rack/handler/puma'
|
482
|
-
rescue LoadError
|
483
|
-
raise LoadError, 'Capybara is unable to load `puma` for its server, please add `puma` to your project or specify a different server via something like `Capybara.server = :webrick`.'
|
484
|
-
else
|
485
|
-
unless Rack::Handler::Puma.respond_to?(:config)
|
486
|
-
raise LoadError, 'Capybara requires `puma` version 3.8.0 or higher, please upgrade `puma` or register and specify your own server block'
|
487
|
-
end
|
488
|
-
end
|
489
|
-
# If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.
|
490
|
-
# Therefore construct and run the Server instance ourselves.
|
491
|
-
# Rack::Handler::Puma.run(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
492
|
-
options = { Host: host, Port: port, Threads: '0:4', workers: 0, daemon: false }.merge(options)
|
493
|
-
conf = Rack::Handler::Puma.config(app, options)
|
494
|
-
events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
|
495
|
-
|
496
|
-
events.log 'Capybara starting Puma...'
|
497
|
-
events.log "* Version #{Puma::Const::PUMA_VERSION} , codename: #{Puma::Const::CODE_NAME}"
|
498
|
-
events.log "* Min threads: #{conf.options[:min_threads]}, max threads: #{conf.options[:max_threads]}"
|
499
|
-
|
500
|
-
Puma::Server.new(conf.app, events, conf.options).tap do |s|
|
501
|
-
s.binder.parse conf.options[:binds], s.events
|
502
|
-
s.min_threads, s.max_threads = conf.options[:min_threads], conf.options[:max_threads]
|
503
|
-
end.run.join
|
504
|
-
end
|
492
|
+
require 'capybara/registrations/servers'
|
493
|
+
require 'capybara/registrations/drivers'
|
505
494
|
|
506
495
|
Capybara.configure do |config|
|
507
496
|
config.always_include_port = false
|
@@ -509,6 +498,7 @@ Capybara.configure do |config|
|
|
509
498
|
config.server = :default
|
510
499
|
config.default_selector = :css
|
511
500
|
config.default_max_wait_time = 2
|
501
|
+
config.default_retry_interval = 0.01
|
512
502
|
config.ignore_hidden_elements = true
|
513
503
|
config.default_host = 'http://www.example.com'
|
514
504
|
config.automatic_reload = true
|
@@ -516,41 +506,16 @@ Capybara.configure do |config|
|
|
516
506
|
config.exact = false
|
517
507
|
config.exact_text = false
|
518
508
|
config.raise_server_errors = true
|
519
|
-
config.server_errors = [
|
509
|
+
config.server_errors = [Exception]
|
520
510
|
config.visible_text_only = false
|
521
511
|
config.automatic_label_click = false
|
522
512
|
config.enable_aria_label = false
|
513
|
+
config.enable_aria_role = false
|
523
514
|
config.reuse_server = true
|
524
515
|
config.default_set_options = {}
|
525
516
|
config.test_id = nil
|
526
517
|
config.predicates_wait = true
|
527
518
|
config.default_normalize_ws = false
|
528
|
-
config.
|
529
|
-
|
530
|
-
|
531
|
-
Capybara.register_driver :rack_test do |app|
|
532
|
-
Capybara::RackTest::Driver.new(app)
|
533
|
-
end
|
534
|
-
|
535
|
-
Capybara.register_driver :selenium do |app|
|
536
|
-
Capybara::Selenium::Driver.new(app)
|
537
|
-
end
|
538
|
-
|
539
|
-
Capybara.register_driver :selenium_headless do |app|
|
540
|
-
Capybara::Selenium::Driver.load_selenium
|
541
|
-
browser_options = ::Selenium::WebDriver::Firefox::Options.new
|
542
|
-
browser_options.args << '-headless'
|
543
|
-
Capybara::Selenium::Driver.new(app, browser: :firefox, options: browser_options)
|
544
|
-
end
|
545
|
-
|
546
|
-
Capybara.register_driver :selenium_chrome do |app|
|
547
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome)
|
548
|
-
end
|
549
|
-
|
550
|
-
Capybara.register_driver :selenium_chrome_headless do |app|
|
551
|
-
Capybara::Selenium::Driver.load_selenium
|
552
|
-
browser_options = ::Selenium::WebDriver::Chrome::Options.new
|
553
|
-
browser_options.args << '--headless'
|
554
|
-
browser_options.args << '--disable-gpu' if Gem.win_platform?
|
555
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
|
519
|
+
config.use_html5_parsing = false
|
520
|
+
config.w3c_click_offset = true
|
556
521
|
end
|
data/spec/basic_node_spec.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe Capybara do
|
6
|
+
include Capybara::RSpecMatchers
|
6
7
|
describe '.string' do
|
7
8
|
let :string do
|
8
|
-
|
9
|
+
described_class.string <<-STRING
|
9
10
|
<html>
|
10
11
|
<head>
|
11
12
|
<title>simple_node</title>
|
@@ -52,7 +53,7 @@ RSpec.describe Capybara do
|
|
52
53
|
end
|
53
54
|
|
54
55
|
it 'allows using custom matchers' do
|
55
|
-
|
56
|
+
described_class.add_selector :lifeform do
|
56
57
|
xpath { |name| ".//option[contains(.,'#{name}')]" }
|
57
58
|
end
|
58
59
|
expect(string).to have_selector(:id, 'page')
|
@@ -62,7 +63,7 @@ RSpec.describe Capybara do
|
|
62
63
|
end
|
63
64
|
|
64
65
|
it 'allows custom matcher using css' do
|
65
|
-
|
66
|
+
described_class.add_selector :section do
|
66
67
|
css { |css_class| "section .#{css_class}" }
|
67
68
|
end
|
68
69
|
expect(string).to have_selector(:section, 'subsection')
|
@@ -110,15 +111,28 @@ RSpec.describe Capybara do
|
|
110
111
|
expect(string.find('//form/input[@name="meh"]')).not_to be_disabled
|
111
112
|
end
|
112
113
|
|
114
|
+
it 'allows finding siblings' do
|
115
|
+
h1 = string.find(:css, 'h1')
|
116
|
+
expect(h1).to have_sibling(:css, 'p', text: 'Yes it is')
|
117
|
+
expect(h1).not_to have_sibling(:css, 'p', text: 'Jonas Nicklas')
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'allows finding ancestor' do
|
121
|
+
h1 = string.find(:css, 'h1')
|
122
|
+
expect(h1).to have_ancestor(:css, '#content')
|
123
|
+
expect(h1).not_to have_ancestor(:css, '#footer')
|
124
|
+
end
|
125
|
+
|
113
126
|
it 'drops illegal fragments when using gumbo' do
|
114
127
|
skip 'libxml is less strict than Gumbo' unless Nokogiri.respond_to?(:HTML5)
|
115
|
-
|
128
|
+
described_class.use_html5_parsing = true
|
129
|
+
expect(described_class.string('<td>1</td>')).not_to have_css('td')
|
116
130
|
end
|
117
131
|
|
118
|
-
it 'can disable use of
|
119
|
-
skip "Test doesn't make sense unlesss
|
120
|
-
|
121
|
-
expect(
|
132
|
+
it 'can disable use of HTML5 parsing' do
|
133
|
+
skip "Test doesn't make sense unlesss HTML5 parsing is loaded (Nokogumbo or Nokogiri >= 1.12.0)" unless Nokogiri.respond_to?(:HTML5)
|
134
|
+
described_class.use_html5_parsing = false
|
135
|
+
expect(described_class.string('<td>1</td>')).to have_css('td')
|
122
136
|
end
|
123
137
|
|
124
138
|
describe '#title' do
|
@@ -129,25 +143,25 @@ RSpec.describe Capybara do
|
|
129
143
|
|
130
144
|
describe '#has_title?' do
|
131
145
|
it 'returns whether the page has the given title' do
|
132
|
-
expect(string.has_title?('simple_node')).to
|
133
|
-
expect(string.has_title?('monkey')).to
|
146
|
+
expect(string.has_title?('simple_node')).to be true
|
147
|
+
expect(string.has_title?('monkey')).to be false
|
134
148
|
end
|
135
149
|
|
136
150
|
it 'allows regexp matches' do
|
137
|
-
expect(string.has_title?(/s[a-z]+_node/)).to
|
138
|
-
expect(string.has_title?(/monkey/)).to
|
151
|
+
expect(string.has_title?(/s[a-z]+_node/)).to be true
|
152
|
+
expect(string.has_title?(/monkey/)).to be false
|
139
153
|
end
|
140
154
|
end
|
141
155
|
|
142
156
|
describe '#has_no_title?' do
|
143
157
|
it 'returns whether the page does not have the given title' do
|
144
|
-
expect(string.has_no_title?('simple_node')).to
|
145
|
-
expect(string.has_no_title?('monkey')).to
|
158
|
+
expect(string.has_no_title?('simple_node')).to be false
|
159
|
+
expect(string.has_no_title?('monkey')).to be true
|
146
160
|
end
|
147
161
|
|
148
162
|
it 'allows regexp matches' do
|
149
|
-
expect(string.has_no_title?(/s[a-z]+_node/)).to
|
150
|
-
expect(string.has_no_title?(/monkey/)).to
|
163
|
+
expect(string.has_no_title?(/s[a-z]+_node/)).to be false
|
164
|
+
expect(string.has_no_title?(/monkey/)).to be true
|
151
165
|
end
|
152
166
|
end
|
153
167
|
end
|
data/spec/capybara_spec.rb
CHANGED
@@ -4,20 +4,32 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
RSpec.describe Capybara do
|
6
6
|
describe 'default_max_wait_time' do
|
7
|
-
|
8
|
-
|
7
|
+
before { @previous_default_time = described_class.default_max_wait_time }
|
8
|
+
|
9
|
+
after { described_class.default_max_wait_time = @previous_default_time } # rubocop:disable RSpec/InstanceVariable
|
10
|
+
|
11
|
+
it 'should be changeable' do
|
12
|
+
expect(described_class.default_max_wait_time).not_to eq(5)
|
13
|
+
described_class.default_max_wait_time = 5
|
14
|
+
expect(described_class.default_max_wait_time).to eq(5)
|
9
15
|
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'default_retry_interval' do
|
19
|
+
before { @previous_default_interval = described_class.default_retry_interval }
|
20
|
+
|
21
|
+
after { described_class.default_retry_interval = @previous_default_interval } # rubocop:disable RSpec/InstanceVariable
|
10
22
|
|
11
23
|
it 'should be changeable' do
|
12
|
-
|
13
|
-
|
14
|
-
expect(
|
24
|
+
expect(described_class.default_retry_interval).not_to eq(0.1)
|
25
|
+
described_class.default_retry_interval = 0.1
|
26
|
+
expect(described_class.default_retry_interval).to eq(0.1)
|
15
27
|
end
|
16
28
|
end
|
17
29
|
|
18
30
|
describe '.register_driver' do
|
19
31
|
it 'should add a new driver' do
|
20
|
-
|
32
|
+
described_class.register_driver :schmoo do |app|
|
21
33
|
Capybara::RackTest::Driver.new(app)
|
22
34
|
end
|
23
35
|
session = Capybara::Session.new(:schmoo, TestApp)
|
@@ -28,85 +40,85 @@ RSpec.describe Capybara do
|
|
28
40
|
|
29
41
|
describe '.register_server' do
|
30
42
|
it 'should add a new server' do
|
31
|
-
|
43
|
+
described_class.register_server :blob do |_app, _port, _host|
|
32
44
|
# do nothing
|
33
45
|
end
|
34
46
|
|
35
|
-
expect(
|
47
|
+
expect(described_class.servers[:blob]).to be_truthy
|
36
48
|
end
|
37
49
|
end
|
38
50
|
|
39
51
|
describe '.server' do
|
40
52
|
after do
|
41
|
-
|
53
|
+
described_class.server = :default
|
42
54
|
end
|
43
55
|
|
44
56
|
it 'should default to a proc that calls run_default_server' do
|
45
57
|
mock_app = Object.new
|
46
|
-
allow(
|
47
|
-
|
48
|
-
expect(
|
58
|
+
allow(described_class).to receive(:run_default_server).and_return(true)
|
59
|
+
described_class.server.call(mock_app, 8000)
|
60
|
+
expect(described_class).to have_received(:run_default_server).with(mock_app, 8000)
|
49
61
|
end
|
50
62
|
|
51
63
|
it 'should return a custom server proc' do
|
52
64
|
server = ->(_app, _port) {}
|
53
|
-
|
54
|
-
|
55
|
-
expect(
|
65
|
+
described_class.register_server :custom, &server
|
66
|
+
described_class.server = :custom
|
67
|
+
expect(described_class.server).to eq(server)
|
56
68
|
end
|
57
69
|
|
58
70
|
it 'should have :webrick registered' do
|
59
|
-
expect(
|
71
|
+
expect(described_class.servers[:webrick]).not_to be_nil
|
60
72
|
end
|
61
73
|
|
62
74
|
it 'should have :puma registered' do
|
63
|
-
expect(
|
75
|
+
expect(described_class.servers[:puma]).not_to be_nil
|
64
76
|
end
|
65
77
|
end
|
66
78
|
|
67
79
|
describe 'server=' do
|
68
80
|
after do
|
69
|
-
|
81
|
+
described_class.server = :default
|
70
82
|
end
|
71
83
|
|
72
84
|
it 'accepts a proc' do
|
73
85
|
server = ->(_app, _port) {}
|
74
|
-
|
75
|
-
expect(
|
86
|
+
described_class.server = server
|
87
|
+
expect(described_class.server).to eq server
|
76
88
|
end
|
77
89
|
end
|
78
90
|
|
79
91
|
describe 'app_host' do
|
80
92
|
after do
|
81
|
-
|
93
|
+
described_class.app_host = nil
|
82
94
|
end
|
83
95
|
|
84
96
|
it 'should warn if not a valid URL' do
|
85
|
-
expect {
|
97
|
+
expect { described_class.app_host = 'www.example.com' }.to raise_error(ArgumentError, /Capybara\.app_host should be set to a url/)
|
86
98
|
end
|
87
99
|
|
88
100
|
it 'should not warn if a valid URL' do
|
89
|
-
expect {
|
101
|
+
expect { described_class.app_host = 'http://www.example.com' }.not_to raise_error
|
90
102
|
end
|
91
103
|
|
92
104
|
it 'should not warn if nil' do
|
93
|
-
expect {
|
105
|
+
expect { described_class.app_host = nil }.not_to raise_error
|
94
106
|
end
|
95
107
|
end
|
96
108
|
|
97
109
|
describe 'default_host' do
|
98
110
|
around do |test|
|
99
|
-
old_default =
|
111
|
+
old_default = described_class.default_host
|
100
112
|
test.run
|
101
|
-
|
113
|
+
described_class.default_host = old_default
|
102
114
|
end
|
103
115
|
|
104
116
|
it 'should raise if not a valid URL' do
|
105
|
-
expect {
|
117
|
+
expect { described_class.default_host = 'www.example.com' }.to raise_error(ArgumentError, /Capybara\.default_host should be set to a url/)
|
106
118
|
end
|
107
119
|
|
108
120
|
it 'should not warn if a valid URL' do
|
109
|
-
expect {
|
121
|
+
expect { described_class.default_host = 'http://www.example.com' }.not_to raise_error
|
110
122
|
end
|
111
123
|
end
|
112
124
|
end
|