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
data/License.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
# Capybara
|
|
2
2
|
|
|
3
|
-
[](https://ci.appveyor.com/api/projects/github/teamcapybara/capybara)
|
|
3
|
+
[](https://github.com/teamcapybara/capybara/actions/workflows/build.yml)
|
|
5
4
|
[](https://codeclimate.com/github/teamcapybara/capybara)
|
|
6
|
-
[](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
|
|
8
|
-
|
|
9
|
-
**Note** You are viewing the README for the development version of Capybara. If you are using the current release version
|
|
10
|
-
you can find the README at https://github.com/teamcapybara/capybara/blob/3.2_stable/README.md
|
|
11
|
-
|
|
5
|
+
[](https://coveralls.io/github/teamcapybara/capybara?branch=master)
|
|
12
6
|
|
|
13
7
|
Capybara helps you test web applications by simulating how a real user would
|
|
14
8
|
interact with your app. It is agnostic about the driver running your tests and
|
|
@@ -21,8 +15,7 @@ If you and/or your company find value in Capybara and would like to contribute f
|
|
|
21
15
|
<a href="https://www.patreon.com/capybara">Patreon</a>
|
|
22
16
|
|
|
23
17
|
|
|
24
|
-
**Need help?** Ask on the
|
|
25
|
-
GitHub): http://groups.google.com/group/ruby-capybara
|
|
18
|
+
**Need help?** Ask on the discussions (please do not open an issue): https://github.com/orgs/teamcapybara/discussions/categories/q-a
|
|
26
19
|
|
|
27
20
|
## Table of contents
|
|
28
21
|
|
|
@@ -37,8 +30,6 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
37
30
|
- [Selecting the Driver](#selecting-the-driver)
|
|
38
31
|
- [RackTest](#racktest)
|
|
39
32
|
- [Selenium](#selenium)
|
|
40
|
-
- [Capybara-webkit](#capybara-webkit)
|
|
41
|
-
- [Poltergeist](#poltergeist)
|
|
42
33
|
- [The DSL](#the-dsl)
|
|
43
34
|
- [Navigating](#navigating)
|
|
44
35
|
- [Clicking links and buttons](#clicking-links-and-buttons)
|
|
@@ -50,6 +41,10 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
50
41
|
- [Scripting](#scripting)
|
|
51
42
|
- [Modals](#modals)
|
|
52
43
|
- [Debugging](#debugging)
|
|
44
|
+
- [Selectors](#selectors)
|
|
45
|
+
- [Name](#selectors-name)
|
|
46
|
+
- [Locator](#selectors-locator)
|
|
47
|
+
- [Filters](#selectors-filters)
|
|
53
48
|
- [Matching](#matching)
|
|
54
49
|
- [Exactness](#exactness)
|
|
55
50
|
- [Strategy](#strategy)
|
|
@@ -58,11 +53,13 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
58
53
|
- [Using the DSL elsewhere](#using-the-dsl-elsewhere)
|
|
59
54
|
- [Calling remote servers](#calling-remote-servers)
|
|
60
55
|
- [Using sessions](#using-sessions)
|
|
56
|
+
- [Named sessions](#named-sessions)
|
|
57
|
+
- [Using sessions manually](#using-sessions-manually)
|
|
61
58
|
- [XPath, CSS and selectors](#xpath-css-and-selectors)
|
|
62
59
|
- [Beware the XPath // trap](#beware-the-xpath--trap)
|
|
63
60
|
- [Configuring and adding drivers](#configuring-and-adding-drivers)
|
|
64
61
|
- [Gotchas:](#gotchas)
|
|
65
|
-
- ["Threadsafe" mode](#threadsafe)
|
|
62
|
+
- ["Threadsafe" mode](#threadsafe-mode)
|
|
66
63
|
- [Development](#development)
|
|
67
64
|
|
|
68
65
|
## <a name="key-benefits"></a>Key benefits
|
|
@@ -76,7 +73,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
76
73
|
|
|
77
74
|
## <a name="setup"></a>Setup
|
|
78
75
|
|
|
79
|
-
Capybara requires Ruby
|
|
76
|
+
Capybara requires Ruby 3.0.0 or later. To install, add this line to your
|
|
80
77
|
`Gemfile` and run `bundle install`:
|
|
81
78
|
|
|
82
79
|
```ruby
|
|
@@ -140,18 +137,20 @@ There are also explicit tags for each registered driver set up for you (`@seleni
|
|
|
140
137
|
|
|
141
138
|
## <a name="using-capybara-with-rspec"></a>Using Capybara with RSpec
|
|
142
139
|
|
|
143
|
-
Load RSpec 3.
|
|
140
|
+
Load RSpec 3.5+ support by adding the following line (typically to your
|
|
144
141
|
`spec_helper.rb` file):
|
|
145
142
|
|
|
146
143
|
```ruby
|
|
147
144
|
require 'capybara/rspec'
|
|
148
145
|
```
|
|
149
146
|
|
|
150
|
-
If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
147
|
+
If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works if
|
|
148
|
+
[you have it configured in RSpec](https://rspec.info/features/6-0/rspec-rails/directory-structure/))
|
|
149
|
+
and if you have your Capybara specs in a different directory, then tag the example groups with
|
|
150
|
+
`type: :feature` or `type: :system` depending on which type of test you're writing.
|
|
151
|
+
|
|
152
|
+
If you are using Rails system specs please see [their documentation](https://rspec.info/features/6-0/rspec-rails/system-specs/system-specs)
|
|
153
|
+
for selecting the driver you wish to use.
|
|
155
154
|
|
|
156
155
|
If you are not using Rails, tag all the example groups in which you want to use
|
|
157
156
|
Capybara with `type: :feature`.
|
|
@@ -161,7 +160,7 @@ You can now write your specs like so:
|
|
|
161
160
|
```ruby
|
|
162
161
|
describe "the signin process", type: :feature do
|
|
163
162
|
before :each do
|
|
164
|
-
User.
|
|
163
|
+
User.create(email: 'user@example.com', password: 'password')
|
|
165
164
|
end
|
|
166
165
|
|
|
167
166
|
it "signs me in" do
|
|
@@ -183,7 +182,7 @@ to one specific driver. For example:
|
|
|
183
182
|
```ruby
|
|
184
183
|
describe 'some stuff which requires js', js: true do
|
|
185
184
|
it 'will use the default js driver'
|
|
186
|
-
it 'will switch to one specific driver', driver: :
|
|
185
|
+
it 'will switch to one specific driver', driver: :selenium
|
|
187
186
|
end
|
|
188
187
|
```
|
|
189
188
|
|
|
@@ -192,7 +191,7 @@ Capybara also comes with a built in DSL for creating descriptive acceptance test
|
|
|
192
191
|
```ruby
|
|
193
192
|
feature "Signing in" do
|
|
194
193
|
background do
|
|
195
|
-
User.
|
|
194
|
+
User.create(email: 'user@example.com', password: 'caplin')
|
|
196
195
|
end
|
|
197
196
|
|
|
198
197
|
scenario "Signing in with correct credentials" do
|
|
@@ -205,7 +204,7 @@ feature "Signing in" do
|
|
|
205
204
|
expect(page).to have_content 'Success'
|
|
206
205
|
end
|
|
207
206
|
|
|
208
|
-
given(:other_user) { User.
|
|
207
|
+
given(:other_user) { User.create(email: 'other@example.com', password: 'rous') }
|
|
209
208
|
|
|
210
209
|
scenario "Signing in as another user" do
|
|
211
210
|
visit '/sessions/new'
|
|
@@ -219,7 +218,7 @@ feature "Signing in" do
|
|
|
219
218
|
end
|
|
220
219
|
```
|
|
221
220
|
|
|
222
|
-
`feature` is in fact just an alias for `describe ..., type
|
|
221
|
+
`feature` is in fact just an alias for `describe ..., type: :feature`,
|
|
223
222
|
`background` is an alias for `before`, `scenario` for `it`, and
|
|
224
223
|
`given`/`given!` aliases for `let`/`let!`, respectively.
|
|
225
224
|
|
|
@@ -260,7 +259,9 @@ end
|
|
|
260
259
|
|
|
261
260
|
## <a name="using-capybara-with-minitest"></a>Using Capybara with Minitest
|
|
262
261
|
|
|
263
|
-
* If you are using Rails
|
|
262
|
+
* If you are using Rails system tests please see their documentation for information on selecting the driver you wish to use.
|
|
263
|
+
|
|
264
|
+
* If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`
|
|
264
265
|
file to make Capybara available in all test cases deriving from
|
|
265
266
|
`ActionDispatch::IntegrationTest`:
|
|
266
267
|
|
|
@@ -275,8 +276,7 @@ end
|
|
|
275
276
|
include Capybara::Minitest::Assertions
|
|
276
277
|
|
|
277
278
|
# Reset sessions and driver between tests
|
|
278
|
-
|
|
279
|
-
def teardown
|
|
279
|
+
teardown do
|
|
280
280
|
Capybara.reset_sessions!
|
|
281
281
|
Capybara.use_default_driver
|
|
282
282
|
end
|
|
@@ -335,15 +335,15 @@ By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
|
|
|
335
335
|
does not support JavaScript, nor is it able to access HTTP resources outside of
|
|
336
336
|
your Rack application, such as remote APIs and OAuth services. To get around
|
|
337
337
|
these limitations, you can set up a different default driver for your features.
|
|
338
|
-
For example if you'd prefer to run everything in Selenium, you could do:
|
|
338
|
+
For example, if you'd prefer to run everything in Selenium, you could do:
|
|
339
339
|
|
|
340
340
|
```ruby
|
|
341
341
|
Capybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
However, if you are using RSpec or Cucumber
|
|
345
|
-
leaving the faster `:rack_test` as the __default_driver__, and
|
|
346
|
-
tests that require a JavaScript-capable driver using `js: true` or
|
|
344
|
+
However, if you are using RSpec or Cucumber (and your app runs correctly without JS),
|
|
345
|
+
you may instead want to consider leaving the faster `:rack_test` as the __default_driver__, and
|
|
346
|
+
marking only those tests that require a JavaScript-capable driver using `js: true` or
|
|
347
347
|
`@javascript`, respectively. By default, JavaScript tests are run using the
|
|
348
348
|
`:selenium` driver. You can change this by setting
|
|
349
349
|
`Capybara.javascript_driver`.
|
|
@@ -352,7 +352,7 @@ You can also change the driver temporarily (typically in the Before/setup and
|
|
|
352
352
|
After/teardown blocks):
|
|
353
353
|
|
|
354
354
|
```ruby
|
|
355
|
-
Capybara.current_driver = :
|
|
355
|
+
Capybara.current_driver = :selenium # temporarily select different driver
|
|
356
356
|
# tests here
|
|
357
357
|
Capybara.use_default_driver # switch back to default driver
|
|
358
358
|
```
|
|
@@ -387,42 +387,26 @@ See the section on adding and configuring drivers.
|
|
|
387
387
|
|
|
388
388
|
### <a name="selenium"></a>Selenium
|
|
389
389
|
|
|
390
|
-
|
|
391
|
-
(Webdriver)](
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
Provided Firefox is installed, everything is set up for you, and you should be
|
|
395
|
-
able to start using Selenium right away.
|
|
396
|
-
|
|
397
|
-
**Note**: drivers which run the server in a different thread may not share the
|
|
398
|
-
same transaction as your tests, causing data not to be shared between your test
|
|
399
|
-
and test server, see "Transactions and database setup" below.
|
|
400
|
-
|
|
401
|
-
### <a name="capybara-webkit"></a>Capybara-webkit
|
|
390
|
+
Capybara supports [Selenium 3.5+
|
|
391
|
+
(Webdriver)](https://www.seleniumhq.org/projects/webdriver/).
|
|
392
|
+
In order to use Selenium, you'll need to install the `selenium-webdriver` gem,
|
|
393
|
+
and add it to your Gemfile if you're using bundler.
|
|
402
394
|
|
|
403
|
-
|
|
404
|
-
testing. It uses QtWebKit to start a rendering engine process. It can execute JavaScript as well.
|
|
405
|
-
It is significantly faster than drivers like Selenium since it does not load an entire browser.
|
|
395
|
+
Capybara pre-registers a number of named drivers that use Selenium - they are:
|
|
406
396
|
|
|
407
|
-
|
|
397
|
+
* :selenium => Selenium driving Firefox
|
|
398
|
+
* :selenium_headless => Selenium driving Firefox in a headless configuration
|
|
399
|
+
* :selenium_chrome => Selenium driving Chrome
|
|
400
|
+
* :selenium_chrome_headless => Selenium driving Chrome in a headless configuration
|
|
408
401
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
402
|
+
These should work (with relevant software installation) in a local desktop configuration but you may
|
|
403
|
+
need to customize them if using in a CI environment where additional options may need to be passed
|
|
404
|
+
to the browsers. See the section on adding and configuring drivers.
|
|
412
405
|
|
|
413
|
-
And you can use it by:
|
|
414
406
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
### <a name="poltergeist"></a>Poltergeist
|
|
420
|
-
|
|
421
|
-
[Poltergeist](https://github.com/teampoltergeist/poltergeist) is another
|
|
422
|
-
headless driver which integrates Capybara with
|
|
423
|
-
[PhantomJS](http://phantomjs.org/). It is truly headless, so doesn't
|
|
424
|
-
require Xvfb to run on your CI server. It will also detect and report
|
|
425
|
-
any Javascript errors that happen within the page.
|
|
407
|
+
**Note**: drivers which run the server in a different thread may not share the
|
|
408
|
+
same transaction as your tests, causing data not to be shared between your test
|
|
409
|
+
and test server, see [Transactions and database setup](#transactions-and-database-setup) below.
|
|
426
410
|
|
|
427
411
|
## <a name="the-dsl"></a>The DSL
|
|
428
412
|
|
|
@@ -617,21 +601,31 @@ In drivers which support it, you can easily execute JavaScript:
|
|
|
617
601
|
page.execute_script("$('body').empty()")
|
|
618
602
|
```
|
|
619
603
|
|
|
620
|
-
For simple expressions, you can return the result of the script.
|
|
621
|
-
that this may break with more complicated expressions:
|
|
604
|
+
For simple expressions, you can return the result of the script.
|
|
622
605
|
|
|
623
606
|
```ruby
|
|
624
607
|
result = page.evaluate_script('4 + 4');
|
|
625
608
|
```
|
|
626
609
|
|
|
610
|
+
For more complicated scripts you'll need to write them as one expression.
|
|
611
|
+
|
|
612
|
+
```ruby
|
|
613
|
+
result = page.evaluate_script(<<~JS, 3, element)
|
|
614
|
+
(function(n, el){
|
|
615
|
+
var val = parseInt(el.value, 10);
|
|
616
|
+
return n+val;
|
|
617
|
+
})(arguments[0], arguments[1])
|
|
618
|
+
JS
|
|
619
|
+
```
|
|
620
|
+
|
|
627
621
|
### <a name="modals"></a>Modals
|
|
628
622
|
|
|
629
|
-
In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.
|
|
623
|
+
In drivers which support it, you can accept, dismiss and respond to alerts, confirms, and prompts.
|
|
630
624
|
|
|
631
|
-
You can accept
|
|
625
|
+
You can accept alert messages by wrapping the code that produces an alert in a block:
|
|
632
626
|
|
|
633
627
|
```ruby
|
|
634
|
-
accept_alert do
|
|
628
|
+
accept_alert 'optional text or regex' do
|
|
635
629
|
click_link('Show Alert')
|
|
636
630
|
end
|
|
637
631
|
```
|
|
@@ -639,7 +633,13 @@ end
|
|
|
639
633
|
You can accept or dismiss a confirmation by wrapping it in a block, as well:
|
|
640
634
|
|
|
641
635
|
```ruby
|
|
642
|
-
|
|
636
|
+
accept_confirm 'optional text' do
|
|
637
|
+
click_link('Show Confirm')
|
|
638
|
+
end
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
```ruby
|
|
642
|
+
dismiss_confirm 'optional text' do
|
|
643
643
|
click_link('Show Confirm')
|
|
644
644
|
end
|
|
645
645
|
```
|
|
@@ -647,7 +647,13 @@ end
|
|
|
647
647
|
You can accept or dismiss prompts as well, and also provide text to fill in for the response:
|
|
648
648
|
|
|
649
649
|
```ruby
|
|
650
|
-
accept_prompt(with: 'Linus Torvalds') do
|
|
650
|
+
accept_prompt('optional text', with: 'Linus Torvalds') do
|
|
651
|
+
click_link('Show Prompt About Linux')
|
|
652
|
+
end
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
```ruby
|
|
656
|
+
dismiss_prompt('optional text') do
|
|
651
657
|
click_link('Show Prompt About Linux')
|
|
652
658
|
end
|
|
653
659
|
```
|
|
@@ -697,6 +703,148 @@ Screenshots are saved to `Capybara.save_path`, relative to the app directory.
|
|
|
697
703
|
If you have required `capybara/rails`, `Capybara.save_path` will default to
|
|
698
704
|
`tmp/capybara`.
|
|
699
705
|
|
|
706
|
+
## <a name="selectors"></a>Selectors
|
|
707
|
+
|
|
708
|
+
Helpers and matchers that accept Selectors share a common method signature that
|
|
709
|
+
includes:
|
|
710
|
+
|
|
711
|
+
1. a positional Name argument
|
|
712
|
+
2. a positional Locator argument
|
|
713
|
+
3. keyword Filter arguments
|
|
714
|
+
4. a predicate Filter block argument
|
|
715
|
+
|
|
716
|
+
These arguments are usually optional in one way or another.
|
|
717
|
+
|
|
718
|
+
### <a name="selectors-name"></a>Name
|
|
719
|
+
|
|
720
|
+
The name argument determines the Selector to use. The argument is optional when
|
|
721
|
+
a helper explicitly conveys the selector name (for example, [`find_field`][]
|
|
722
|
+
uses `:field`, [`find_link`][] uses `:link`, etc):
|
|
723
|
+
|
|
724
|
+
```ruby
|
|
725
|
+
page.html # => '<a href="/">Home</a>'
|
|
726
|
+
|
|
727
|
+
page.find(:link) == page.find_link
|
|
728
|
+
|
|
729
|
+
page.html # => '<input>'
|
|
730
|
+
|
|
731
|
+
page.find(:field) == page.find_field
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
### <a name="selectors-locator"></a>Locator
|
|
735
|
+
|
|
736
|
+
The locator argument usually represents information that can most meaningfully
|
|
737
|
+
distinguish an element that matches the selector from an element that does not:
|
|
738
|
+
|
|
739
|
+
```ruby
|
|
740
|
+
page.html # => '<div id="greeting">Hello world</div>'
|
|
741
|
+
|
|
742
|
+
page.find(:css, 'div').text # => 'Hello world'
|
|
743
|
+
page.find(:xpath, './/div').text # => 'Hello world'
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
General purpose finder methods like [`find`][] and [`all`][] can accept the
|
|
747
|
+
locator as their first positional argument when the method can infer the default
|
|
748
|
+
value from the [`Capybara.default_selector`][] configuration:
|
|
749
|
+
|
|
750
|
+
```ruby
|
|
751
|
+
page.html # => '<div id="greeting">Hello world</div>'
|
|
752
|
+
|
|
753
|
+
Capybara.default_selector = :css
|
|
754
|
+
|
|
755
|
+
page.find('div').text # => 'Hello world'
|
|
756
|
+
|
|
757
|
+
Capybara.default_selector = :xpath
|
|
758
|
+
|
|
759
|
+
page.find('.//div').text # => 'Hello world'
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
The locator argument's semantics are context-specific, and depend on the
|
|
763
|
+
selector. The types of arguments are varied. Some selectors support `String` or
|
|
764
|
+
`Regexp` arguments, while others like `:table_row` support `Array<String>` and
|
|
765
|
+
`Hash<String, String>`:
|
|
766
|
+
|
|
767
|
+
```ruby
|
|
768
|
+
page.html # => '<label for="greeting">Greeting</label>
|
|
769
|
+
<input id="greeting" name="content">'
|
|
770
|
+
|
|
771
|
+
# find by the <input> element's [id] attribute
|
|
772
|
+
page.find(:id, 'greeting') == page.find_by_id('greeting') # => true
|
|
773
|
+
|
|
774
|
+
# find by the <input> element's [id] attribute
|
|
775
|
+
page.find(:field, 'greeting') == page.find_field('greeting') # => true
|
|
776
|
+
|
|
777
|
+
# find by the <input> element's [name] attribute
|
|
778
|
+
page.find(:field, 'content') == page.find_field('content') # => true
|
|
779
|
+
|
|
780
|
+
# find by the <label> element's text
|
|
781
|
+
page.find(:field, 'Greeting') == page.find_field('Greeting') # => true
|
|
782
|
+
|
|
783
|
+
page.html # => '<table>
|
|
784
|
+
<tr>
|
|
785
|
+
<th>A</th>
|
|
786
|
+
<th>B</th>
|
|
787
|
+
</tr>
|
|
788
|
+
<tr>
|
|
789
|
+
<td>1</td>
|
|
790
|
+
<td>2</td>
|
|
791
|
+
</tr>
|
|
792
|
+
</table>'
|
|
793
|
+
|
|
794
|
+
# find by <td> content
|
|
795
|
+
page.find(:table_row, ['1', '2']) == page.find(:css, 'tr:last-of-type') # => true
|
|
796
|
+
|
|
797
|
+
# find by <th> content paired with corresponding <td> content
|
|
798
|
+
page.find(:table_row, 'A' => '1') == page.find(:table_row, 'B' => '2') # => true
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### <a name="selectors-filters"></a> Filters
|
|
802
|
+
|
|
803
|
+
All filters are optional. The supported set of keys is a mixture of both global
|
|
804
|
+
and context-specific filters.The supported types of values depend on the
|
|
805
|
+
context:
|
|
806
|
+
|
|
807
|
+
```ruby
|
|
808
|
+
page.html # => '<a href="/">Home</a>'
|
|
809
|
+
|
|
810
|
+
# find by the [href] attribute
|
|
811
|
+
page.find_link(href: '/') == page.find_link(text: 'Home') # => true
|
|
812
|
+
|
|
813
|
+
page.html # => '<div id="element" data-attribute="value">Content</div>'
|
|
814
|
+
|
|
815
|
+
# find by the [id] attribute
|
|
816
|
+
page.find(id: 'element') == page.find(text: 'Content') # => true
|
|
817
|
+
|
|
818
|
+
# find by the [data-attribute] attribute
|
|
819
|
+
page.find(:element, 'data-attribute': /value/) == page.find(text: 'Content') # => true
|
|
820
|
+
|
|
821
|
+
page.html # => '<input type="checkbox">'
|
|
822
|
+
|
|
823
|
+
# find by the absence of the [checked] attribute
|
|
824
|
+
page.find_field(checked: false) == page.find_field(unchecked: true) # => true
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
The predicate block is always optional. When there are results for a selector
|
|
828
|
+
query, the block is called with each item in the result set. When the block
|
|
829
|
+
evaluates to true, the item is included from the result set. Otherwise, the item
|
|
830
|
+
is excluded:
|
|
831
|
+
|
|
832
|
+
```ruby
|
|
833
|
+
page.html # => '<input role="switch" type="checkbox" checked>'
|
|
834
|
+
|
|
835
|
+
switch = page.find_field { |input| input["role"] == "switch" }
|
|
836
|
+
field = page.find_field(checked: true)
|
|
837
|
+
|
|
838
|
+
switch == field # => true
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
[`find`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find
|
|
842
|
+
[`all`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:all
|
|
843
|
+
[`Capybara.default_selector`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara%2Econfigure
|
|
844
|
+
[`find_by_id`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_by_id
|
|
845
|
+
[`find_field`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_field
|
|
846
|
+
[`find_link`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_link
|
|
847
|
+
|
|
700
848
|
## <a name="matching"></a>Matching
|
|
701
849
|
|
|
702
850
|
It is possible to customize how Capybara finds elements. At your disposal
|
|
@@ -777,7 +925,7 @@ expect(page).to have_content('baz')
|
|
|
777
925
|
If clicking on the *foo* link triggers an asynchronous process, such as
|
|
778
926
|
an Ajax request, which, when complete will add the *bar* link to the page,
|
|
779
927
|
clicking on the *bar* link would be expected to fail, since that link doesn't
|
|
780
|
-
exist yet. However Capybara is smart enough to retry finding the link for a
|
|
928
|
+
exist yet. However, Capybara is smart enough to retry finding the link for a
|
|
781
929
|
brief period of time before giving up and throwing an error. The same is true of
|
|
782
930
|
the next line, which looks for the content *baz* on the page; it will retry
|
|
783
931
|
looking for that content for a brief time. You can adjust how long this period
|
|
@@ -791,13 +939,25 @@ Be aware that because of this behaviour, the following two statements are **not*
|
|
|
791
939
|
equivalent, and you should **always** use the latter!
|
|
792
940
|
|
|
793
941
|
```ruby
|
|
794
|
-
|
|
795
|
-
|
|
942
|
+
# Given use of a driver where the page is loaded when visit returns
|
|
943
|
+
# and that Capybara.predicates_wait is `true`
|
|
944
|
+
# consider a page where the `a` tag is removed through AJAX after 1s
|
|
945
|
+
visit(some_path)
|
|
946
|
+
!page.has_xpath?('a') # is false
|
|
947
|
+
page.has_no_xpath?('a') # is true
|
|
796
948
|
```
|
|
797
949
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
950
|
+
First expression:
|
|
951
|
+
- `has_xpath?('a')` is called right after `visit` returns. It is `true` because the link has not yet been removed
|
|
952
|
+
- Capybara does not wait upon successful predicates/assertions, therefore **has_xpath? returns `true` immediately**
|
|
953
|
+
- The expression returns `false` (because it is negated with the leading `!`)
|
|
954
|
+
|
|
955
|
+
Second expression:
|
|
956
|
+
- `has_no_xpath?('a')` is called right after `visit` returns. It is `false` because the link has not yet been removed.
|
|
957
|
+
- Capybara waits upon failed predicates/assertions, therefore **has_no_xpath? does not return `false` immediately**
|
|
958
|
+
- Capybara will periodically re-check the predicate/assertion up to the `default_max_wait_time` defined
|
|
959
|
+
- after 1s, the predicate becomes `true` (because the link has been removed)
|
|
960
|
+
- The expression returns `true`
|
|
801
961
|
|
|
802
962
|
Capybara's RSpec matchers, however, are smart enough to handle either form.
|
|
803
963
|
The two following statements are functionally equivalent:
|
|
@@ -932,12 +1092,17 @@ Capybara.default_selector = :xpath
|
|
|
932
1092
|
find('.//ul/li').text
|
|
933
1093
|
```
|
|
934
1094
|
|
|
935
|
-
Capybara
|
|
936
|
-
|
|
1095
|
+
Capybara provides a number of other built-in selector types. The full list, along
|
|
1096
|
+
with applicable filters, can be seen at [built-in selectors](https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Selector)
|
|
1097
|
+
|
|
1098
|
+
Capybara also allows you to add custom selectors, which can be very useful if you
|
|
1099
|
+
find yourself using the same kinds of selectors very often. The examples below are very
|
|
1100
|
+
simple, and there are many available features not demonstrated. For more in-depth examples
|
|
1101
|
+
please see Capybaras built-in selector definitions.
|
|
937
1102
|
|
|
938
1103
|
```ruby
|
|
939
|
-
Capybara.add_selector(:
|
|
940
|
-
xpath { |id| XPath.descendant[XPath.attr(:
|
|
1104
|
+
Capybara.add_selector(:my_attribute) do
|
|
1105
|
+
xpath { |id| XPath.descendant[XPath.attr(:my_attribute) == id.to_s] }
|
|
941
1106
|
end
|
|
942
1107
|
|
|
943
1108
|
Capybara.add_selector(:row) do
|
|
@@ -954,9 +1119,9 @@ an XPath expression generated through the XPath gem. You can now use these
|
|
|
954
1119
|
selectors like this:
|
|
955
1120
|
|
|
956
1121
|
```ruby
|
|
957
|
-
find(:
|
|
958
|
-
find(:row, 3)
|
|
959
|
-
find(:flash_type, :notice)
|
|
1122
|
+
find(:my_attribute, 'post_123') # find element with matching attribute
|
|
1123
|
+
find(:row, 3) # find 3rd row in table body
|
|
1124
|
+
find(:flash_type, :notice) # find element with id of 'flash' and class of 'notice'
|
|
960
1125
|
```
|
|
961
1126
|
|
|
962
1127
|
## <a name="beware-the-xpath--trap"></a>Beware the XPath // trap
|
|
@@ -1002,6 +1167,7 @@ end
|
|
|
1002
1167
|
However, it's also possible to give this configuration a different name.
|
|
1003
1168
|
|
|
1004
1169
|
```ruby
|
|
1170
|
+
# Note: Capybara registers this by default
|
|
1005
1171
|
Capybara.register_driver :selenium_chrome do |app|
|
|
1006
1172
|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
|
|
1007
1173
|
end
|
|
@@ -1047,6 +1213,13 @@ additional info about how the underlying driver can be configured.
|
|
|
1047
1213
|
are testing for specific server errors and using multiple sessions make sure to test for the
|
|
1048
1214
|
errors using the initial session (usually :default)
|
|
1049
1215
|
|
|
1216
|
+
* If WebMock is enabled, you may encounter a "Too many open files"
|
|
1217
|
+
error. A simple `page.find` call may cause thousands of HTTP requests
|
|
1218
|
+
until the timeout occurs. By default, WebMock will cause each of these
|
|
1219
|
+
requests to spawn a new connection. To work around this problem, you
|
|
1220
|
+
may need to [enable WebMock's `net_http_connect_on_start: true`
|
|
1221
|
+
parameter](https://github.com/bblimke/webmock/blob/master/README.md#connecting-on-nethttpstart).
|
|
1222
|
+
|
|
1050
1223
|
## <a name="threadsafe"></a>"Threadsafe" mode
|
|
1051
1224
|
|
|
1052
1225
|
In normal mode most of Capybara's configuration options are global settings which can cause issues
|
data/lib/capybara/config.rb
CHANGED
|
@@ -7,11 +7,12 @@ module Capybara
|
|
|
7
7
|
class Config
|
|
8
8
|
extend Forwardable
|
|
9
9
|
|
|
10
|
-
OPTIONS = %i[
|
|
10
|
+
OPTIONS = %i[
|
|
11
|
+
app reuse_server threadsafe server default_driver javascript_driver use_html5_parsing allow_gumbo
|
|
12
|
+
].freeze
|
|
11
13
|
|
|
12
|
-
attr_accessor :app
|
|
13
|
-
attr_reader :reuse_server, :threadsafe
|
|
14
|
-
attr_reader :session_options
|
|
14
|
+
attr_accessor :app, :use_html5_parsing
|
|
15
|
+
attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor
|
|
15
16
|
attr_writer :default_driver, :javascript_driver
|
|
16
17
|
|
|
17
18
|
SessionConfig::OPTIONS.each do |method|
|
|
@@ -23,10 +24,13 @@ module Capybara
|
|
|
23
24
|
@javascript_driver = nil
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
attr_writer :reuse_server
|
|
27
|
+
attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor
|
|
27
28
|
|
|
28
29
|
def threadsafe=(bool)
|
|
29
|
-
|
|
30
|
+
if (bool != threadsafe) && Session.instance_created?
|
|
31
|
+
raise 'Threadsafe setting cannot be changed once a session is created'
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
@threadsafe = bool
|
|
31
35
|
end
|
|
32
36
|
|
|
@@ -57,7 +61,7 @@ module Capybara
|
|
|
57
61
|
@server = if name.respond_to? :call
|
|
58
62
|
name
|
|
59
63
|
elsif options
|
|
60
|
-
proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, options) }
|
|
64
|
+
proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, **options) }
|
|
61
65
|
else
|
|
62
66
|
Capybara.servers[name.to_sym]
|
|
63
67
|
end
|
|
@@ -79,10 +83,22 @@ module Capybara
|
|
|
79
83
|
@javascript_driver || :selenium
|
|
80
84
|
end
|
|
81
85
|
|
|
82
|
-
def deprecate(method, alternate_method, once
|
|
86
|
+
def deprecate(method, alternate_method, once: false)
|
|
83
87
|
@deprecation_notified ||= {}
|
|
84
|
-
|
|
88
|
+
unless once && @deprecation_notified[method]
|
|
89
|
+
Capybara::Helpers.warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead: #{Capybara::Helpers.filter_backtrace(caller)}"
|
|
90
|
+
end
|
|
85
91
|
@deprecation_notified[method] = true
|
|
86
92
|
end
|
|
93
|
+
|
|
94
|
+
def allow_gumbo=(val)
|
|
95
|
+
deprecate('allow_gumbo=', 'use_html5_parsing=')
|
|
96
|
+
self.use_html5_parsing = val
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def allow_gumbo
|
|
100
|
+
deprecate('allow_gumbo', 'use_html5_parsing')
|
|
101
|
+
use_html5_parsing
|
|
102
|
+
end
|
|
87
103
|
end
|
|
88
104
|
end
|
data/lib/capybara/cucumber.rb
CHANGED
|
@@ -22,6 +22,6 @@ end
|
|
|
22
22
|
Before do |scenario|
|
|
23
23
|
scenario.source_tag_names.each do |tag|
|
|
24
24
|
driver_name = tag.sub(/^@/, '').to_sym
|
|
25
|
-
Capybara.current_driver = driver_name if Capybara.drivers
|
|
25
|
+
Capybara.current_driver = driver_name if Capybara.drivers[driver_name]
|
|
26
26
|
end
|
|
27
27
|
end
|