capybara 3.0.0 → 3.36.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 +777 -10
- data/License.txt +1 -1
- data/README.md +75 -58
- data/lib/capybara/config.rb +29 -10
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +22 -4
- data/lib/capybara/driver/node.rb +34 -9
- data/lib/capybara/dsl.rb +14 -6
- data/lib/capybara/helpers.rb +52 -7
- data/lib/capybara/minitest/spec.rb +173 -84
- data/lib/capybara/minitest.rb +250 -144
- data/lib/capybara/node/actions.rb +248 -124
- data/lib/capybara/node/base.rb +34 -20
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +13 -15
- data/lib/capybara/node/element.rb +339 -113
- data/lib/capybara/node/finders.rb +95 -82
- data/lib/capybara/node/matchers.rb +338 -157
- data/lib/capybara/node/simple.rb +54 -15
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +9 -10
- data/lib/capybara/queries/base_query.rb +25 -18
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +11 -0
- data/lib/capybara/queries/selector_query.rb +600 -103
- data/lib/capybara/queries/sibling_query.rb +9 -7
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +40 -22
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +47 -28
- data/lib/capybara/rack_test/driver.rb +12 -3
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +53 -50
- data/lib/capybara/rack_test/node.rb +114 -37
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/registration_container.rb +44 -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 +45 -0
- data/lib/capybara/result.rb +86 -52
- data/lib/capybara/rspec/features.rb +8 -10
- data/lib/capybara/rspec/matcher_proxies.rb +39 -18
- data/lib/capybara/rspec/matchers/base.rb +111 -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 +77 -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 +138 -316
- data/lib/capybara/rspec.rb +3 -2
- 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 +89 -12
- 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 +54 -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 +279 -0
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +72 -27
- data/lib/capybara/selector/filters/base.rb +45 -2
- data/lib/capybara/selector/filters/expression_filter.rb +5 -6
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +18 -4
- data/lib/capybara/selector/regexp_disassembler.rb +214 -0
- data/lib/capybara/selector/selector.rb +85 -200
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +226 -537
- 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 +296 -238
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -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 +228 -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/logger_suppressor.rb +40 -0
- data/lib/capybara/selenium/node.rb +436 -166
- data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +104 -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/action_pauser.rb +26 -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 +69 -0
- data/lib/capybara/server/checker.rb +44 -0
- data/lib/capybara/server/middleware.rb +71 -0
- data/lib/capybara/server.rb +58 -67
- data/lib/capybara/session/config.rb +38 -6
- data/lib/capybara/session/matchers.rb +26 -19
- data/lib/capybara/session.rb +258 -190
- 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 +122 -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 +135 -42
- 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.rb → assert_current_path_spec.rb} +20 -18
- 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.rb → assert_text_spec.rb} +62 -38
- data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +120 -72
- data/lib/capybara/spec/session/body_spec.rb +11 -13
- data/lib/capybara/spec/session/check_spec.rb +111 -51
- data/lib/capybara/spec/session/choose_spec.rb +62 -30
- data/lib/capybara/spec/session/click_button_spec.rb +227 -161
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
- data/lib/capybara/spec/session/click_link_spec.rb +78 -55
- data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
- data/lib/capybara/spec/session/current_url_spec.rb +44 -37
- 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.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 +8 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -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 +104 -44
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
- data/lib/capybara/spec/session/find_field_spec.rb +33 -31
- data/lib/capybara/spec/session/find_link_spec.rb +32 -14
- data/lib/capybara/spec/session/find_spec.rb +236 -141
- data/lib/capybara/spec/session/first_spec.rb +44 -43
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +44 -19
- 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 +18 -18
- 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 +92 -12
- data/lib/capybara/spec/session/has_css_spec.rb +271 -137
- data/lib/capybara/spec/session/has_current_path_spec.rb +48 -33
- data/lib/capybara/spec/session/has_field_spec.rb +137 -58
- data/lib/capybara/spec/session/has_link_spec.rb +30 -6
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +26 -24
- data/lib/capybara/spec/session/has_select_spec.rb +75 -47
- data/lib/capybara/spec/session/has_selector_spec.rb +102 -69
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +170 -4
- data/lib/capybara/spec/session/has_text_spec.rb +108 -52
- 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.rb → headers_spec.rb} +1 -1
- data/lib/capybara/spec/session/html_spec.rb +13 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
- data/lib/capybara/spec/session/node_spec.rb +871 -122
- data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +52 -37
- data/lib/capybara/spec/session/{response_code.rb → 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 +5 -4
- data/lib/capybara/spec/session/save_page_spec.rb +41 -38
- data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
- data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/scroll_spec.rb +117 -0
- data/lib/capybara/spec/session/select_spec.rb +102 -76
- data/lib/capybara/spec/session/selectors_spec.rb +51 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +26 -24
- data/lib/capybara/spec/session/title_spec.rb +8 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +40 -21
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +59 -53
- data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
- data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
- data/lib/capybara/spec/session/window/window_spec.rb +88 -54
- data/lib/capybara/spec/session/window/windows_spec.rb +10 -7
- data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
- data/lib/capybara/spec/session/within_spec.rb +69 -44
- data/lib/capybara/spec/spec_helper.rb +41 -53
- data/lib/capybara/spec/test_app.rb +79 -40
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +134 -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 +43 -10
- 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_other.erb +6 -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 +31 -25
- data/lib/capybara.rb +120 -100
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +54 -52
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +80 -53
- data/spec/filter_set_spec.rb +24 -7
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- 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 +38 -5
- data/spec/minitest_spec_spec.rb +88 -62
- data/spec/per_session_config_spec.rb +5 -5
- data/spec/rack_test_spec.rb +169 -115
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +86 -33
- data/spec/rspec/features_spec.rb +26 -23
- data/spec/rspec/scenarios_spec.rb +8 -4
- data/spec/rspec/shared_spec_matchers.rb +393 -363
- data/spec/rspec/views_spec.rb +4 -3
- data/spec/rspec_matchers_spec.rb +10 -10
- data/spec/rspec_spec.rb +109 -85
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +391 -61
- data/spec/selenium_spec_chrome.rb +180 -41
- data/spec/selenium_spec_chrome_remote.rb +101 -0
- data/spec/selenium_spec_edge.rb +28 -8
- data/spec/selenium_spec_firefox.rb +211 -0
- data/spec/selenium_spec_firefox_remote.rb +80 -0
- data/spec/selenium_spec_ie.rb +127 -11
- data/spec/selenium_spec_safari.rb +156 -0
- data/spec/server_spec.rb +177 -78
- data/spec/session_spec.rb +52 -16
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +455 -123
- data/spec/spec_helper.rb +91 -2
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +343 -42
- 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/rspec/compound.rb +0 -90
- data/lib/capybara/spec/session/assert_selector.rb +0 -149
- 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 -143
data/lib/capybara/window.rb
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Capybara
|
|
4
4
|
##
|
|
5
|
-
# The Window class represents a browser window.
|
|
5
|
+
# The {Window} class represents a browser window.
|
|
6
6
|
#
|
|
7
|
-
# You can get an instance of the class by calling
|
|
7
|
+
# You can get an instance of the class by calling any of:
|
|
8
8
|
#
|
|
9
9
|
# * {Capybara::Session#windows}
|
|
10
10
|
# * {Capybara::Session#current_window}
|
|
@@ -12,12 +12,12 @@ module Capybara
|
|
|
12
12
|
# * {Capybara::Session#switch_to_window}
|
|
13
13
|
#
|
|
14
14
|
# Note that some drivers (e.g. Selenium) support getting size of/resizing/closing only
|
|
15
|
-
#
|
|
15
|
+
# current window. So if you invoke such method for:
|
|
16
16
|
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
17
|
+
# * window that is current, Capybara will make 2 Selenium method invocations
|
|
18
|
+
# (get handle of current window + get size/resize/close).
|
|
19
|
+
# * window that is not current, Capybara will make 4 Selenium method invocations
|
|
20
|
+
# (get handle of current window + switch to given handle + get size/resize/close + switch to original handle)
|
|
21
21
|
#
|
|
22
22
|
class Window
|
|
23
23
|
# @return [String] a string that uniquely identifies window within session
|
|
@@ -57,12 +57,12 @@ module Capybara
|
|
|
57
57
|
# Close window.
|
|
58
58
|
#
|
|
59
59
|
# If this method was called for window that is current, then after calling this method
|
|
60
|
-
#
|
|
61
|
-
#
|
|
60
|
+
# future invocations of other Capybara methods should raise
|
|
61
|
+
# {Capybara::Driver::Base#no_such_window_error session.driver.no_such_window_error} until another window will be switched to.
|
|
62
62
|
#
|
|
63
63
|
# @!macro about_current
|
|
64
64
|
# If this method was called for window that is not current, then after calling this method
|
|
65
|
-
# current window
|
|
65
|
+
# current window should remain the same as it was before calling this method.
|
|
66
66
|
#
|
|
67
67
|
def close
|
|
68
68
|
@driver.close_window(handle)
|
|
@@ -82,8 +82,8 @@ module Capybara
|
|
|
82
82
|
# Resize window.
|
|
83
83
|
#
|
|
84
84
|
# @macro about_current
|
|
85
|
-
# @param width [
|
|
86
|
-
# @param height [
|
|
85
|
+
# @param width [Integer] the new window width in pixels
|
|
86
|
+
# @param height [Integer] the new window height in pixels
|
|
87
87
|
#
|
|
88
88
|
def resize_to(width, height)
|
|
89
89
|
wait_for_stable_size { @driver.resize_window_to(handle, width, height) }
|
|
@@ -93,7 +93,7 @@ module Capybara
|
|
|
93
93
|
# Maximize window.
|
|
94
94
|
#
|
|
95
95
|
# If a particular driver (e.g. headless driver) doesn't have concept of maximizing it
|
|
96
|
-
#
|
|
96
|
+
# may not support this method.
|
|
97
97
|
#
|
|
98
98
|
# @macro about_current
|
|
99
99
|
#
|
|
@@ -101,6 +101,17 @@ module Capybara
|
|
|
101
101
|
wait_for_stable_size { @driver.maximize_window(handle) }
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
##
|
|
105
|
+
# Fullscreen window.
|
|
106
|
+
#
|
|
107
|
+
# If a particular driver doesn't have concept of fullscreen it may not support this method.
|
|
108
|
+
#
|
|
109
|
+
# @macro about_current
|
|
110
|
+
#
|
|
111
|
+
def fullscreen
|
|
112
|
+
@driver.fullscreen_window(handle)
|
|
113
|
+
end
|
|
114
|
+
|
|
104
115
|
def eql?(other)
|
|
105
116
|
other.is_a?(self.class) && @session == other.session && @handle == other.handle
|
|
106
117
|
end
|
|
@@ -118,19 +129,14 @@ module Capybara
|
|
|
118
129
|
|
|
119
130
|
def wait_for_stable_size(seconds = session.config.default_max_wait_time)
|
|
120
131
|
res = yield if block_given?
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
sleep 0.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
end while (Capybara::Helpers.monotonic_time - start_time) < seconds
|
|
132
|
+
timer = Capybara::Helpers.timer(expire_in: seconds)
|
|
133
|
+
loop do
|
|
134
|
+
prev_size = size
|
|
135
|
+
sleep 0.025
|
|
136
|
+
return res if prev_size == size
|
|
137
|
+
break if timer.expired?
|
|
138
|
+
end
|
|
129
139
|
raise Capybara::WindowError, "Window size not stable within #{seconds} seconds."
|
|
130
140
|
end
|
|
131
|
-
|
|
132
|
-
def raise_unless_current(what)
|
|
133
|
-
raise Capybara::WindowError, "#{what} not current window is not possible." unless current?
|
|
134
|
-
end
|
|
135
141
|
end
|
|
136
142
|
end
|
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,6 +39,8 @@ module Capybara
|
|
|
38
39
|
# See {Capybara.configure}
|
|
39
40
|
# @!method javascript_driver
|
|
40
41
|
# See {Capybara.configure}
|
|
42
|
+
# @!method use_html5_parsing
|
|
43
|
+
# See {Capybara.configure}
|
|
41
44
|
Config::OPTIONS.each do |method|
|
|
42
45
|
def_delegators :config, method, "#{method}="
|
|
43
46
|
end
|
|
@@ -64,31 +67,47 @@ module Capybara
|
|
|
64
67
|
# config.app_host = 'http://www.google.com'
|
|
65
68
|
# end
|
|
66
69
|
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
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_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
|
|
83
|
+
# - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
|
|
84
|
+
# - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
|
|
85
|
+
# - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).
|
|
86
|
+
# - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions
|
|
87
|
+
# written using the `XPath#is` method.
|
|
88
|
+
# - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.
|
|
89
|
+
# - **ignore_hidden_elements** (Boolean = `true`) - Whether to ignore hidden elements on the page.
|
|
90
|
+
# - **match** (`:one`, `:first`, `:prefer_exact`, `:smart` = `:smart`) - The matching strategy to find nodes.
|
|
91
|
+
# - **predicates_wait** (Boolean = `true`) - Whether Capybara's predicate matchers use waiting behavior by default.
|
|
92
|
+
# - **raise_server_errors** (Boolean = `true`) - Should errors raised in the server be raised in the tests?
|
|
93
|
+
# - **reuse_server** (Boolean = `true`) - Whether to reuse the server thread between multiple sessions using the same app object.
|
|
94
|
+
# - **run_server** (Boolean = `true`) - Whether to start a Rack server for the given Rack app.
|
|
95
|
+
# - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},
|
|
96
|
+
# {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
|
|
97
|
+
# - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
|
|
98
|
+
# - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
|
|
99
|
+
# - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
|
|
100
|
+
# and {configure raise_server_errors} is `true`.
|
|
101
|
+
# - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
|
|
102
|
+
# - **threadsafe** (Boolean = `false`) - Whether sessions can be configured individually.
|
|
103
|
+
# - **w3c_click_offset** (Boolean = 'false') - Whether click offsets should be from element center (true) or top left (false)
|
|
104
|
+
#
|
|
105
|
+
# #### DSL Options
|
|
106
|
+
#
|
|
107
|
+
# When using `capybara/dsl`, the following options are also available:
|
|
108
|
+
#
|
|
109
|
+
# - **default_driver** (Symbol = `:rack_test`) - The name of the driver to use by default.
|
|
110
|
+
# - **javascript_driver** (Symbol = `:selenium`) - The name of a driver to use for JavaScript enabled tests.
|
|
92
111
|
#
|
|
93
112
|
def configure
|
|
94
113
|
yield config
|
|
@@ -108,7 +127,7 @@ module Capybara
|
|
|
108
127
|
# @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
|
|
109
128
|
#
|
|
110
129
|
def register_driver(name, &block)
|
|
111
|
-
drivers
|
|
130
|
+
drivers.send(:register, name, block)
|
|
112
131
|
end
|
|
113
132
|
|
|
114
133
|
##
|
|
@@ -127,7 +146,7 @@ module Capybara
|
|
|
127
146
|
# @yieldparam host The host/ip to bind to
|
|
128
147
|
#
|
|
129
148
|
def register_server(name, &block)
|
|
130
|
-
servers
|
|
149
|
+
servers.send(:register, name.to_sym, block)
|
|
131
150
|
end
|
|
132
151
|
|
|
133
152
|
##
|
|
@@ -158,8 +177,8 @@ module Capybara
|
|
|
158
177
|
# @param [Symbol] name The name of the selector to add
|
|
159
178
|
# @yield A block executed in the context of the new {Capybara::Selector}
|
|
160
179
|
#
|
|
161
|
-
def add_selector(name, &block)
|
|
162
|
-
Capybara::Selector.add(name, &block)
|
|
180
|
+
def add_selector(name, **options, &block)
|
|
181
|
+
Capybara::Selector.add(name, **options, &block)
|
|
163
182
|
end
|
|
164
183
|
|
|
165
184
|
##
|
|
@@ -169,7 +188,7 @@ module Capybara
|
|
|
169
188
|
# button style (a class) might look like this
|
|
170
189
|
#
|
|
171
190
|
# Capybara.modify_selector(:button) do
|
|
172
|
-
# filter (:
|
|
191
|
+
# filter (:btn_style, valid_values: [:primary, :secondary]) { |node, style| node[:class].split.include? "btn-#{style}" }
|
|
173
192
|
# end
|
|
174
193
|
#
|
|
175
194
|
#
|
|
@@ -181,11 +200,11 @@ module Capybara
|
|
|
181
200
|
end
|
|
182
201
|
|
|
183
202
|
def drivers
|
|
184
|
-
@drivers ||=
|
|
203
|
+
@drivers ||= RegistrationContainer.new
|
|
185
204
|
end
|
|
186
205
|
|
|
187
206
|
def servers
|
|
188
|
-
@servers ||=
|
|
207
|
+
@servers ||= RegistrationContainer.new
|
|
189
208
|
end
|
|
190
209
|
|
|
191
210
|
# Wraps the given string, which should contain an HTML document or fragment
|
|
@@ -194,15 +213,13 @@ module Capybara
|
|
|
194
213
|
# any string containing HTML in the exact same way you would query the current document in a Capybara
|
|
195
214
|
# session.
|
|
196
215
|
#
|
|
197
|
-
#
|
|
198
|
-
#
|
|
216
|
+
# @example A single element
|
|
199
217
|
# node = Capybara.string('<a href="foo">bar</a>')
|
|
200
218
|
# anchor = node.first('a')
|
|
201
219
|
# anchor[:href] #=> 'foo'
|
|
202
220
|
# anchor.text #=> 'bar'
|
|
203
221
|
#
|
|
204
|
-
#
|
|
205
|
-
#
|
|
222
|
+
# @example Multiple elements
|
|
206
223
|
# node = Capybara.string <<-HTML
|
|
207
224
|
# <ul>
|
|
208
225
|
# <li id="home">Home</li>
|
|
@@ -290,12 +307,12 @@ module Capybara
|
|
|
290
307
|
|
|
291
308
|
##
|
|
292
309
|
#
|
|
293
|
-
# The current Capybara::Session based on what is set as
|
|
310
|
+
# The current {Capybara::Session} based on what is set as {app} and {current_driver}.
|
|
294
311
|
#
|
|
295
312
|
# @return [Capybara::Session] The currently used session
|
|
296
313
|
#
|
|
297
314
|
def current_session
|
|
298
|
-
session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
|
|
315
|
+
specified_session || session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
|
|
299
316
|
end
|
|
300
317
|
|
|
301
318
|
##
|
|
@@ -333,22 +350,31 @@ module Capybara
|
|
|
333
350
|
|
|
334
351
|
##
|
|
335
352
|
#
|
|
336
|
-
# Yield a block using a specific session name.
|
|
353
|
+
# Yield a block using a specific session name or {Capybara::Session} instance.
|
|
337
354
|
#
|
|
338
|
-
def using_session(
|
|
355
|
+
def using_session(name_or_session, &block)
|
|
356
|
+
previous_session = current_session
|
|
339
357
|
previous_session_info = {
|
|
358
|
+
specified_session: specified_session,
|
|
340
359
|
session_name: session_name,
|
|
341
360
|
current_driver: current_driver,
|
|
342
361
|
app: app
|
|
343
362
|
}
|
|
344
|
-
self.session_name =
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
self.current_driver = previous_session_info[:current_driver]
|
|
350
|
-
self.app = previous_session_info[:app]
|
|
363
|
+
self.specified_session = self.session_name = nil
|
|
364
|
+
if name_or_session.is_a? Capybara::Session
|
|
365
|
+
self.specified_session = name_or_session
|
|
366
|
+
else
|
|
367
|
+
self.session_name = name_or_session
|
|
351
368
|
end
|
|
369
|
+
|
|
370
|
+
if block.arity.zero?
|
|
371
|
+
yield
|
|
372
|
+
else
|
|
373
|
+
yield current_session, previous_session
|
|
374
|
+
end
|
|
375
|
+
ensure
|
|
376
|
+
self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
|
|
377
|
+
self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
|
|
352
378
|
end
|
|
353
379
|
|
|
354
380
|
##
|
|
@@ -359,9 +385,21 @@ module Capybara
|
|
|
359
385
|
# @return [Nokogiri::HTML::Document] HTML document
|
|
360
386
|
#
|
|
361
387
|
def HTML(html) # rubocop:disable Naming/MethodName
|
|
362
|
-
Nokogiri
|
|
388
|
+
# Nokogiri >= 1.12.0 or Nokogumbo installed and allowed for use
|
|
389
|
+
html_parser, using_html5 = if defined?(Nokogiri::HTML5) && Capybara.use_html5_parsing
|
|
390
|
+
[Nokogiri::HTML5, true]
|
|
391
|
+
else
|
|
392
|
+
[defined?(Nokogiri::HTML4) ? Nokogiri::HTML4 : Nokogiri::HTML, false]
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
html_parser.parse(html).tap do |document|
|
|
396
|
+
document.xpath('//template').each do |template|
|
|
397
|
+
# template elements content is not part of the document
|
|
398
|
+
template.inner_html = ''
|
|
399
|
+
end
|
|
363
400
|
document.xpath('//textarea').each do |textarea|
|
|
364
|
-
|
|
401
|
+
# The Nokogiri HTML5 parser already returns spec compliant contents
|
|
402
|
+
textarea['_capybara_raw_value'] = using_html5 ? textarea.content : textarea.content.delete_prefix("\n")
|
|
365
403
|
end
|
|
366
404
|
end
|
|
367
405
|
end
|
|
@@ -377,7 +415,25 @@ module Capybara
|
|
|
377
415
|
end
|
|
378
416
|
|
|
379
417
|
def session_pool
|
|
380
|
-
@session_pool ||=
|
|
418
|
+
@session_pool ||= Hash.new do |hash, name|
|
|
419
|
+
hash[name] = Capybara::Session.new(current_driver, app)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def specified_session
|
|
424
|
+
if threadsafe
|
|
425
|
+
Thread.current['capybara_specified_session']
|
|
426
|
+
else
|
|
427
|
+
@specified_session ||= nil
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def specified_session=(session)
|
|
432
|
+
if threadsafe
|
|
433
|
+
Thread.current['capybara_specified_session'] = session
|
|
434
|
+
else
|
|
435
|
+
@specified_session = session
|
|
436
|
+
end
|
|
381
437
|
end
|
|
382
438
|
end
|
|
383
439
|
|
|
@@ -405,6 +461,8 @@ module Capybara
|
|
|
405
461
|
require 'capybara/queries/match_query'
|
|
406
462
|
require 'capybara/queries/ancestor_query'
|
|
407
463
|
require 'capybara/queries/sibling_query'
|
|
464
|
+
require 'capybara/queries/style_query'
|
|
465
|
+
require 'capybara/queries/active_element_query'
|
|
408
466
|
|
|
409
467
|
require 'capybara/node/finders'
|
|
410
468
|
require 'capybara/node/matchers'
|
|
@@ -422,40 +480,14 @@ module Capybara
|
|
|
422
480
|
require 'capybara/rack_test/node'
|
|
423
481
|
require 'capybara/rack_test/form'
|
|
424
482
|
require 'capybara/rack_test/browser'
|
|
425
|
-
require 'capybara/rack_test/css_handlers
|
|
483
|
+
require 'capybara/rack_test/css_handlers'
|
|
426
484
|
|
|
427
485
|
require 'capybara/selenium/node'
|
|
428
486
|
require 'capybara/selenium/driver'
|
|
429
487
|
end
|
|
430
488
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
Capybara.register_server :webrick do |app, port, host, **options|
|
|
436
|
-
require 'rack/handler/webrick'
|
|
437
|
-
Rack::Handler::WEBrick.run(app, { Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log.new(nil, 0) }.merge(options))
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
Capybara.register_server :puma do |app, port, host, **options|
|
|
441
|
-
require 'rack/handler/puma'
|
|
442
|
-
# If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.
|
|
443
|
-
# Therefore construct and run the Server instance ourselves.
|
|
444
|
-
# Rack::Handler::Puma.run(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
|
445
|
-
|
|
446
|
-
conf = Rack::Handler::Puma.config(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
|
447
|
-
events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
|
|
448
|
-
|
|
449
|
-
events.log "Capybara starting Puma..."
|
|
450
|
-
events.log "* Version #{Puma::Const::PUMA_VERSION} , codename: #{Puma::Const::CODE_NAME}"
|
|
451
|
-
events.log "* Min threads: #{conf.options[:min_threads]}, max threads: #{conf.options[:max_threads]}"
|
|
452
|
-
|
|
453
|
-
Puma::Server.new(conf.app, events, conf.options).tap do |s|
|
|
454
|
-
s.binder.parse conf.options[:binds], s.events
|
|
455
|
-
s.min_threads = conf.options[:min_threads]
|
|
456
|
-
s.max_threads = conf.options[:max_threads]
|
|
457
|
-
end.run.join
|
|
458
|
-
end
|
|
489
|
+
require 'capybara/registrations/servers'
|
|
490
|
+
require 'capybara/registrations/drivers'
|
|
459
491
|
|
|
460
492
|
Capybara.configure do |config|
|
|
461
493
|
config.always_include_port = false
|
|
@@ -464,34 +496,22 @@ Capybara.configure do |config|
|
|
|
464
496
|
config.default_selector = :css
|
|
465
497
|
config.default_max_wait_time = 2
|
|
466
498
|
config.ignore_hidden_elements = true
|
|
467
|
-
config.default_host =
|
|
499
|
+
config.default_host = 'http://www.example.com'
|
|
468
500
|
config.automatic_reload = true
|
|
469
501
|
config.match = :smart
|
|
470
502
|
config.exact = false
|
|
471
503
|
config.exact_text = false
|
|
472
504
|
config.raise_server_errors = true
|
|
473
|
-
config.server_errors = [
|
|
505
|
+
config.server_errors = [Exception]
|
|
474
506
|
config.visible_text_only = false
|
|
475
507
|
config.automatic_label_click = false
|
|
476
508
|
config.enable_aria_label = false
|
|
509
|
+
config.enable_aria_role = false
|
|
477
510
|
config.reuse_server = true
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
Capybara.register_driver :selenium do |app|
|
|
485
|
-
Capybara::Selenium::Driver.new(app)
|
|
486
|
-
end
|
|
487
|
-
|
|
488
|
-
Capybara.register_driver :selenium_chrome do |app|
|
|
489
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome)
|
|
490
|
-
end
|
|
491
|
-
|
|
492
|
-
Capybara.register_driver :selenium_chrome_headless do |app|
|
|
493
|
-
browser_options = ::Selenium::WebDriver::Chrome::Options.new
|
|
494
|
-
browser_options.args << '--headless'
|
|
495
|
-
browser_options.args << '--disable-gpu'
|
|
496
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
|
|
511
|
+
config.default_set_options = {}
|
|
512
|
+
config.test_id = nil
|
|
513
|
+
config.predicates_wait = true
|
|
514
|
+
config.default_normalize_ws = false
|
|
515
|
+
config.use_html5_parsing = false
|
|
516
|
+
config.w3c_click_offset = false
|
|
497
517
|
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>
|
|
@@ -46,97 +47,121 @@ RSpec.describe Capybara do
|
|
|
46
47
|
STRING
|
|
47
48
|
end
|
|
48
49
|
|
|
49
|
-
it
|
|
50
|
+
it 'allows using matchers' do
|
|
50
51
|
expect(string).to have_css('#page')
|
|
51
52
|
expect(string).not_to have_css('#does-not-exist')
|
|
52
53
|
end
|
|
53
54
|
|
|
54
|
-
it
|
|
55
|
-
|
|
55
|
+
it 'allows using custom matchers' do
|
|
56
|
+
described_class.add_selector :lifeform do
|
|
56
57
|
xpath { |name| ".//option[contains(.,'#{name}')]" }
|
|
57
58
|
end
|
|
58
|
-
expect(string).to have_selector(:id,
|
|
59
|
+
expect(string).to have_selector(:id, 'page')
|
|
59
60
|
expect(string).not_to have_selector(:id, 'does-not-exist')
|
|
60
|
-
expect(string).to have_selector(:lifeform,
|
|
61
|
-
expect(string).not_to have_selector(:lifeform,
|
|
61
|
+
expect(string).to have_selector(:lifeform, 'Monkey')
|
|
62
|
+
expect(string).not_to have_selector(:lifeform, 'Gorilla')
|
|
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')
|
|
69
70
|
expect(string).not_to have_selector(:section, 'section_8')
|
|
70
71
|
end
|
|
71
72
|
|
|
72
|
-
it
|
|
73
|
+
it 'allows using matchers with text option' do
|
|
73
74
|
expect(string).to have_css('h1', text: 'Totally awesome')
|
|
74
75
|
expect(string).not_to have_css('h1', text: 'Not so awesome')
|
|
75
76
|
end
|
|
76
77
|
|
|
77
|
-
it
|
|
78
|
+
it 'allows finding only visible nodes' do
|
|
78
79
|
expect(string.all(:css, '#secret', visible: true)).to be_empty
|
|
79
80
|
expect(string.all(:css, '#secret', visible: false).size).to eq(1)
|
|
80
81
|
end
|
|
81
82
|
|
|
82
|
-
it
|
|
83
|
+
it 'allows finding elements and extracting text from them' do
|
|
83
84
|
expect(string.find('//h1').text).to eq('Totally awesome')
|
|
84
85
|
end
|
|
85
86
|
|
|
86
|
-
it
|
|
87
|
+
it 'allows finding elements and extracting attributes from them' do
|
|
87
88
|
expect(string.find('//h1')[:data]).to eq('fantastic')
|
|
88
89
|
end
|
|
89
90
|
|
|
90
|
-
it
|
|
91
|
+
it 'allows finding elements and extracting the tag name from them' do
|
|
91
92
|
expect(string.find('//h1').tag_name).to eq('h1')
|
|
92
93
|
end
|
|
93
94
|
|
|
94
|
-
it
|
|
95
|
+
it 'allows finding elements and extracting the path' do
|
|
95
96
|
expect(string.find('//h1').path).to eq('/html/body/div/div[1]/h1')
|
|
96
97
|
end
|
|
97
98
|
|
|
98
|
-
it
|
|
99
|
+
it 'allows finding elements and extracting the value' do
|
|
99
100
|
expect(string.find('//div/input').value).to eq('bar')
|
|
100
101
|
expect(string.find('//select').value).to eq('Capybara')
|
|
101
102
|
end
|
|
102
103
|
|
|
103
|
-
it
|
|
104
|
+
it 'allows finding elements and checking if they are visible' do
|
|
104
105
|
expect(string.find('//h1')).to be_visible
|
|
105
|
-
expect(string.find(:css,
|
|
106
|
+
expect(string.find(:css, '#secret', visible: false)).not_to be_visible
|
|
106
107
|
end
|
|
107
108
|
|
|
108
|
-
it
|
|
109
|
+
it 'allows finding elements and checking if they are disabled' do
|
|
109
110
|
expect(string.find('//form/input[@name="bleh"]')).to be_disabled
|
|
110
111
|
expect(string.find('//form/input[@name="meh"]')).not_to be_disabled
|
|
111
112
|
end
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
+
|
|
126
|
+
it 'drops illegal fragments when using gumbo' do
|
|
127
|
+
skip 'libxml is less strict than Gumbo' unless Nokogiri.respond_to?(:HTML5)
|
|
128
|
+
described_class.use_html5_parsing = true
|
|
129
|
+
expect(described_class.string('<td>1</td>')).not_to have_css('td')
|
|
130
|
+
end
|
|
131
|
+
|
|
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')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe '#title' do
|
|
139
|
+
it 'returns the page title' do
|
|
140
|
+
expect(string.title).to eq('simple_node')
|
|
116
141
|
end
|
|
117
142
|
end
|
|
118
143
|
|
|
119
|
-
describe
|
|
120
|
-
it
|
|
121
|
-
expect(string.has_title?('simple_node')).to
|
|
122
|
-
expect(string.has_title?('monkey')).to
|
|
144
|
+
describe '#has_title?' do
|
|
145
|
+
it 'returns whether the page has the given title' do
|
|
146
|
+
expect(string.has_title?('simple_node')).to be true
|
|
147
|
+
expect(string.has_title?('monkey')).to be false
|
|
123
148
|
end
|
|
124
149
|
|
|
125
|
-
it
|
|
126
|
-
expect(string.has_title?(/s[a-z]+_node/)).to
|
|
127
|
-
expect(string.has_title?(/monkey/)).to
|
|
150
|
+
it 'allows regexp matches' do
|
|
151
|
+
expect(string.has_title?(/s[a-z]+_node/)).to be true
|
|
152
|
+
expect(string.has_title?(/monkey/)).to be false
|
|
128
153
|
end
|
|
129
154
|
end
|
|
130
155
|
|
|
131
156
|
describe '#has_no_title?' do
|
|
132
|
-
it
|
|
133
|
-
expect(string.has_no_title?('simple_node')).to
|
|
134
|
-
expect(string.has_no_title?('monkey')).to
|
|
157
|
+
it 'returns whether the page does not have the given title' do
|
|
158
|
+
expect(string.has_no_title?('simple_node')).to be false
|
|
159
|
+
expect(string.has_no_title?('monkey')).to be true
|
|
135
160
|
end
|
|
136
161
|
|
|
137
|
-
it
|
|
138
|
-
expect(string.has_no_title?(/s[a-z]+_node/)).to
|
|
139
|
-
expect(string.has_no_title?(/monkey/)).to
|
|
162
|
+
it 'allows regexp matches' do
|
|
163
|
+
expect(string.has_no_title?(/s[a-z]+_node/)).to be false
|
|
164
|
+
expect(string.has_no_title?(/monkey/)).to be true
|
|
140
165
|
end
|
|
141
166
|
end
|
|
142
167
|
end
|