capybara 2.18.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 -1
- data/History.md +945 -12
- data/License.txt +1 -1
- data/README.md +264 -90
- data/lib/capybara/config.rb +29 -57
- data/lib/capybara/cucumber.rb +2 -3
- data/lib/capybara/driver/base.rb +35 -18
- data/lib/capybara/driver/node.rb +40 -10
- data/lib/capybara/dsl.rb +10 -7
- data/lib/capybara/helpers.rb +70 -31
- data/lib/capybara/minitest/spec.rb +185 -83
- data/lib/capybara/minitest.rb +232 -112
- data/lib/capybara/node/actions.rb +274 -171
- data/lib/capybara/node/base.rb +42 -34
- data/lib/capybara/node/document.rb +15 -3
- data/lib/capybara/node/document_matchers.rb +19 -21
- data/lib/capybara/node/element.rb +362 -135
- data/lib/capybara/node/finders.rb +151 -137
- data/lib/capybara/node/matchers.rb +394 -209
- data/lib/capybara/node/simple.rb +59 -26
- 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 +12 -9
- data/lib/capybara/queries/base_query.rb +39 -28
- data/lib/capybara/queries/current_path_query.rb +21 -27
- data/lib/capybara/queries/match_query.rb +14 -7
- data/lib/capybara/queries/selector_query.rb +659 -149
- data/lib/capybara/queries/sibling_query.rb +11 -9
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +56 -38
- data/lib/capybara/queries/title_query.rb +8 -11
- data/lib/capybara/rack_test/browser.rb +114 -42
- data/lib/capybara/rack_test/css_handlers.rb +6 -4
- data/lib/capybara/rack_test/driver.rb +22 -17
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +93 -58
- data/lib/capybara/rack_test/node.rb +184 -81
- data/lib/capybara/rails.rb +3 -7
- 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 +97 -63
- data/lib/capybara/rspec/features.rb +17 -50
- data/lib/capybara/rspec/matcher_proxies.rb +52 -15
- 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 +146 -310
- data/lib/capybara/rspec.rb +7 -11
- 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 +85 -13
- 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 +2 -17
- data/lib/capybara/selector/filter_set.rb +80 -33
- data/lib/capybara/selector/filters/base.rb +50 -6
- data/lib/capybara/selector/filters/expression_filter.rb +8 -26
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +16 -12
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +93 -210
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +475 -523
- 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 +298 -267
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
- 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 +517 -145
- 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 +80 -0
- data/lib/capybara/server/checker.rb +44 -0
- data/lib/capybara/server/middleware.rb +71 -0
- data/lib/capybara/server.rb +59 -67
- data/lib/capybara/session/config.rb +81 -67
- data/lib/capybara/session/matchers.rb +28 -20
- data/lib/capybara/session.rb +337 -365
- 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 +151 -12
- data/lib/capybara/spec/session/accept_alert_spec.rb +12 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +6 -5
- data/lib/capybara/spec/session/accept_prompt_spec.rb +10 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +161 -57
- data/lib/capybara/spec/session/ancestor_spec.rb +27 -24
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +68 -38
- data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
- data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
- data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
- data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +22 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +144 -69
- data/lib/capybara/spec/session/body_spec.rb +12 -13
- data/lib/capybara/spec/session/check_spec.rb +117 -55
- data/lib/capybara/spec/session/choose_spec.rb +64 -31
- data/lib/capybara/spec/session/click_button_spec.rb +231 -173
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +55 -35
- data/lib/capybara/spec/session/click_link_spec.rb +93 -58
- data/lib/capybara/spec/session/current_scope_spec.rb +12 -11
- data/lib/capybara/spec/session/current_url_spec.rb +57 -39
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +4 -4
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +3 -2
- data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
- data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +71 -57
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +8 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +29 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +10 -8
- data/lib/capybara/spec/session/fill_in_spec.rb +134 -43
- data/lib/capybara/spec/session/find_button_spec.rb +25 -24
- data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
- data/lib/capybara/spec/session/find_field_spec.rb +37 -41
- data/lib/capybara/spec/session/find_link_spec.rb +46 -17
- data/lib/capybara/spec/session/find_spec.rb +260 -145
- data/lib/capybara/spec/session/first_spec.rb +80 -52
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +33 -20
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +52 -32
- data/lib/capybara/spec/session/go_back_spec.rb +2 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +31 -31
- 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 +100 -13
- data/lib/capybara/spec/session/has_css_spec.rb +272 -137
- data/lib/capybara/spec/session/has_current_path_spec.rb +60 -61
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +139 -59
- data/lib/capybara/spec/session/has_link_spec.rb +47 -6
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +42 -40
- data/lib/capybara/spec/session/has_select_spec.rb +107 -72
- data/lib/capybara/spec/session/has_selector_spec.rb +120 -71
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +183 -5
- data/lib/capybara/spec/session/has_text_spec.rb +106 -62
- data/lib/capybara/spec/session/has_title_spec.rb +20 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +57 -38
- data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
- data/lib/capybara/spec/session/html_spec.rb +14 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
- data/lib/capybara/spec/session/node_spec.rb +1024 -153
- data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
- data/lib/capybara/spec/session/refresh_spec.rb +12 -6
- data/lib/capybara/spec/session/reset_session_spec.rb +82 -35
- data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +8 -12
- data/lib/capybara/spec/session/save_page_spec.rb +42 -55
- data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
- 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 +107 -81
- data/lib/capybara/spec/session/selectors_spec.rb +52 -19
- data/lib/capybara/spec/session/sibling_spec.rb +10 -10
- data/lib/capybara/spec/session/text_spec.rb +37 -21
- data/lib/capybara/spec/session/title_spec.rb +17 -5
- data/lib/capybara/spec/session/uncheck_spec.rb +43 -23
- data/lib/capybara/spec/session/unselect_spec.rb +39 -38
- data/lib/capybara/spec/session/visit_spec.rb +85 -53
- data/lib/capybara/spec/session/window/become_closed_spec.rb +24 -20
- data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +27 -22
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +12 -6
- data/lib/capybara/spec/session/window/window_spec.rb +97 -63
- data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
- data/lib/capybara/spec/session/window/within_window_spec.rb +31 -86
- data/lib/capybara/spec/session/within_spec.rb +83 -44
- data/lib/capybara/spec/spec_helper.rb +54 -44
- data/lib/capybara/spec/test_app.rb +158 -43
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +163 -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 +68 -1
- data/lib/capybara/spec/views/with_animation.erb +81 -0
- 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 +69 -12
- 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 +30 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +21 -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 +5 -2
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +36 -34
- data/lib/capybara.rb +134 -107
- data/spec/basic_node_spec.rb +60 -34
- data/spec/capybara_spec.rb +63 -88
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +85 -64
- data/spec/filter_set_spec.rb +27 -9
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +6 -5
- data/spec/fixtures/selenium_driver_rspec_success.rb +6 -5
- data/spec/minitest_spec.rb +52 -7
- data/spec/minitest_spec_spec.rb +94 -63
- data/spec/per_session_config_spec.rb +14 -13
- data/spec/rack_test_spec.rb +194 -125
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +111 -50
- data/spec/rspec/features_spec.rb +37 -31
- data/spec/rspec/scenarios_spec.rb +10 -8
- data/spec/rspec/shared_spec_matchers.rb +473 -422
- data/spec/rspec/views_spec.rb +5 -3
- data/spec/rspec_matchers_spec.rb +52 -11
- data/spec/rspec_spec.rb +109 -89
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +397 -68
- data/spec/selenium_spec_chrome.rb +187 -40
- data/spec/selenium_spec_chrome_remote.rb +96 -0
- data/spec/selenium_spec_edge.rb +60 -0
- data/spec/selenium_spec_firefox.rb +201 -41
- data/spec/selenium_spec_firefox_remote.rb +94 -0
- data/spec/selenium_spec_ie.rb +149 -0
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +213 -102
- data/spec/session_spec.rb +53 -16
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +473 -122
- data/spec/spec_helper.rb +126 -7
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +355 -73
- data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
- data/.yard/templates_custom/default/class/html/setup.rb +0 -17
- data/.yard/yard_extensions.rb +0 -78
- data/lib/capybara/query.rb +0 -7
- data/lib/capybara/rspec/compound.rb +0 -95
- data/lib/capybara/spec/session/assert_current_path.rb +0 -72
- data/lib/capybara/spec/session/assert_selector.rb +0 -148
- data/lib/capybara/spec/session/assert_text.rb +0 -234
- 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 -127
|
@@ -1,87 +1,64 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
3
4
|
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
|
|
4
5
|
# the class specifically when determining whether to construct the request as multipart.
|
|
5
6
|
# That check should be based solely on the form element's 'enctype' attribute value,
|
|
6
7
|
# which should probably be provided to Rack::Test in its non-GET request methods.
|
|
7
8
|
class NilUploadedFile < Rack::Test::UploadedFile
|
|
8
|
-
def initialize
|
|
9
|
-
@empty_file = Tempfile.new(
|
|
9
|
+
def initialize # rubocop:disable Lint/MissingSuper
|
|
10
|
+
@empty_file = Tempfile.new('nil_uploaded_file')
|
|
10
11
|
@empty_file.close
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
def original_filename;
|
|
14
|
-
def content_type;
|
|
14
|
+
def original_filename; ''; end
|
|
15
|
+
def content_type; 'application/octet-stream'; end
|
|
15
16
|
def path; @empty_file.path; end
|
|
16
17
|
def size; 0; end
|
|
17
|
-
def read;
|
|
18
|
+
def read; ''; end
|
|
19
|
+
def append_to(_); end
|
|
20
|
+
def set_encoding(_); end # rubocop:disable Naming/AccessorMethodName
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
def params(button)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
xpath
|
|
26
|
-
xpath=xpath.union(x.anywhere(*form_element_types).where(x.attr(:form) == native[:id])) if native[:id]
|
|
27
|
-
xpath.where(~x.attr(:disabled))
|
|
24
|
+
form_element_types = %i[input select textarea button]
|
|
25
|
+
form_elements_xpath = XPath.generate do |xp|
|
|
26
|
+
xpath = xp.descendant(*form_element_types).where(!xp.attr(:form))
|
|
27
|
+
xpath += xp.anywhere(*form_element_types).where(xp.attr(:form) == native[:id]) if native[:id]
|
|
28
|
+
xpath.where(!xp.attr(:disabled))
|
|
28
29
|
end.to_s
|
|
29
30
|
|
|
30
|
-
native.xpath(form_elements_xpath).
|
|
31
|
+
form_elements = native.xpath(form_elements_xpath).reject { |el| submitter?(el) && (el != button.native) }
|
|
32
|
+
|
|
33
|
+
form_params = form_elements.each_with_object({}.compare_by_identity) do |field, params|
|
|
31
34
|
case field.name
|
|
32
|
-
when 'input'
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
node=Capybara::RackTest::Node.new(self.driver, field)
|
|
36
|
-
merge_param!(params, field['name'].to_s, node.value.to_s)
|
|
37
|
-
end
|
|
38
|
-
elsif %w(submit image).include? field['type']
|
|
39
|
-
# TO DO identify the click button here (in document order, rather
|
|
40
|
-
# than leaving until the end of the params)
|
|
41
|
-
elsif field['type'] =='file'
|
|
42
|
-
if multipart?
|
|
43
|
-
file = \
|
|
44
|
-
if (value = field['value']).to_s.empty?
|
|
45
|
-
NilUploadedFile.new
|
|
46
|
-
else
|
|
47
|
-
mime_info = MiniMime.lookup_by_filename(value)
|
|
48
|
-
Rack::Test::UploadedFile.new(value, (mime_info && mime_info.content_type).to_s)
|
|
49
|
-
end
|
|
50
|
-
merge_param!(params, field['name'].to_s, file)
|
|
51
|
-
else
|
|
52
|
-
merge_param!(params, field['name'].to_s, File.basename(field['value'].to_s))
|
|
53
|
-
end
|
|
54
|
-
else
|
|
55
|
-
merge_param!(params, field['name'].to_s, field['value'].to_s)
|
|
56
|
-
end
|
|
57
|
-
when 'select'
|
|
58
|
-
if field['multiple'] == 'multiple'
|
|
59
|
-
options = field.xpath(".//option[@selected]")
|
|
60
|
-
options.each do |option|
|
|
61
|
-
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s)
|
|
62
|
-
end
|
|
63
|
-
else
|
|
64
|
-
option = field.xpath(".//option[@selected]").first
|
|
65
|
-
option ||= field.xpath('.//option').first
|
|
66
|
-
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
|
|
67
|
-
end
|
|
68
|
-
when 'textarea'
|
|
69
|
-
merge_param!(params, field['name'].to_s, field['_capybara_raw_value'].to_s.gsub(/\n/, "\r\n"))
|
|
35
|
+
when 'input', 'button' then add_input_param(field, params)
|
|
36
|
+
when 'select' then add_select_param(field, params)
|
|
37
|
+
when 'textarea' then add_textarea_param(field, params)
|
|
70
38
|
end
|
|
71
39
|
end
|
|
72
|
-
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|
|
73
40
|
|
|
74
|
-
params
|
|
41
|
+
form_params.each_with_object(make_params) do |(name, value), params|
|
|
42
|
+
merge_param!(params, name, value)
|
|
43
|
+
end.to_params_hash
|
|
44
|
+
|
|
45
|
+
# form_elements.each_with_object(make_params) do |field, params|
|
|
46
|
+
# case field.name
|
|
47
|
+
# when 'input', 'button' then add_input_param(field, params)
|
|
48
|
+
# when 'select' then add_select_param(field, params)
|
|
49
|
+
# when 'textarea' then add_textarea_param(field, params)
|
|
50
|
+
# end
|
|
51
|
+
# end.to_params_hash
|
|
75
52
|
end
|
|
76
53
|
|
|
77
54
|
def submit(button)
|
|
78
|
-
action =
|
|
79
|
-
method =
|
|
80
|
-
driver.submit(method, action.to_s, params(button))
|
|
55
|
+
action = button&.[]('formaction') || native['action']
|
|
56
|
+
method = button&.[]('formmethod') || request_method
|
|
57
|
+
driver.submit(method, action.to_s, params(button), content_type: native['enctype'])
|
|
81
58
|
end
|
|
82
59
|
|
|
83
60
|
def multipart?
|
|
84
|
-
self[:enctype] ==
|
|
61
|
+
self[:enctype] == 'multipart/form-data'
|
|
85
62
|
end
|
|
86
63
|
|
|
87
64
|
private
|
|
@@ -93,10 +70,11 @@ private
|
|
|
93
70
|
end
|
|
94
71
|
|
|
95
72
|
def request_method
|
|
96
|
-
self[:method]
|
|
73
|
+
/post/i.match?(self[:method] || '') ? :post : :get
|
|
97
74
|
end
|
|
98
75
|
|
|
99
76
|
def merge_param!(params, key, value)
|
|
77
|
+
key = key.to_s
|
|
100
78
|
if Rack::Utils.respond_to?(:default_query_parser)
|
|
101
79
|
Rack::Utils.default_query_parser.normalize_params(params, key, value, Rack::Utils.param_depth_limit)
|
|
102
80
|
else
|
|
@@ -111,4 +89,61 @@ private
|
|
|
111
89
|
ParamsHash.new
|
|
112
90
|
end
|
|
113
91
|
end
|
|
92
|
+
|
|
93
|
+
def add_input_param(field, params)
|
|
94
|
+
name, value = field['name'].to_s, field['value'].to_s
|
|
95
|
+
return if name.empty?
|
|
96
|
+
|
|
97
|
+
value = case field['type']
|
|
98
|
+
when 'radio', 'checkbox'
|
|
99
|
+
return unless field['checked']
|
|
100
|
+
|
|
101
|
+
Capybara::RackTest::Node.new(driver, field).value.to_s
|
|
102
|
+
when 'file'
|
|
103
|
+
return if value.empty? && params.keys.include?(name) && Rack::Test::VERSION.to_f >= 2.0 # rubocop:disable Performance/InefficientHashSearch
|
|
104
|
+
|
|
105
|
+
if multipart?
|
|
106
|
+
file_to_upload(value)
|
|
107
|
+
else
|
|
108
|
+
File.basename(value)
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
value
|
|
112
|
+
end
|
|
113
|
+
# merge_param!(params, name, value)
|
|
114
|
+
params[name] = value
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def file_to_upload(filename)
|
|
118
|
+
if filename.empty?
|
|
119
|
+
NilUploadedFile.new
|
|
120
|
+
else
|
|
121
|
+
mime_info = MiniMime.lookup_by_filename(filename)
|
|
122
|
+
Rack::Test::UploadedFile.new(filename, mime_info&.content_type&.to_s)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def add_select_param(field, params)
|
|
127
|
+
name = field['name']
|
|
128
|
+
if field.has_attribute?('multiple')
|
|
129
|
+
value = field.xpath('.//option[@selected]').map do |option|
|
|
130
|
+
# merge_param!(params, field['name'], (option['value'] || option.text).to_s)
|
|
131
|
+
(option['value'] || option.text).to_s
|
|
132
|
+
end
|
|
133
|
+
params[name] = value unless value.empty?
|
|
134
|
+
else
|
|
135
|
+
option = field.xpath('.//option[@selected]').first || field.xpath('.//option').first
|
|
136
|
+
# merge_param!(params, field['name'], (option['value'] || option.text).to_s) if option
|
|
137
|
+
params[name] = (option['value'] || option.text).to_s if option
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def add_textarea_param(field, params)
|
|
142
|
+
# merge_param!(params, field['name'], field['_capybara_raw_value'].to_s.gsub(/\r?\n/, "\r\n"))
|
|
143
|
+
params[field['name']] = field['_capybara_raw_value'].to_s.gsub(/\r?\n/, "\r\n")
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def submitter?(el)
|
|
147
|
+
(%w[submit image].include? el['type']) || (el.name == 'button')
|
|
148
|
+
end
|
|
114
149
|
end
|
|
@@ -1,79 +1,78 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'capybara/rack_test/errors'
|
|
4
|
+
require 'capybara/node/whitespace_normalizer'
|
|
5
|
+
|
|
2
6
|
class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
7
|
+
include Capybara::Node::WhitespaceNormalizer
|
|
8
|
+
|
|
9
|
+
BLOCK_ELEMENTS = %w[p h1 h2 h3 h4 h5 h6 ol ul pre address blockquote dl div fieldset form hr noscript table].freeze
|
|
10
|
+
|
|
3
11
|
def all_text
|
|
4
|
-
|
|
12
|
+
normalize_spacing(native.text)
|
|
5
13
|
end
|
|
6
14
|
|
|
7
15
|
def visible_text
|
|
8
|
-
|
|
16
|
+
normalize_visible_spacing(displayed_text)
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
def [](name)
|
|
12
20
|
string_node[name]
|
|
13
21
|
end
|
|
14
22
|
|
|
23
|
+
def style(_styles)
|
|
24
|
+
raise NotImplementedError, 'The rack_test driver does not process CSS'
|
|
25
|
+
end
|
|
26
|
+
|
|
15
27
|
def value
|
|
16
28
|
string_node.value
|
|
17
29
|
end
|
|
18
30
|
|
|
19
|
-
def set(value)
|
|
20
|
-
return if disabled?
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return
|
|
24
|
-
end
|
|
31
|
+
def set(value, **options)
|
|
32
|
+
return if disabled? || readonly?
|
|
33
|
+
|
|
34
|
+
warn "Options passed to Node#set but the RackTest driver doesn't support any - ignoring" unless options.empty?
|
|
25
35
|
|
|
26
|
-
if (Array
|
|
27
|
-
raise TypeError
|
|
36
|
+
if value.is_a?(Array) && !multiple?
|
|
37
|
+
raise TypeError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}"
|
|
28
38
|
end
|
|
29
39
|
|
|
30
|
-
if radio?
|
|
31
|
-
|
|
32
|
-
elsif
|
|
33
|
-
|
|
34
|
-
elsif
|
|
35
|
-
set_input(value)
|
|
36
|
-
elsif textarea?
|
|
37
|
-
native['_capybara_raw_value'] = value.to_s
|
|
40
|
+
if radio? then set_radio(value)
|
|
41
|
+
elsif checkbox? then set_checkbox(value)
|
|
42
|
+
elsif range? then set_range(value)
|
|
43
|
+
elsif input_field? then set_input(value)
|
|
44
|
+
elsif textarea? then native['_capybara_raw_value'] = value.to_s
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
def select_option
|
|
42
49
|
return if disabled?
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
native["selected"] = 'selected'
|
|
50
|
+
|
|
51
|
+
deselect_options unless select_node.multiple?
|
|
52
|
+
native['selected'] = 'selected'
|
|
47
53
|
end
|
|
48
54
|
|
|
49
55
|
def unselect_option
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
end
|
|
56
|
+
raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select_node.multiple?
|
|
57
|
+
|
|
53
58
|
native.remove_attribute('selected')
|
|
54
59
|
end
|
|
55
60
|
|
|
56
|
-
def click
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
def click(keys = [], **options)
|
|
62
|
+
options.delete(:offset)
|
|
63
|
+
raise ArgumentError, 'The RackTest driver does not support click options' unless keys.empty? && options.empty?
|
|
64
|
+
|
|
65
|
+
if link?
|
|
66
|
+
follow_link
|
|
67
|
+
elsif submits?
|
|
63
68
|
associated_form = form
|
|
64
69
|
Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form
|
|
65
|
-
elsif
|
|
70
|
+
elsif checkable?
|
|
66
71
|
set(!checked?)
|
|
67
|
-
elsif
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
find_xpath(".//input").first
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
if labelled_control && (labelled_control.checkbox? || labelled_control.radio?)
|
|
75
|
-
labelled_control.set(!labelled_control.checked?)
|
|
76
|
-
end
|
|
72
|
+
elsif tag_name == 'label'
|
|
73
|
+
click_label
|
|
74
|
+
elsif (details = native.xpath('.//ancestor-or-self::details').last)
|
|
75
|
+
toggle_details(details)
|
|
77
76
|
end
|
|
78
77
|
end
|
|
79
78
|
|
|
@@ -94,47 +93,79 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
|
94
93
|
end
|
|
95
94
|
|
|
96
95
|
def disabled?
|
|
97
|
-
if
|
|
98
|
-
|
|
96
|
+
return true if string_node.disabled?
|
|
97
|
+
|
|
98
|
+
if %w[option optgroup].include? tag_name
|
|
99
|
+
find_xpath(OPTION_OWNER_XPATH)[0].disabled?
|
|
99
100
|
else
|
|
100
|
-
|
|
101
|
+
!find_xpath(DISABLED_BY_FIELDSET_XPATH).empty?
|
|
101
102
|
end
|
|
102
103
|
end
|
|
103
104
|
|
|
105
|
+
def readonly?
|
|
106
|
+
# readonly attribute not valid on these input types
|
|
107
|
+
return false if input_field? && %w[hidden range color checkbox radio file submit image reset button].include?(type)
|
|
108
|
+
|
|
109
|
+
super
|
|
110
|
+
end
|
|
111
|
+
|
|
104
112
|
def path
|
|
105
113
|
native.path
|
|
106
114
|
end
|
|
107
115
|
|
|
108
|
-
def find_xpath(locator)
|
|
109
|
-
native.xpath(locator).map { |
|
|
116
|
+
def find_xpath(locator, **_hints)
|
|
117
|
+
native.xpath(locator).map { |el| self.class.new(driver, el) }
|
|
110
118
|
end
|
|
111
119
|
|
|
112
|
-
def find_css(locator)
|
|
113
|
-
native.css(locator, Capybara::RackTest::CSSHandlers.new).map { |
|
|
120
|
+
def find_css(locator, **_hints)
|
|
121
|
+
native.css(locator, Capybara::RackTest::CSSHandlers.new).map { |el| self.class.new(driver, el) }
|
|
114
122
|
end
|
|
115
123
|
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
public_instance_methods(false).each do |meth_name|
|
|
125
|
+
alias_method "unchecked_#{meth_name}", meth_name
|
|
126
|
+
private "unchecked_#{meth_name}" # rubocop:disable Style/AccessModifierDeclarations
|
|
127
|
+
|
|
128
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
|
129
|
+
def #{meth_name}(...)
|
|
130
|
+
stale_check
|
|
131
|
+
method(:"unchecked_#{meth_name}").call(...)
|
|
132
|
+
end
|
|
133
|
+
METHOD
|
|
118
134
|
end
|
|
119
135
|
|
|
120
136
|
protected
|
|
121
137
|
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
# @api private
|
|
139
|
+
def displayed_text(check_ancestor: true)
|
|
140
|
+
if !string_node.visible?(check_ancestor)
|
|
124
141
|
''
|
|
125
142
|
elsif native.text?
|
|
126
|
-
native
|
|
143
|
+
native
|
|
144
|
+
.text
|
|
145
|
+
.delete(REMOVED_CHARACTERS)
|
|
146
|
+
.tr(SQUEEZED_SPACES, ' ')
|
|
147
|
+
.squeeze(' ')
|
|
127
148
|
elsif native.element?
|
|
128
|
-
native.children.map do |child|
|
|
129
|
-
Capybara::RackTest::Node.new(driver, child).
|
|
130
|
-
end.join
|
|
131
|
-
|
|
149
|
+
text = native.children.map do |child|
|
|
150
|
+
Capybara::RackTest::Node.new(driver, child).displayed_text(check_ancestor: false)
|
|
151
|
+
end.join || ''
|
|
152
|
+
text = "\n#{text}\n" if BLOCK_ELEMENTS.include?(tag_name)
|
|
153
|
+
text
|
|
154
|
+
else # rubocop:disable Lint/DuplicateBranch
|
|
132
155
|
''
|
|
133
156
|
end
|
|
134
157
|
end
|
|
135
158
|
|
|
136
159
|
private
|
|
137
160
|
|
|
161
|
+
def stale_check
|
|
162
|
+
raise Capybara::RackTest::Errors::StaleElementReferenceError unless native.document == driver.dom
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def deselect_options
|
|
166
|
+
select_node.find_xpath('.//option[@selected]').each { |node| node.native.remove_attribute('selected') }
|
|
167
|
+
end
|
|
168
|
+
|
|
138
169
|
def string_node
|
|
139
170
|
@string_node ||= Capybara::Node::Simple.new(native)
|
|
140
171
|
end
|
|
@@ -150,19 +181,19 @@ private
|
|
|
150
181
|
|
|
151
182
|
def form
|
|
152
183
|
if native[:form]
|
|
153
|
-
native.xpath("//form[@id='#{native[:form]}']")
|
|
184
|
+
native.xpath("//form[@id='#{native[:form]}']")
|
|
154
185
|
else
|
|
155
|
-
native.ancestors('form')
|
|
156
|
-
end
|
|
186
|
+
native.ancestors('form')
|
|
187
|
+
end.first
|
|
157
188
|
end
|
|
158
189
|
|
|
159
|
-
def set_radio(_value)
|
|
160
|
-
other_radios_xpath = XPath.generate { |
|
|
161
|
-
driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute(
|
|
190
|
+
def set_radio(_value) # rubocop:disable Naming/AccessorMethodName
|
|
191
|
+
other_radios_xpath = XPath.generate { |xp| xp.anywhere(:input)[xp.attr(:name) == self[:name]] }.to_s
|
|
192
|
+
driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute('checked') }
|
|
162
193
|
native['checked'] = 'checked'
|
|
163
194
|
end
|
|
164
195
|
|
|
165
|
-
def set_checkbox(value)
|
|
196
|
+
def set_checkbox(value) # rubocop:disable Naming/AccessorMethodName
|
|
166
197
|
if value && !native['checked']
|
|
167
198
|
native['checked'] = 'checked'
|
|
168
199
|
elsif !value && native['checked']
|
|
@@ -170,25 +201,36 @@ private
|
|
|
170
201
|
end
|
|
171
202
|
end
|
|
172
203
|
|
|
173
|
-
def
|
|
204
|
+
def set_range(value) # rubocop:disable Naming/AccessorMethodName
|
|
205
|
+
min, max, step = (native['min'] || 0).to_f, (native['max'] || 100).to_f, (native['step'] || 1).to_f
|
|
206
|
+
value = value.to_f
|
|
207
|
+
value = value.clamp(min, max)
|
|
208
|
+
value = (((value - min) / step).round * step) + min
|
|
209
|
+
native['value'] = value.clamp(min, max)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def set_input(value) # rubocop:disable Naming/AccessorMethodName
|
|
174
213
|
if text_or_password? && attribute_is_not_blank?(:maxlength)
|
|
175
214
|
# Browser behavior for maxlength="0" is inconsistent, so we stick with
|
|
176
215
|
# Firefox, allowing no input
|
|
177
216
|
value = value.to_s[0...self[:maxlength].to_i]
|
|
178
217
|
end
|
|
179
|
-
if Array
|
|
180
|
-
value.each do |
|
|
218
|
+
if value.is_a?(Array) # Assert multiple attribute is present
|
|
219
|
+
value.each do |val|
|
|
181
220
|
new_native = native.clone
|
|
182
221
|
new_native.remove_attribute('value')
|
|
183
222
|
native.add_next_sibling(new_native)
|
|
184
|
-
new_native['value'] =
|
|
223
|
+
new_native['value'] = val.to_s
|
|
185
224
|
end
|
|
186
225
|
native.remove
|
|
187
226
|
else
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
227
|
+
value.to_s.tap do |set_value|
|
|
228
|
+
if set_value.end_with?("\n") && form&.css('input, textarea')&.count == 1
|
|
229
|
+
native['value'] = set_value.to_s.chop
|
|
230
|
+
Capybara::RackTest::Form.new(driver, form).submit(self)
|
|
231
|
+
else
|
|
232
|
+
native['value'] = set_value
|
|
233
|
+
end
|
|
192
234
|
end
|
|
193
235
|
end
|
|
194
236
|
end
|
|
@@ -197,25 +239,86 @@ private
|
|
|
197
239
|
self[attribute] && !self[attribute].empty?
|
|
198
240
|
end
|
|
199
241
|
|
|
242
|
+
def follow_link
|
|
243
|
+
method = self['data-method'] || self['data-turbo-method'] if driver.options[:respect_data_method]
|
|
244
|
+
method ||= :get
|
|
245
|
+
driver.follow(method, self[:href].to_s)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def click_label
|
|
249
|
+
labelled_control = if native[:for]
|
|
250
|
+
find_xpath("//input[@id='#{native[:for]}']")
|
|
251
|
+
else
|
|
252
|
+
find_xpath('.//input')
|
|
253
|
+
end.first
|
|
254
|
+
|
|
255
|
+
labelled_control.set(!labelled_control.checked?) if checkbox_or_radio?(labelled_control)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def toggle_details(details = nil)
|
|
259
|
+
details ||= native.xpath('.//ancestor-or-self::details').last
|
|
260
|
+
return unless details
|
|
261
|
+
|
|
262
|
+
if details.has_attribute?('open')
|
|
263
|
+
details.remove_attribute('open')
|
|
264
|
+
else
|
|
265
|
+
details.set_attribute('open', 'open')
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def link?
|
|
270
|
+
tag_name == 'a' && !self[:href].nil?
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def submits?
|
|
274
|
+
(tag_name == 'input' && %w[submit image].include?(type)) || (tag_name == 'button' && [nil, 'submit'].include?(type))
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def checkable?
|
|
278
|
+
tag_name == 'input' && %w[checkbox radio].include?(type)
|
|
279
|
+
end
|
|
280
|
+
|
|
200
281
|
protected
|
|
201
282
|
|
|
202
|
-
def
|
|
203
|
-
|
|
283
|
+
def checkbox_or_radio?(field = self)
|
|
284
|
+
field&.checkbox? || field&.radio?
|
|
204
285
|
end
|
|
205
286
|
|
|
206
|
-
def
|
|
207
|
-
|
|
287
|
+
def checkbox?
|
|
288
|
+
input_field? && type == 'checkbox'
|
|
208
289
|
end
|
|
209
290
|
|
|
210
291
|
def radio?
|
|
211
292
|
input_field? && type == 'radio'
|
|
212
293
|
end
|
|
213
294
|
|
|
295
|
+
def text_or_password?
|
|
296
|
+
input_field? && (type == 'text' || type == 'password')
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def input_field?
|
|
300
|
+
tag_name == 'input'
|
|
301
|
+
end
|
|
302
|
+
|
|
214
303
|
def textarea?
|
|
215
|
-
tag_name ==
|
|
304
|
+
tag_name == 'textarea'
|
|
216
305
|
end
|
|
217
306
|
|
|
218
|
-
def
|
|
219
|
-
input_field? &&
|
|
307
|
+
def range?
|
|
308
|
+
input_field? && type == 'range'
|
|
220
309
|
end
|
|
310
|
+
|
|
311
|
+
OPTION_OWNER_XPATH = XPath.parent(:optgroup, :select, :datalist).to_s.freeze
|
|
312
|
+
DISABLED_BY_FIELDSET_XPATH = XPath.generate do |x|
|
|
313
|
+
x.parent(:fieldset)[
|
|
314
|
+
XPath.attr(:disabled)
|
|
315
|
+
] + x.ancestor[
|
|
316
|
+
~x.self(:legend) |
|
|
317
|
+
x.preceding_sibling(:legend)
|
|
318
|
+
][
|
|
319
|
+
x.parent(:fieldset)[
|
|
320
|
+
x.attr(:disabled)
|
|
321
|
+
]
|
|
322
|
+
]
|
|
323
|
+
end.to_s.freeze
|
|
221
324
|
end
|
data/lib/capybara/rails.rb
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'capybara/dsl'
|
|
3
4
|
|
|
4
5
|
Capybara.app = Rack::Builder.new do
|
|
5
|
-
map
|
|
6
|
-
|
|
7
|
-
run Rails.application
|
|
8
|
-
else # Rails 2
|
|
9
|
-
use Rails::Rack::Static
|
|
10
|
-
run ActionController::Dispatcher.new
|
|
11
|
-
end
|
|
6
|
+
map '/' do
|
|
7
|
+
run Rails.application
|
|
12
8
|
end
|
|
13
9
|
end.to_app
|
|
14
10
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capybara
|
|
4
|
+
# @api private
|
|
5
|
+
class RegistrationContainer
|
|
6
|
+
def names
|
|
7
|
+
@registered.keys
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def [](name)
|
|
11
|
+
@registered[name]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def []=(name, value)
|
|
15
|
+
Capybara::Helpers.warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'
|
|
16
|
+
@registered[name] = value
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def method_missing(method_name, ...)
|
|
20
|
+
if @registered.respond_to?(method_name)
|
|
21
|
+
Capybara::Helpers.warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
|
|
22
|
+
return @registered.public_send(method_name, ...)
|
|
23
|
+
end
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def respond_to_missing?(method_name, include_all)
|
|
28
|
+
@registered.respond_to?(method_name) || super
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def initialize
|
|
34
|
+
@registered = {}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def register(name, block)
|
|
38
|
+
@registered[name] = block
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Capybara.register_driver :rack_test do |app|
|
|
4
|
+
Capybara::RackTest::Driver.new(app)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
Capybara.register_driver :selenium do |app|
|
|
8
|
+
Capybara::Selenium::Driver.new(app)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Capybara.register_driver :selenium_headless do |app|
|
|
12
|
+
version = Capybara::Selenium::Driver.load_selenium
|
|
13
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
|
14
|
+
browser_options = Selenium::WebDriver::Firefox::Options.new.tap do |opts|
|
|
15
|
+
opts.add_argument '-headless'
|
|
16
|
+
end
|
|
17
|
+
Capybara::Selenium::Driver.new(app, **{ :browser => :firefox, options_key => browser_options })
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Capybara.register_driver :selenium_chrome do |app|
|
|
21
|
+
version = Capybara::Selenium::Driver.load_selenium
|
|
22
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
|
23
|
+
browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts|
|
|
24
|
+
# Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
|
|
25
|
+
opts.add_argument('--disable-site-isolation-trials')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Capybara::Selenium::Driver.new(app, **{ :browser => :chrome, options_key => browser_options })
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
Capybara.register_driver :selenium_chrome_headless do |app|
|
|
32
|
+
version = Capybara::Selenium::Driver.load_selenium
|
|
33
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
|
34
|
+
browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts|
|
|
35
|
+
opts.add_argument('--headless=new')
|
|
36
|
+
opts.add_argument('--disable-gpu') if Gem.win_platform?
|
|
37
|
+
# Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
|
|
38
|
+
opts.add_argument('--disable-site-isolation-trials')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Capybara::Selenium::Driver.new(app, **{ :browser => :chrome, options_key => browser_options })
|
|
42
|
+
end
|