capybara 3.3.0 → 3.40.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/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,32 +67,49 @@ 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
|
-
#
|
92
|
-
#
|
70
|
+
# #### Configurable options
|
71
|
+
#
|
72
|
+
# - **use_html5_parsing** (Boolean = `false`) - When Nokogiri >= 1.12.0 or `nokogumbo` is installed, whether HTML5 parsing will be used for HTML strings.
|
73
|
+
# - **always_include_port** (Boolean = `false`) - Whether the Rack server's port should automatically be inserted into every visited URL
|
74
|
+
# unless another port is explicitly specified.
|
75
|
+
# - **app_host** (String, `nil`) - The default host to use when giving a relative URL to visit, must be a valid URL e.g. `http://www.example.com`.
|
76
|
+
# - **asset_host** (String = `nil`) - Where dynamic assets are hosted - will be prepended to relative asset locations if present.
|
77
|
+
# - **automatic_label_click** (Boolean = `false`) - Whether {Capybara::Node::Element#choose Element#choose}, {Capybara::Node::Element#check Element#check},
|
78
|
+
# {Capybara::Node::Element#uncheck Element#uncheck} will attempt to click the associated `<label>` element if the checkbox/radio button are non-visible.
|
79
|
+
# - **automatic_reload** (Boolean = `true`) - Whether to automatically reload elements as Capybara is waiting.
|
80
|
+
# - **default_max_wait_time** (Numeric = `2`) - The maximum number of seconds to wait for asynchronous processes to finish.
|
81
|
+
# - **default_normalize_ws** (Boolean = `false`) - Whether text predicates and matchers use normalize whitespace behavior.
|
82
|
+
# - **default_retry_interval** (Numeric = `0.01`) - The number of seconds to delay the next check in asynchronous processes.
|
83
|
+
# - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
|
84
|
+
# - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
|
85
|
+
# - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
|
86
|
+
# - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).
|
87
|
+
# - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions
|
88
|
+
# written using the `XPath#is` method.
|
89
|
+
# - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.
|
90
|
+
# - **ignore_hidden_elements** (Boolean = `true`) - Whether to ignore hidden elements on the page.
|
91
|
+
# - **match** (`:one`, `:first`, `:prefer_exact`, `:smart` = `:smart`) - The matching strategy to find nodes.
|
92
|
+
# - **predicates_wait** (Boolean = `true`) - Whether Capybara's predicate matchers use waiting behavior by default.
|
93
|
+
# - **raise_server_errors** (Boolean = `true`) - Should errors raised in the server be raised in the tests?
|
94
|
+
# - **reuse_server** (Boolean = `true`) - Whether to reuse the server thread between multiple sessions using the same app object.
|
95
|
+
# - **run_server** (Boolean = `true`) - Whether to start a Rack server for the given Rack app.
|
96
|
+
# - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},
|
97
|
+
# {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
|
98
|
+
# - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
|
99
|
+
# - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
|
100
|
+
# - **server_host** (String = "127.0.0.1") - The IP address Capybara will bind the application server to. If the test application is to be accessed from an external host, you will want to change this to "0.0.0.0" or to a more specific IP address that your test client can reach.
|
101
|
+
# - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
|
102
|
+
# and {configure raise_server_errors} is `true`.
|
103
|
+
# - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
|
104
|
+
# - **threadsafe** (Boolean = `false`) - Whether sessions can be configured individually.
|
105
|
+
# - **w3c_click_offset** (Boolean = 'true') - Whether click offsets should be from element center (true) or top left (false)
|
106
|
+
#
|
107
|
+
# #### DSL Options
|
108
|
+
#
|
109
|
+
# When using `capybara/dsl`, the following options are also available:
|
110
|
+
#
|
111
|
+
# - **default_driver** (Symbol = `:rack_test`) - The name of the driver to use by default.
|
112
|
+
# - **javascript_driver** (Symbol = `:selenium`) - The name of a driver to use for JavaScript enabled tests.
|
93
113
|
#
|
94
114
|
def configure
|
95
115
|
yield config
|
@@ -109,7 +129,7 @@ module Capybara
|
|
109
129
|
# @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
|
110
130
|
#
|
111
131
|
def register_driver(name, &block)
|
112
|
-
drivers
|
132
|
+
drivers.send(:register, name, block)
|
113
133
|
end
|
114
134
|
|
115
135
|
##
|
@@ -128,7 +148,7 @@ module Capybara
|
|
128
148
|
# @yieldparam host The host/ip to bind to
|
129
149
|
#
|
130
150
|
def register_server(name, &block)
|
131
|
-
servers
|
151
|
+
servers.send(:register, name.to_sym, block)
|
132
152
|
end
|
133
153
|
|
134
154
|
##
|
@@ -159,8 +179,8 @@ module Capybara
|
|
159
179
|
# @param [Symbol] name The name of the selector to add
|
160
180
|
# @yield A block executed in the context of the new {Capybara::Selector}
|
161
181
|
#
|
162
|
-
def add_selector(name, &block)
|
163
|
-
Capybara::Selector.add(name, &block)
|
182
|
+
def add_selector(name, **options, &block)
|
183
|
+
Capybara::Selector.add(name, **options, &block)
|
164
184
|
end
|
165
185
|
|
166
186
|
##
|
@@ -170,7 +190,7 @@ module Capybara
|
|
170
190
|
# button style (a class) might look like this
|
171
191
|
#
|
172
192
|
# Capybara.modify_selector(:button) do
|
173
|
-
# filter (:
|
193
|
+
# filter (:btn_style, valid_values: [:primary, :secondary]) { |node, style| node[:class].split.include? "btn-#{style}" }
|
174
194
|
# end
|
175
195
|
#
|
176
196
|
#
|
@@ -182,11 +202,11 @@ module Capybara
|
|
182
202
|
end
|
183
203
|
|
184
204
|
def drivers
|
185
|
-
@drivers ||=
|
205
|
+
@drivers ||= RegistrationContainer.new
|
186
206
|
end
|
187
207
|
|
188
208
|
def servers
|
189
|
-
@servers ||=
|
209
|
+
@servers ||= RegistrationContainer.new
|
190
210
|
end
|
191
211
|
|
192
212
|
# Wraps the given string, which should contain an HTML document or fragment
|
@@ -195,15 +215,13 @@ module Capybara
|
|
195
215
|
# any string containing HTML in the exact same way you would query the current document in a Capybara
|
196
216
|
# session.
|
197
217
|
#
|
198
|
-
#
|
199
|
-
#
|
218
|
+
# @example A single element
|
200
219
|
# node = Capybara.string('<a href="foo">bar</a>')
|
201
220
|
# anchor = node.first('a')
|
202
221
|
# anchor[:href] #=> 'foo'
|
203
222
|
# anchor.text #=> 'bar'
|
204
223
|
#
|
205
|
-
#
|
206
|
-
#
|
224
|
+
# @example Multiple elements
|
207
225
|
# node = Capybara.string <<-HTML
|
208
226
|
# <ul>
|
209
227
|
# <li id="home">Home</li>
|
@@ -242,7 +260,7 @@ module Capybara
|
|
242
260
|
#
|
243
261
|
def current_driver
|
244
262
|
if threadsafe
|
245
|
-
Thread.current
|
263
|
+
Thread.current.thread_variable_get :capybara_current_driver
|
246
264
|
else
|
247
265
|
@current_driver
|
248
266
|
end || default_driver
|
@@ -251,7 +269,7 @@ module Capybara
|
|
251
269
|
|
252
270
|
def current_driver=(name)
|
253
271
|
if threadsafe
|
254
|
-
Thread.current
|
272
|
+
Thread.current.thread_variable_set :capybara_current_driver, name
|
255
273
|
else
|
256
274
|
@current_driver = name
|
257
275
|
end
|
@@ -291,12 +309,12 @@ module Capybara
|
|
291
309
|
|
292
310
|
##
|
293
311
|
#
|
294
|
-
# The current Capybara::Session based on what is set as
|
312
|
+
# The current {Capybara::Session} based on what is set as {app} and {current_driver}.
|
295
313
|
#
|
296
314
|
# @return [Capybara::Session] The currently used session
|
297
315
|
#
|
298
316
|
def current_session
|
299
|
-
session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
|
317
|
+
specified_session || session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
|
300
318
|
end
|
301
319
|
|
302
320
|
##
|
@@ -318,7 +336,8 @@ module Capybara
|
|
318
336
|
#
|
319
337
|
def session_name
|
320
338
|
if threadsafe
|
321
|
-
Thread.current
|
339
|
+
Thread.current.thread_variable_get(:capybara_session_name) ||
|
340
|
+
Thread.current.thread_variable_set(:capybara_session_name, :default)
|
322
341
|
else
|
323
342
|
@session_name ||= :default
|
324
343
|
end
|
@@ -326,7 +345,7 @@ module Capybara
|
|
326
345
|
|
327
346
|
def session_name=(name)
|
328
347
|
if threadsafe
|
329
|
-
Thread.current
|
348
|
+
Thread.current.thread_variable_set :capybara_session_name, name
|
330
349
|
else
|
331
350
|
@session_name = name
|
332
351
|
end
|
@@ -334,22 +353,31 @@ module Capybara
|
|
334
353
|
|
335
354
|
##
|
336
355
|
#
|
337
|
-
# Yield a block using a specific session name.
|
356
|
+
# Yield a block using a specific session name or {Capybara::Session} instance.
|
338
357
|
#
|
339
|
-
def using_session(
|
358
|
+
def using_session(name_or_session, &block)
|
359
|
+
previous_session = current_session
|
340
360
|
previous_session_info = {
|
361
|
+
specified_session: specified_session,
|
341
362
|
session_name: session_name,
|
342
363
|
current_driver: current_driver,
|
343
364
|
app: app
|
344
365
|
}
|
345
|
-
self.session_name =
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
366
|
+
self.specified_session = self.session_name = nil
|
367
|
+
if name_or_session.is_a? Capybara::Session
|
368
|
+
self.specified_session = name_or_session
|
369
|
+
else
|
370
|
+
self.session_name = name_or_session
|
371
|
+
end
|
372
|
+
|
373
|
+
if block.arity.zero?
|
374
|
+
yield
|
375
|
+
else
|
376
|
+
yield current_session, previous_session
|
352
377
|
end
|
378
|
+
ensure
|
379
|
+
self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
|
380
|
+
self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
|
353
381
|
end
|
354
382
|
|
355
383
|
##
|
@@ -360,9 +388,21 @@ module Capybara
|
|
360
388
|
# @return [Nokogiri::HTML::Document] HTML document
|
361
389
|
#
|
362
390
|
def HTML(html) # rubocop:disable Naming/MethodName
|
363
|
-
Nokogiri
|
391
|
+
# Nokogiri >= 1.12.0 or Nokogumbo installed and allowed for use
|
392
|
+
html_parser, using_html5 = if defined?(Nokogiri::HTML5) && Capybara.use_html5_parsing
|
393
|
+
[Nokogiri::HTML5, true]
|
394
|
+
else
|
395
|
+
[defined?(Nokogiri::HTML4) ? Nokogiri::HTML4 : Nokogiri::HTML, false]
|
396
|
+
end
|
397
|
+
|
398
|
+
html_parser.parse(html).tap do |document|
|
399
|
+
document.xpath('//template').each do |template|
|
400
|
+
# template elements content is not part of the document
|
401
|
+
template.inner_html = ''
|
402
|
+
end
|
364
403
|
document.xpath('//textarea').each do |textarea|
|
365
|
-
|
404
|
+
# The Nokogiri HTML5 parser already returns spec compliant contents
|
405
|
+
textarea['_capybara_raw_value'] = using_html5 ? textarea.content : textarea.content.delete_prefix("\n")
|
366
406
|
end
|
367
407
|
end
|
368
408
|
end
|
@@ -378,7 +418,25 @@ module Capybara
|
|
378
418
|
end
|
379
419
|
|
380
420
|
def session_pool
|
381
|
-
@session_pool ||=
|
421
|
+
@session_pool ||= Hash.new do |hash, name|
|
422
|
+
hash[name] = Capybara::Session.new(current_driver, app)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
def specified_session
|
427
|
+
if threadsafe
|
428
|
+
Thread.current.thread_variable_get :capybara_specified_session
|
429
|
+
else
|
430
|
+
@specified_session ||= nil
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def specified_session=(session)
|
435
|
+
if threadsafe
|
436
|
+
Thread.current.thread_variable_set :capybara_specified_session, session
|
437
|
+
else
|
438
|
+
@specified_session = session
|
439
|
+
end
|
382
440
|
end
|
383
441
|
end
|
384
442
|
|
@@ -407,6 +465,7 @@ module Capybara
|
|
407
465
|
require 'capybara/queries/ancestor_query'
|
408
466
|
require 'capybara/queries/sibling_query'
|
409
467
|
require 'capybara/queries/style_query'
|
468
|
+
require 'capybara/queries/active_element_query'
|
410
469
|
|
411
470
|
require 'capybara/node/finders'
|
412
471
|
require 'capybara/node/matchers'
|
@@ -424,45 +483,14 @@ module Capybara
|
|
424
483
|
require 'capybara/rack_test/node'
|
425
484
|
require 'capybara/rack_test/form'
|
426
485
|
require 'capybara/rack_test/browser'
|
427
|
-
require 'capybara/rack_test/css_handlers
|
486
|
+
require 'capybara/rack_test/css_handlers'
|
428
487
|
|
429
488
|
require 'capybara/selenium/node'
|
430
|
-
require 'capybara/selenium/nodes/marionette_node'
|
431
489
|
require 'capybara/selenium/driver'
|
432
490
|
end
|
433
491
|
|
434
|
-
|
435
|
-
|
436
|
-
end
|
437
|
-
|
438
|
-
Capybara.register_server :webrick do |app, port, host, **options|
|
439
|
-
require 'rack/handler/webrick'
|
440
|
-
Rack::Handler::WEBrick.run(app, { Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log.new(nil, 0) }.merge(options))
|
441
|
-
end
|
442
|
-
|
443
|
-
Capybara.register_server :puma do |app, port, host, **options|
|
444
|
-
begin
|
445
|
-
require 'rack/handler/puma'
|
446
|
-
rescue LoadError
|
447
|
-
raise LoadError, "Capybara is unable to load `puma` for its server, please add `puma` to your project or specify a different server via something like `Capybara.server = :webrick`."
|
448
|
-
end
|
449
|
-
# If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.
|
450
|
-
# Therefore construct and run the Server instance ourselves.
|
451
|
-
# Rack::Handler::Puma.run(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
452
|
-
|
453
|
-
conf = Rack::Handler::Puma.config(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
454
|
-
events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
|
455
|
-
|
456
|
-
events.log "Capybara starting Puma..."
|
457
|
-
events.log "* Version #{Puma::Const::PUMA_VERSION} , codename: #{Puma::Const::CODE_NAME}"
|
458
|
-
events.log "* Min threads: #{conf.options[:min_threads]}, max threads: #{conf.options[:max_threads]}"
|
459
|
-
|
460
|
-
Puma::Server.new(conf.app, events, conf.options).tap do |s|
|
461
|
-
s.binder.parse conf.options[:binds], s.events
|
462
|
-
s.min_threads = conf.options[:min_threads]
|
463
|
-
s.max_threads = conf.options[:max_threads]
|
464
|
-
end.run.join
|
465
|
-
end
|
492
|
+
require 'capybara/registrations/servers'
|
493
|
+
require 'capybara/registrations/drivers'
|
466
494
|
|
467
495
|
Capybara.configure do |config|
|
468
496
|
config.always_include_port = false
|
@@ -470,37 +498,24 @@ Capybara.configure do |config|
|
|
470
498
|
config.server = :default
|
471
499
|
config.default_selector = :css
|
472
500
|
config.default_max_wait_time = 2
|
501
|
+
config.default_retry_interval = 0.01
|
473
502
|
config.ignore_hidden_elements = true
|
474
|
-
config.default_host =
|
503
|
+
config.default_host = 'http://www.example.com'
|
475
504
|
config.automatic_reload = true
|
476
505
|
config.match = :smart
|
477
506
|
config.exact = false
|
478
507
|
config.exact_text = false
|
479
508
|
config.raise_server_errors = true
|
480
|
-
config.server_errors = [
|
509
|
+
config.server_errors = [Exception]
|
481
510
|
config.visible_text_only = false
|
482
511
|
config.automatic_label_click = false
|
483
512
|
config.enable_aria_label = false
|
513
|
+
config.enable_aria_role = false
|
484
514
|
config.reuse_server = true
|
485
515
|
config.default_set_options = {}
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
Capybara.register_driver :selenium do |app|
|
493
|
-
Capybara::Selenium::Driver.new(app)
|
494
|
-
end
|
495
|
-
|
496
|
-
Capybara.register_driver :selenium_chrome do |app|
|
497
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome)
|
498
|
-
end
|
499
|
-
|
500
|
-
Capybara.register_driver :selenium_chrome_headless do |app|
|
501
|
-
Capybara::Selenium::Driver.load_selenium
|
502
|
-
browser_options = ::Selenium::WebDriver::Chrome::Options.new
|
503
|
-
browser_options.args << '--headless'
|
504
|
-
browser_options.args << '--disable-gpu' if Gem.win_platform?
|
505
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
|
516
|
+
config.test_id = nil
|
517
|
+
config.predicates_wait = true
|
518
|
+
config.default_normalize_ws = false
|
519
|
+
config.use_html5_parsing = false
|
520
|
+
config.w3c_click_offset = true
|
506
521
|
end
|
data/spec/basic_node_spec.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe Capybara do
|
6
|
+
include Capybara::RSpecMatchers
|
6
7
|
describe '.string' do
|
7
8
|
let :string do
|
8
|
-
|
9
|
+
described_class.string <<-STRING
|
9
10
|
<html>
|
10
11
|
<head>
|
11
12
|
<title>simple_node</title>
|
@@ -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
|