capybara 3.32.2
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 +7 -0
- data/.yardopts +1 -0
- data/History.md +1813 -0
- data/License.txt +22 -0
- data/README.md +1099 -0
- data/lib/capybara.rb +511 -0
- data/lib/capybara/config.rb +94 -0
- data/lib/capybara/cucumber.rb +27 -0
- data/lib/capybara/driver/base.rb +170 -0
- data/lib/capybara/driver/node.rb +139 -0
- data/lib/capybara/dsl.rb +65 -0
- data/lib/capybara/helpers.rb +108 -0
- data/lib/capybara/minitest.rb +386 -0
- data/lib/capybara/minitest/spec.rb +264 -0
- data/lib/capybara/node/actions.rb +420 -0
- data/lib/capybara/node/base.rb +143 -0
- data/lib/capybara/node/document.rb +48 -0
- data/lib/capybara/node/document_matchers.rb +67 -0
- data/lib/capybara/node/element.rb +606 -0
- data/lib/capybara/node/finders.rb +325 -0
- data/lib/capybara/node/matchers.rb +883 -0
- data/lib/capybara/node/simple.rb +208 -0
- data/lib/capybara/queries/ancestor_query.rb +27 -0
- data/lib/capybara/queries/base_query.rb +106 -0
- data/lib/capybara/queries/current_path_query.rb +51 -0
- data/lib/capybara/queries/match_query.rb +26 -0
- data/lib/capybara/queries/selector_query.rb +710 -0
- data/lib/capybara/queries/sibling_query.rb +26 -0
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +110 -0
- data/lib/capybara/queries/title_query.rb +39 -0
- data/lib/capybara/rack_test/browser.rb +140 -0
- data/lib/capybara/rack_test/css_handlers.rb +13 -0
- data/lib/capybara/rack_test/driver.rb +109 -0
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +127 -0
- data/lib/capybara/rack_test/node.rb +325 -0
- data/lib/capybara/rails.rb +16 -0
- data/lib/capybara/registrations/drivers.rb +36 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
- data/lib/capybara/registrations/servers.rb +44 -0
- data/lib/capybara/result.rb +190 -0
- data/lib/capybara/rspec.rb +29 -0
- data/lib/capybara/rspec/features.rb +23 -0
- data/lib/capybara/rspec/matcher_proxies.rb +82 -0
- data/lib/capybara/rspec/matchers.rb +201 -0
- 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 +38 -0
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/selector.rb +233 -0
- data/lib/capybara/selector/builders/css_builder.rb +84 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +69 -0
- data/lib/capybara/selector/css.rb +102 -0
- data/lib/capybara/selector/definition.rb +276 -0
- data/lib/capybara/selector/definition/button.rb +51 -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 +27 -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 +46 -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/filter.rb +5 -0
- data/lib/capybara/selector/filter_set.rb +124 -0
- data/lib/capybara/selector/filters/base.rb +77 -0
- data/lib/capybara/selector/filters/expression_filter.rb +22 -0
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +31 -0
- data/lib/capybara/selector/regexp_disassembler.rb +214 -0
- data/lib/capybara/selector/selector.rb +147 -0
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- 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 +496 -0
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +119 -0
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +126 -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 +78 -0
- data/lib/capybara/selenium/logger_suppressor.rb +34 -0
- data/lib/capybara/selenium/node.rb +610 -0
- data/lib/capybara/selenium/nodes/chrome_node.rb +119 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +131 -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 +47 -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.rb +126 -0
- data/lib/capybara/server/animation_disabler.rb +58 -0
- data/lib/capybara/server/checker.rb +44 -0
- data/lib/capybara/server/middleware.rb +69 -0
- data/lib/capybara/session.rb +942 -0
- data/lib/capybara/session/config.rb +124 -0
- data/lib/capybara/session/matchers.rb +87 -0
- data/lib/capybara/spec/fixtures/another_test_file.txt +1 -0
- data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
- data/lib/capybara/spec/fixtures/no_extension +1 -0
- data/lib/capybara/spec/fixtures/test_file.txt +1 -0
- data/lib/capybara/spec/public/jquery-ui.js +13 -0
- data/lib/capybara/spec/public/jquery.js +5 -0
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +268 -0
- data/lib/capybara/spec/session/accept_alert_spec.rb +81 -0
- data/lib/capybara/spec/session/accept_confirm_spec.rb +32 -0
- data/lib/capybara/spec/session/accept_prompt_spec.rb +78 -0
- data/lib/capybara/spec/session/all_spec.rb +278 -0
- data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
- data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
- data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
- data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
- data/lib/capybara/spec/session/assert_title_spec.rb +93 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +216 -0
- data/lib/capybara/spec/session/body_spec.rb +23 -0
- data/lib/capybara/spec/session/check_spec.rb +235 -0
- data/lib/capybara/spec/session/choose_spec.rb +121 -0
- data/lib/capybara/spec/session/click_button_spec.rb +506 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +129 -0
- data/lib/capybara/spec/session/click_link_spec.rb +229 -0
- data/lib/capybara/spec/session/current_scope_spec.rb +31 -0
- data/lib/capybara/spec/session/current_url_spec.rb +115 -0
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +36 -0
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +21 -0
- data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +38 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +31 -0
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +25 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +120 -0
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +49 -0
- data/lib/capybara/spec/session/execute_script_spec.rb +28 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +286 -0
- data/lib/capybara/spec/session/find_button_spec.rb +74 -0
- data/lib/capybara/spec/session/find_by_id_spec.rb +33 -0
- data/lib/capybara/spec/session/find_field_spec.rb +113 -0
- data/lib/capybara/spec/session/find_link_spec.rb +70 -0
- data/lib/capybara/spec/session/find_spec.rb +531 -0
- data/lib/capybara/spec/session/first_spec.rb +156 -0
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +116 -0
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
- data/lib/capybara/spec/session/go_back_spec.rb +12 -0
- data/lib/capybara/spec/session/go_forward_spec.rb +14 -0
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
- data/lib/capybara/spec/session/has_button_spec.rb +69 -0
- data/lib/capybara/spec/session/has_css_spec.rb +374 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +138 -0
- data/lib/capybara/spec/session/has_field_spec.rb +349 -0
- data/lib/capybara/spec/session/has_link_spec.rb +39 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
- data/lib/capybara/spec/session/has_select_spec.rb +310 -0
- data/lib/capybara/spec/session/has_selector_spec.rb +202 -0
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +198 -0
- data/lib/capybara/spec/session/has_text_spec.rb +394 -0
- data/lib/capybara/spec/session/has_title_spec.rb +71 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +149 -0
- data/lib/capybara/spec/session/headers_spec.rb +8 -0
- data/lib/capybara/spec/session/html_spec.rb +47 -0
- data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
- data/lib/capybara/spec/session/node_spec.rb +1292 -0
- data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
- data/lib/capybara/spec/session/refresh_spec.rb +33 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +148 -0
- data/lib/capybara/spec/session/response_code_spec.rb +8 -0
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +21 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +43 -0
- data/lib/capybara/spec/session/save_page_spec.rb +110 -0
- data/lib/capybara/spec/session/save_screenshot_spec.rb +55 -0
- data/lib/capybara/spec/session/screenshot_spec.rb +18 -0
- data/lib/capybara/spec/session/scroll_spec.rb +117 -0
- data/lib/capybara/spec/session/select_spec.rb +229 -0
- data/lib/capybara/spec/session/selectors_spec.rb +98 -0
- data/lib/capybara/spec/session/sibling_spec.rb +52 -0
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/session/text_spec.rb +74 -0
- data/lib/capybara/spec/session/title_spec.rb +29 -0
- data/lib/capybara/spec/session/uncheck_spec.rb +100 -0
- data/lib/capybara/spec/session/unselect_spec.rb +116 -0
- data/lib/capybara/spec/session/visit_spec.rb +204 -0
- data/lib/capybara/spec/session/window/become_closed_spec.rb +89 -0
- data/lib/capybara/spec/session/window/current_window_spec.rb +28 -0
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +31 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +132 -0
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +99 -0
- data/lib/capybara/spec/session/window/window_spec.rb +203 -0
- data/lib/capybara/spec/session/window/windows_spec.rb +34 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +157 -0
- data/lib/capybara/spec/session/within_spec.rb +199 -0
- data/lib/capybara/spec/spec_helper.rb +134 -0
- data/lib/capybara/spec/test_app.rb +226 -0
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/buttons.erb +5 -0
- data/lib/capybara/spec/views/fieldsets.erb +30 -0
- data/lib/capybara/spec/views/form.erb +685 -0
- data/lib/capybara/spec/views/frame_child.erb +18 -0
- data/lib/capybara/spec/views/frame_one.erb +10 -0
- data/lib/capybara/spec/views/frame_parent.erb +9 -0
- data/lib/capybara/spec/views/frame_two.erb +9 -0
- data/lib/capybara/spec/views/header_links.erb +8 -0
- data/lib/capybara/spec/views/host_links.erb +13 -0
- data/lib/capybara/spec/views/initial_alert.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +47 -0
- data/lib/capybara/spec/views/offset.erb +32 -0
- data/lib/capybara/spec/views/path.erb +13 -0
- data/lib/capybara/spec/views/popup_one.erb +9 -0
- data/lib/capybara/spec/views/popup_two.erb +9 -0
- data/lib/capybara/spec/views/postback.erb +14 -0
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +20 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +130 -0
- data/lib/capybara/spec/views/with_animation.erb +74 -0
- data/lib/capybara/spec/views/with_base_tag.erb +11 -0
- data/lib/capybara/spec/views/with_count.erb +8 -0
- data/lib/capybara/spec/views/with_dragula.erb +22 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
- data/lib/capybara/spec/views/with_hover.erb +24 -0
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +208 -0
- data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
- data/lib/capybara/spec/views/with_html_entities.erb +2 -0
- data/lib/capybara/spec/views/with_js.erb +160 -0
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +20 -0
- data/lib/capybara/spec/views/with_scope.erb +42 -0
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_simple_html.erb +2 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_title.erb +5 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
- data/lib/capybara/spec/views/with_windows.erb +54 -0
- data/lib/capybara/spec/views/within_frames.erb +15 -0
- data/lib/capybara/version.rb +5 -0
- data/lib/capybara/window.rb +146 -0
- data/spec/basic_node_spec.rb +154 -0
- data/spec/capybara_spec.rb +112 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +276 -0
- data/spec/filter_set_spec.rb +46 -0
- data/spec/fixtures/capybara.csv +1 -0
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +13 -0
- data/spec/fixtures/selenium_driver_rspec_success.rb +13 -0
- data/spec/minitest_spec.rb +163 -0
- data/spec/minitest_spec_spec.rb +162 -0
- data/spec/per_session_config_spec.rb +68 -0
- data/spec/rack_test_spec.rb +268 -0
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +196 -0
- data/spec/rspec/features_spec.rb +99 -0
- data/spec/rspec/scenarios_spec.rb +19 -0
- data/spec/rspec/shared_spec_matchers.rb +947 -0
- data/spec/rspec/views_spec.rb +14 -0
- data/spec/rspec_matchers_spec.rb +62 -0
- data/spec/rspec_spec.rb +145 -0
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +513 -0
- data/spec/selenium_spec_chrome.rb +188 -0
- data/spec/selenium_spec_chrome_remote.rb +96 -0
- data/spec/selenium_spec_edge.rb +47 -0
- data/spec/selenium_spec_firefox.rb +208 -0
- data/spec/selenium_spec_firefox_remote.rb +80 -0
- data/spec/selenium_spec_ie.rb +150 -0
- data/spec/selenium_spec_safari.rb +148 -0
- data/spec/server_spec.rb +292 -0
- data/spec/session_spec.rb +91 -0
- data/spec/shared_selenium_node.rb +83 -0
- data/spec/shared_selenium_session.rb +476 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +753 -0
data/spec/result_spec.rb
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Capybara::Result do
|
|
6
|
+
let :string do
|
|
7
|
+
Capybara.string <<-STRING
|
|
8
|
+
<ul>
|
|
9
|
+
<li>Alpha</li>
|
|
10
|
+
<li>Beta</li>
|
|
11
|
+
<li>Gamma</li>
|
|
12
|
+
<li>Delta</li>
|
|
13
|
+
</ul>
|
|
14
|
+
STRING
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let :result do
|
|
18
|
+
string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'has a length' do
|
|
22
|
+
expect(result.length).to eq(4)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'has a first element' do
|
|
26
|
+
result.first.text == 'Alpha'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'has a last element' do
|
|
30
|
+
result.last.text == 'Delta'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'can supports values_at method' do
|
|
34
|
+
expect(result.values_at(0, 2).map(&:text)).to eq(%w[Alpha Gamma])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'can return an element by its index' do
|
|
38
|
+
expect(result.at(1).text).to eq('Beta')
|
|
39
|
+
expect(result[2].text).to eq('Gamma')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'can be mapped' do
|
|
43
|
+
expect(result.map(&:text)).to eq(%w[Alpha Beta Gamma Delta])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'can be selected' do
|
|
47
|
+
expect(result.count do |element|
|
|
48
|
+
element.text.include? 't'
|
|
49
|
+
end).to eq(2)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'can be reduced' do
|
|
53
|
+
expect(result.reduce('') do |memo, element|
|
|
54
|
+
memo + element.text[0]
|
|
55
|
+
end).to eq('ABGD')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'can be sampled' do
|
|
59
|
+
expect(result).to include(result.sample)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'can be indexed' do
|
|
63
|
+
expect(result.index do |el|
|
|
64
|
+
el.text == 'Gamma'
|
|
65
|
+
end).to eq(2)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def recalc_result
|
|
69
|
+
string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'supports all modes of []' do
|
|
73
|
+
expect(recalc_result[1].text).to eq 'Beta'
|
|
74
|
+
expect(recalc_result[0, 2].map(&:text)).to eq %w[Alpha Beta]
|
|
75
|
+
expect(recalc_result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
|
|
76
|
+
expect(recalc_result[-1].text).to eq 'Delta'
|
|
77
|
+
expect(recalc_result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
|
|
78
|
+
expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]
|
|
79
|
+
expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
|
|
80
|
+
expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]
|
|
81
|
+
expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
|
|
85
|
+
it 'supports endless ranges' do
|
|
86
|
+
expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
|
|
87
|
+
end
|
|
88
|
+
TEST
|
|
89
|
+
|
|
90
|
+
eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
|
|
91
|
+
it 'supports inclusive positive beginless ranges' do
|
|
92
|
+
expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'supports inclusive negative beginless ranges' do
|
|
96
|
+
expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
|
|
97
|
+
expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'supports exclusive positive beginless ranges' do
|
|
101
|
+
expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'supports exclusive negative beginless ranges' do
|
|
105
|
+
expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
|
|
106
|
+
expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
|
|
107
|
+
end
|
|
108
|
+
TEST
|
|
109
|
+
|
|
110
|
+
it 'works with filter blocks' do
|
|
111
|
+
result = string.all('//li') { |node| node.text == 'Alpha' }
|
|
112
|
+
expect(result.size).to eq 1
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Not a great test but it indirectly tests what is needed
|
|
116
|
+
it 'should evaluate filters lazily for idx' do
|
|
117
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
|
|
118
|
+
# Not processed until accessed
|
|
119
|
+
expect(result.instance_variable_get('@result_cache').size).to be 0
|
|
120
|
+
|
|
121
|
+
# Only one retrieved when needed
|
|
122
|
+
result.first
|
|
123
|
+
expect(result.instance_variable_get('@result_cache').size).to be 1
|
|
124
|
+
|
|
125
|
+
# works for indexed access
|
|
126
|
+
result[0]
|
|
127
|
+
expect(result.instance_variable_get('@result_cache').size).to be 1
|
|
128
|
+
|
|
129
|
+
result[2]
|
|
130
|
+
expect(result.instance_variable_get('@result_cache').size).to be 3
|
|
131
|
+
|
|
132
|
+
# All cached when converted to array
|
|
133
|
+
result.to_a
|
|
134
|
+
expect(result.instance_variable_get('@result_cache').size).to eq 4
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'should evaluate filters lazily for range' do
|
|
138
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
|
|
139
|
+
result[0..1]
|
|
140
|
+
expect(result.instance_variable_get('@result_cache').size).to be 2
|
|
141
|
+
|
|
142
|
+
expect(result[0..7].size).to eq 4
|
|
143
|
+
expect(result.instance_variable_get('@result_cache').size).to be 4
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'should evaluate filters lazily for idx and length' do
|
|
147
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
|
|
148
|
+
result[1, 2]
|
|
149
|
+
expect(result.instance_variable_get('@result_cache').size).to be 3
|
|
150
|
+
|
|
151
|
+
expect(result[2, 5].size).to eq 2
|
|
152
|
+
expect(result.instance_variable_get('@result_cache').size).to be 4
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'should only need to evaluate one result for any?' do
|
|
156
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
|
|
157
|
+
result.any?
|
|
158
|
+
expect(result.instance_variable_get('@result_cache').size).to be 1
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'should evaluate all elements when #to_a called' do
|
|
162
|
+
# All cached when converted to array
|
|
163
|
+
result.to_a
|
|
164
|
+
expect(result.instance_variable_get('@result_cache').size).to eq 4
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
describe '#each' do
|
|
168
|
+
it 'lazily evaluates' do
|
|
169
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
|
|
170
|
+
results = []
|
|
171
|
+
result.each do |el|
|
|
172
|
+
results << el
|
|
173
|
+
expect(result.instance_variable_get('@result_cache').size).to eq results.size
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
expect(results.size).to eq 4
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
context 'without a block' do
|
|
180
|
+
it 'returns an iterator' do
|
|
181
|
+
expect(result.each).to be_a(Enumerator)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'lazily evaluates' do
|
|
185
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
|
|
186
|
+
result.each.with_index do |_el, idx|
|
|
187
|
+
expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def jruby_lazy_enumerator_workaround?
|
|
194
|
+
RUBY_PLATFORM == 'java'
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'capybara/rspec'
|
|
5
|
+
|
|
6
|
+
# rubocop:disable RSpec/InstanceVariable
|
|
7
|
+
RSpec.configuration.before(:each, file_path: './spec/rspec/features_spec.rb') do
|
|
8
|
+
@in_filtered_hook = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
feature "Capybara's feature DSL" do
|
|
12
|
+
background do
|
|
13
|
+
@in_background = true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
scenario 'includes Capybara' do
|
|
17
|
+
visit('/')
|
|
18
|
+
expect(page).to have_content('Hello world!')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
scenario 'preserves description' do |ex|
|
|
22
|
+
expect(ex.metadata[:full_description])
|
|
23
|
+
.to eq("Capybara's feature DSL preserves description")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
scenario 'allows driver switching', driver: :selenium do
|
|
27
|
+
expect(Capybara.current_driver).to eq(:selenium)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
scenario 'runs background' do
|
|
31
|
+
expect(@in_background).to be_truthy
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
scenario 'runs hooks filtered by file path' do
|
|
35
|
+
expect(@in_filtered_hook).to be_truthy
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
scenario "doesn't pollute the Object namespace" do
|
|
39
|
+
expect(Object.new).not_to respond_to(:feature)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
feature 'nested features' do
|
|
43
|
+
scenario 'work as expected' do
|
|
44
|
+
visit '/'
|
|
45
|
+
expect(page).to have_content 'Hello world!'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
scenario 'are marked in the metadata as capybara_feature' do |ex|
|
|
49
|
+
expect(ex.metadata[:capybara_feature]).to be_truthy
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
scenario 'have a type of :feature' do |ex|
|
|
53
|
+
expect(ex.metadata[:type]).to eq :feature
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
# rubocop:enable RSpec/InstanceVariable
|
|
58
|
+
|
|
59
|
+
feature 'given and given! aliases to let and let!' do
|
|
60
|
+
given(:value) { :available }
|
|
61
|
+
given!(:value_in_background) { :available }
|
|
62
|
+
|
|
63
|
+
background do
|
|
64
|
+
expect(value_in_background).to be(:available)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
scenario 'given and given! work as intended' do
|
|
68
|
+
expect(value).to be(:available)
|
|
69
|
+
expect(value_in_background).to be(:available)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
feature "Capybara's feature DSL with driver", driver: :culerity do
|
|
74
|
+
scenario 'switches driver' do
|
|
75
|
+
expect(Capybara.current_driver).to eq(:culerity)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# rubocop:disable RSpec/RepeatedExample
|
|
80
|
+
xfeature 'if xfeature aliases to pending then' do
|
|
81
|
+
scenario "this should be 'temporarily disabled with xfeature'" do
|
|
82
|
+
# dummy
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
scenario "this also should be 'temporarily disabled with xfeature'" do
|
|
86
|
+
# dummy
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
ffeature 'if ffeature aliases focused tag then' do # rubocop:disable RSpec/Focus
|
|
91
|
+
scenario 'scenario inside this feature has metatag focus tag' do |example|
|
|
92
|
+
expect(example.metadata[:focus]).to eq true
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
scenario 'other scenarios also has metatag focus tag ' do |example|
|
|
96
|
+
expect(example.metadata[:focus]).to eq true
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
# rubocop:enable RSpec/RepeatedExample
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'capybara/rspec'
|
|
5
|
+
|
|
6
|
+
RSpec.configuration.before(:each, file_path: './spec/rspec/scenarios_spec.rb') do
|
|
7
|
+
@in_filtered_hook = true
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
feature 'if fscenario aliases focused tag then' do
|
|
11
|
+
fscenario 'scenario should have focused meta tag' do |example| # rubocop:disable RSpec/Focus
|
|
12
|
+
expect(example.metadata[:focus]).to eq true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
feature 'if xscenario aliases to pending then' do
|
|
17
|
+
xscenario "this test should be 'temporarily disabled with xscenario'" do
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,947 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'capybara/dsl'
|
|
5
|
+
require 'capybara/rspec/matchers'
|
|
6
|
+
require 'benchmark'
|
|
7
|
+
|
|
8
|
+
# rubocop:disable RSpec/ExpectActual
|
|
9
|
+
|
|
10
|
+
RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
11
|
+
include Capybara::DSL
|
|
12
|
+
include Capybara::RSpecMatchers
|
|
13
|
+
|
|
14
|
+
describe 'have_css matcher' do
|
|
15
|
+
it 'gives proper description' do
|
|
16
|
+
expect(have_css('h1').description).to eq('have visible css "h1"')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context 'on a string' do
|
|
20
|
+
context 'with should' do
|
|
21
|
+
it 'passes if has_css? returns true' do
|
|
22
|
+
expect('<h1>Text</h1>').to have_css('h1')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'fails if has_css? returns false' do
|
|
26
|
+
expect do
|
|
27
|
+
expect('<h1>Text</h1>').to have_css('h2')
|
|
28
|
+
end.to raise_error(/expected to find css "h2" but there were no matches/)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'passes if matched node count equals expected count' do
|
|
32
|
+
expect('<h1>Text</h1>').to have_css('h1', count: 1)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'fails if matched node count does not equal expected count' do
|
|
36
|
+
expect do
|
|
37
|
+
expect('<h1>Text</h1>').to have_css('h1', count: 2)
|
|
38
|
+
end.to raise_error('expected to find visible css "h1" 2 times, found 1 match: "Text"')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'fails if matched node count is less than expected minimum count' do
|
|
42
|
+
expect do
|
|
43
|
+
expect('<h1>Text</h1>').to have_css('p', minimum: 1)
|
|
44
|
+
end.to raise_error('expected to find css "p" at least 1 time but there were no matches')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'fails if matched node count is more than expected maximum count' do
|
|
48
|
+
expect do
|
|
49
|
+
expect('<h1>Text</h1><h1>Text</h1><h1>Text</h1>').to have_css('h1', maximum: 2)
|
|
50
|
+
end.to raise_error('expected to find visible css "h1" at most 2 times, found 3 matches: "Text", "Text", "Text"')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'fails if matched node count does not belong to expected range' do
|
|
54
|
+
expect do
|
|
55
|
+
expect('<h1>Text</h1>').to have_css('h1', between: 2..3)
|
|
56
|
+
end.to raise_error('expected to find visible css "h1" between 2 and 3 times, found 1 match: "Text"')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'with should_not' do
|
|
61
|
+
it 'passes if has_no_css? returns true' do
|
|
62
|
+
expect('<h1>Text</h1>').not_to have_css('h2')
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'fails if has_no_css? returns false' do
|
|
66
|
+
expect do
|
|
67
|
+
expect('<h1>Text</h1>').not_to have_css('h1')
|
|
68
|
+
end.to raise_error(/expected not to find visible css "h1"/)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'passes if matched node count does not equal expected count' do
|
|
72
|
+
expect('<h1>Text</h1>').not_to have_css('h1', count: 2)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'fails if matched node count equals expected count' do
|
|
76
|
+
expect do
|
|
77
|
+
expect('<h1>Text</h1>').not_to have_css('h1', count: 1)
|
|
78
|
+
end.to raise_error(/expected not to find visible css "h1"/)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'supports compounding' do
|
|
83
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_css('h1').and have_css('h2')
|
|
84
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_css('h3').or have_css('h1')
|
|
85
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_no_css('h4').and have_css('h2')
|
|
86
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_no_css('h2').or have_css('h1')
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'on a page or node' do
|
|
91
|
+
before do
|
|
92
|
+
visit('/with_html')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'with should' do
|
|
96
|
+
it 'passes if has_css? returns true' do
|
|
97
|
+
expect(page).to have_css('h1')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'fails if has_css? returns false' do
|
|
101
|
+
expect do
|
|
102
|
+
expect(page).to have_css('h1#doesnotexist')
|
|
103
|
+
end.to raise_error(/expected to find css "h1#doesnotexist" but there were no matches/)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'with should_not' do
|
|
108
|
+
it 'passes if has_no_css? returns true' do
|
|
109
|
+
expect(page).not_to have_css('h1#doesnotexist')
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'fails if has_no_css? returns false' do
|
|
113
|
+
expect do
|
|
114
|
+
expect(page).not_to have_css('h1')
|
|
115
|
+
end.to raise_error(/expected not to find visible css "h1"/)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe 'have_xpath matcher' do
|
|
122
|
+
it 'gives proper description' do
|
|
123
|
+
expect(have_xpath('//h1').description).to eq("have visible xpath \"\/\/h1\"")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
context 'on a string' do
|
|
127
|
+
context 'with should' do
|
|
128
|
+
it 'passes if has_xpath? returns true' do
|
|
129
|
+
expect('<h1>Text</h1>').to have_xpath('//h1')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'fails if has_xpath? returns false' do
|
|
133
|
+
expect do
|
|
134
|
+
expect('<h1>Text</h1>').to have_xpath('//h2')
|
|
135
|
+
end.to raise_error(%r{expected to find xpath "//h2" but there were no matches})
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
context 'with should_not' do
|
|
140
|
+
it 'passes if has_no_xpath? returns true' do
|
|
141
|
+
expect('<h1>Text</h1>').not_to have_xpath('//h2')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'fails if has_no_xpath? returns false' do
|
|
145
|
+
expect do
|
|
146
|
+
expect('<h1>Text</h1>').not_to have_xpath('//h1')
|
|
147
|
+
end.to raise_error(%r{expected not to find visible xpath "//h1"})
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'supports compounding' do
|
|
152
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_xpath('//h1').and have_xpath('//h2')
|
|
153
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_xpath('//h3').or have_xpath('//h1')
|
|
154
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_no_xpath('//h4').and have_xpath('//h1')
|
|
155
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_no_xpath('//h4').or have_xpath('//h4')
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context 'on a page or node' do
|
|
160
|
+
before do
|
|
161
|
+
visit('/with_html')
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context 'with should' do
|
|
165
|
+
it 'passes if has_xpath? returns true' do
|
|
166
|
+
expect(page).to have_xpath('//h1')
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it 'fails if has_xpath? returns false' do
|
|
170
|
+
expect do
|
|
171
|
+
expect(page).to have_xpath("//h1[@id='doesnotexist']")
|
|
172
|
+
end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context 'with should_not' do
|
|
177
|
+
it 'passes if has_no_xpath? returns true' do
|
|
178
|
+
expect(page).not_to have_xpath('//h1[@id="doesnotexist"]')
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'fails if has_no_xpath? returns false' do
|
|
182
|
+
expect do
|
|
183
|
+
expect(page).not_to have_xpath('//h1')
|
|
184
|
+
end.to raise_error(%r{expected not to find visible xpath "//h1"})
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe 'have_selector matcher' do
|
|
191
|
+
it 'gives proper description' do
|
|
192
|
+
matcher = have_selector('//h1')
|
|
193
|
+
expect('<h1>Text</h1>').to matcher
|
|
194
|
+
expect(matcher.description).to eq('have visible xpath "//h1"')
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
context 'on a string' do
|
|
198
|
+
context 'with should' do
|
|
199
|
+
it 'passes if has_selector? returns true' do
|
|
200
|
+
expect('<h1>Text</h1>').to have_selector('//h1')
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'fails if has_selector? returns false' do
|
|
204
|
+
expect do
|
|
205
|
+
expect('<h1>Text</h1>').to have_selector('//h2')
|
|
206
|
+
end.to raise_error(%r{expected to find xpath "//h2" but there were no matches})
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
context 'with should_not' do
|
|
211
|
+
it 'passes if has_no_selector? returns true' do
|
|
212
|
+
expect('<h1>Text</h1>').not_to have_selector(:css, 'h2')
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'fails if has_no_selector? returns false' do
|
|
216
|
+
expect do
|
|
217
|
+
expect('<h1>Text</h1>').not_to have_selector(:css, 'h1')
|
|
218
|
+
end.to raise_error(/expected not to find visible css "h1"/)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context 'on a page or node' do
|
|
224
|
+
before do
|
|
225
|
+
visit('/with_html')
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
context 'with should' do
|
|
229
|
+
it 'passes if has_selector? returns true' do
|
|
230
|
+
expect(page).to have_selector('//h1', text: 'test')
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it 'fails if has_selector? returns false' do
|
|
234
|
+
expect do
|
|
235
|
+
expect(page).to have_selector("//h1[@id='doesnotexist']")
|
|
236
|
+
end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it 'includes text in error message' do
|
|
240
|
+
expect do
|
|
241
|
+
expect(page).to have_selector('//h1', text: 'wrong text')
|
|
242
|
+
end.to raise_error(%r{expected to find visible xpath "//h1" with text "wrong text" but there were no matches})
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
context 'with should_not' do
|
|
247
|
+
it 'passes if has_no_css? returns true' do
|
|
248
|
+
expect(page).not_to have_selector(:css, 'h1#doesnotexist')
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it 'fails if has_no_selector? returns false' do
|
|
252
|
+
expect do
|
|
253
|
+
expect(page).not_to have_selector(:css, 'h1', text: 'test')
|
|
254
|
+
end.to raise_error(/expected not to find visible css "h1" with text "test"/)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it 'supports compounding' do
|
|
260
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_selector('//h1').and have_selector('//h2')
|
|
261
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_selector('//h3').or have_selector('//h1')
|
|
262
|
+
expect('<h1>Text</h1><h2>Text</h2>').to have_no_selector('//h3').and have_selector('//h1')
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
describe 'have_content matcher' do
|
|
267
|
+
it 'gives proper description' do
|
|
268
|
+
expect(have_content('Text').description).to eq('have text "Text"')
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
context 'on a string' do
|
|
272
|
+
context 'with should' do
|
|
273
|
+
it 'passes if has_content? returns true' do
|
|
274
|
+
expect('<h1>Text</h1>').to have_content('Text')
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it 'passes if has_content? returns true using regexp' do
|
|
278
|
+
expect('<h1>Text</h1>').to have_content(/ext/)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it 'fails if has_content? returns false' do
|
|
282
|
+
expect do
|
|
283
|
+
expect('<h1>Text</h1>').to have_content('No such Text')
|
|
284
|
+
end.to raise_error(/expected to find text "No such Text" in "Text"/)
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
context 'with should_not' do
|
|
289
|
+
it 'passes if has_no_content? returns true' do
|
|
290
|
+
expect('<h1>Text</h1>').not_to have_content('No such Text')
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
it 'passes because escapes any characters that would have special meaning in a regexp' do
|
|
294
|
+
expect('<h1>Text</h1>').not_to have_content('.')
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it 'fails if has_no_content? returns false' do
|
|
298
|
+
expect do
|
|
299
|
+
expect('<h1>Text</h1>').not_to have_content('Text')
|
|
300
|
+
end.to raise_error(/expected not to find text "Text" in "Text"/)
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
context 'on a page or node' do
|
|
306
|
+
before do
|
|
307
|
+
visit('/with_html')
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
context 'with should' do
|
|
311
|
+
it 'passes if has_content? returns true' do
|
|
312
|
+
expect(page).to have_content('This is a test')
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it 'passes if has_content? returns true using regexp' do
|
|
316
|
+
expect(page).to have_content(/test/)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
it 'fails if has_content? returns false' do
|
|
320
|
+
expect do
|
|
321
|
+
expect(page).to have_content('No such Text')
|
|
322
|
+
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
context 'with default selector CSS' do
|
|
326
|
+
before { Capybara.default_selector = :css }
|
|
327
|
+
|
|
328
|
+
after { Capybara.default_selector = :xpath }
|
|
329
|
+
|
|
330
|
+
it 'fails if has_content? returns false' do
|
|
331
|
+
expect do
|
|
332
|
+
expect(page).to have_content('No such Text')
|
|
333
|
+
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
context 'with should_not' do
|
|
339
|
+
it 'passes if has_no_content? returns true' do
|
|
340
|
+
expect(page).not_to have_content('No such Text')
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it 'fails if has_no_content? returns false' do
|
|
344
|
+
expect do
|
|
345
|
+
expect(page).not_to have_content('This is a test')
|
|
346
|
+
end.to raise_error(/expected not to find text "This is a test"/)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it 'supports compounding' do
|
|
352
|
+
expect('<h1>Text</h1><h2>And</h2>').to have_content('Text').and have_content('And')
|
|
353
|
+
expect('<h1>Text</h1><h2>Or</h2>').to have_content('XYZ').or have_content('Or')
|
|
354
|
+
expect('<h1>Text</h1><h2>Or</h2>').to have_no_content('XYZ').and have_content('Or')
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
describe 'have_text matcher' do
|
|
359
|
+
it 'gives proper description' do
|
|
360
|
+
expect(have_text('Text').description).to eq('have text "Text"')
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
context 'on a string' do
|
|
364
|
+
context 'with should' do
|
|
365
|
+
it 'passes if text contains given string' do
|
|
366
|
+
expect('<h1>Text</h1>').to have_text('Text')
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it 'passes if text matches given regexp' do
|
|
370
|
+
expect('<h1>Text</h1>').to have_text(/ext/)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
it "fails if text doesn't contain given string" do
|
|
374
|
+
expect do
|
|
375
|
+
expect('<h1>Text</h1>').to have_text('No such Text')
|
|
376
|
+
end.to raise_error(/expected to find text "No such Text" in "Text"/)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it "fails if text doesn't match given regexp" do
|
|
380
|
+
expect do
|
|
381
|
+
expect('<h1>Text</h1>').to have_text(/No such Text/)
|
|
382
|
+
end.to raise_error('expected to find text matching /No such Text/ in "Text"')
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it 'casts Integer to string' do
|
|
386
|
+
expect do
|
|
387
|
+
expect('<h1>Text</h1>').to have_text(3)
|
|
388
|
+
end.to raise_error(/expected to find text "3" in "Text"/)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
it 'fails if matched text count does not equal to expected count' do
|
|
392
|
+
expect do
|
|
393
|
+
expect('<h1>Text</h1>').to have_text('Text', count: 2)
|
|
394
|
+
end.to raise_error('expected to find text "Text" 2 times but found 1 time in "Text"')
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
it 'fails if matched text count is less than expected minimum count' do
|
|
398
|
+
expect do
|
|
399
|
+
expect('<h1>Text</h1>').to have_text('Lorem', minimum: 1)
|
|
400
|
+
end.to raise_error('expected to find text "Lorem" at least 1 time but found 0 times in "Text"')
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it 'fails if matched text count is more than expected maximum count' do
|
|
404
|
+
expect do
|
|
405
|
+
expect('<h1>Text TextText</h1>').to have_text('Text', maximum: 2)
|
|
406
|
+
end.to raise_error('expected to find text "Text" at most 2 times but found 3 times in "Text TextText"')
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
it 'fails if matched text count does not belong to expected range' do
|
|
410
|
+
expect do
|
|
411
|
+
expect('<h1>Text</h1>').to have_text('Text', between: 2..3)
|
|
412
|
+
end.to raise_error('expected to find text "Text" between 2 and 3 times but found 1 time in "Text"')
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
context 'with should_not' do
|
|
417
|
+
it "passes if text doesn't contain a string" do
|
|
418
|
+
expect('<h1>Text</h1>').not_to have_text('No such Text')
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
it 'passes because escapes any characters that would have special meaning in a regexp' do
|
|
422
|
+
expect('<h1>Text</h1>').not_to have_text('.')
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
it 'fails if text contains a string' do
|
|
426
|
+
expect do
|
|
427
|
+
expect('<h1>Text</h1>').not_to have_text('Text')
|
|
428
|
+
end.to raise_error(/expected not to find text "Text" in "Text"/)
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
context 'on a page or node' do
|
|
434
|
+
before do
|
|
435
|
+
visit('/with_html')
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
context 'with should' do
|
|
439
|
+
it 'passes if has_text? returns true' do
|
|
440
|
+
expect(page).to have_text('This is a test')
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
it 'passes if has_text? returns true using regexp' do
|
|
444
|
+
expect(page).to have_text(/test/)
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it 'can check for all text' do
|
|
448
|
+
expect(page).to have_text(:all, 'Some of this text is hidden!')
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
it 'can check for visible text' do
|
|
452
|
+
expect(page).to have_text(:visible, 'Some of this text is')
|
|
453
|
+
expect(page).not_to have_text(:visible, 'Some of this text is hidden!')
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
it 'fails if has_text? returns false' do
|
|
457
|
+
expect do
|
|
458
|
+
expect(page).to have_text('No such Text')
|
|
459
|
+
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
context 'with default selector CSS' do
|
|
463
|
+
before { Capybara.default_selector = :css }
|
|
464
|
+
|
|
465
|
+
after { Capybara.default_selector = :xpath }
|
|
466
|
+
|
|
467
|
+
it 'fails if has_text? returns false' do
|
|
468
|
+
expect do
|
|
469
|
+
expect(page).to have_text('No such Text')
|
|
470
|
+
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
context 'with should_not' do
|
|
476
|
+
it 'passes if has_no_text? returns true' do
|
|
477
|
+
expect(page).not_to have_text('No such Text')
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
it 'fails if has_no_text? returns false' do
|
|
481
|
+
expect do
|
|
482
|
+
expect(page).not_to have_text('This is a test')
|
|
483
|
+
end.to raise_error(/expected not to find text "This is a test"/)
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
it 'supports compounding' do
|
|
489
|
+
expect('<h1>Text</h1><h2>And</h2>').to have_text('Text').and have_text('And')
|
|
490
|
+
expect('<h1>Text</h1><h2>Or</h2>').to have_text('Not here').or have_text('Or')
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
describe 'have_link matcher' do
|
|
495
|
+
let(:html) { '<a href="#">Just a link</a><a href="#">Another link</a>' }
|
|
496
|
+
|
|
497
|
+
it 'gives proper description' do
|
|
498
|
+
expect(have_link('Just a link').description).to eq('have visible link "Just a link"')
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
it 'passes if there is such a link' do
|
|
502
|
+
expect(html).to have_link('Just a link')
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
it 'fails if there is no such link' do
|
|
506
|
+
expect do
|
|
507
|
+
expect(html).to have_link('No such Link')
|
|
508
|
+
end.to raise_error(/expected to find link "No such Link"/)
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it 'supports compounding' do
|
|
512
|
+
expect(html).to have_link('Just a link').and have_link('Another link')
|
|
513
|
+
expect(html).to have_link('Not a link').or have_link('Another link')
|
|
514
|
+
expect(html).to have_no_link('Not a link').and have_link('Another link')
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
describe 'have_title matcher' do
|
|
519
|
+
it 'gives proper description' do
|
|
520
|
+
expect(have_title('Just a title').description).to eq('have title "Just a title"')
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
context 'on a string' do
|
|
524
|
+
let(:html) { '<title>Just a title</title>' }
|
|
525
|
+
|
|
526
|
+
it 'passes if there is such a title' do
|
|
527
|
+
expect(html).to have_title('Just a title')
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
it 'fails if there is no such title' do
|
|
531
|
+
expect do
|
|
532
|
+
expect(html).to have_title('No such title')
|
|
533
|
+
end.to raise_error('expected "Just a title" to include "No such title"')
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
it "fails if title doesn't match regexp" do
|
|
537
|
+
expect do
|
|
538
|
+
expect(html).to have_title(/[[:upper:]]+[[:lower:]]+l{2}o/)
|
|
539
|
+
end.to raise_error('expected "Just a title" to match /[[:upper:]]+[[:lower:]]+l{2}o/')
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
context 'on a page or node' do
|
|
544
|
+
it 'passes if there is such a title' do
|
|
545
|
+
visit('/with_js')
|
|
546
|
+
expect(page).to have_title('with_js')
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
it 'fails if there is no such title' do
|
|
550
|
+
visit('/with_js')
|
|
551
|
+
expect do
|
|
552
|
+
expect(page).to have_title('No such title')
|
|
553
|
+
end.to raise_error('expected "with_js" to include "No such title"')
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
context 'with wait' do
|
|
557
|
+
before do
|
|
558
|
+
session.visit('/with_js')
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
it 'waits if wait time is more than timeout' do
|
|
562
|
+
session.click_link('Change title')
|
|
563
|
+
using_wait_time 0 do
|
|
564
|
+
expect(session).to have_title('changed title', wait: 2)
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "doesn't wait if wait time is less than timeout" do
|
|
569
|
+
session.click_link('Change title')
|
|
570
|
+
using_wait_time 3 do
|
|
571
|
+
expect(session).not_to have_title('changed title', wait: 0)
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
it 'supports compounding' do
|
|
578
|
+
expect('<title>I compound</title>').to have_title('I dont compound').or have_title('I compound')
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
describe 'have_current_path matcher' do
|
|
583
|
+
it 'gives proper description' do
|
|
584
|
+
expect(have_current_path('http://www.example.com').description).to eq('have current path "http://www.example.com"')
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
context 'on a page or node' do
|
|
588
|
+
it 'passes if there is such a current path' do
|
|
589
|
+
visit('/with_js')
|
|
590
|
+
expect(page).to have_current_path('/with_js')
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
it 'fails if there is no such current_path' do
|
|
594
|
+
visit('/with_js')
|
|
595
|
+
expect do
|
|
596
|
+
expect(page).to have_current_path('/not_with_js')
|
|
597
|
+
end.to raise_error('expected "/with_js" to equal "/not_with_js"')
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
context 'with wait' do
|
|
601
|
+
before do
|
|
602
|
+
session.visit('/with_js')
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
it 'waits if wait time is more than timeout' do
|
|
606
|
+
session.click_link('Change page')
|
|
607
|
+
using_wait_time 0 do
|
|
608
|
+
expect(session).to have_current_path('/with_html', wait: 2)
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
it "doesn't wait if wait time is less than timeout" do
|
|
613
|
+
session.click_link('Change page')
|
|
614
|
+
using_wait_time 0 do
|
|
615
|
+
expect(session).not_to have_current_path('/with_html')
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
it 'supports compounding' do
|
|
622
|
+
visit('/with_html')
|
|
623
|
+
expect(page).to have_current_path('/not_with_html').or have_current_path('/with_html')
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
describe 'have_button matcher' do
|
|
628
|
+
let(:html) { '<button>A button</button><input type="submit" value="Another button"/>' }
|
|
629
|
+
|
|
630
|
+
it 'gives proper description with no options' do
|
|
631
|
+
expect(have_button('A button').description).to eq('have visible button "A button" that is not disabled')
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
it 'gives proper description with disabled :any option' do
|
|
635
|
+
expect(have_button('A button', disabled: :all).description).to eq('have visible button "A button"')
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
it 'passes if there is such a button' do
|
|
639
|
+
expect(html).to have_button('A button')
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
it 'fails if there is no such button' do
|
|
643
|
+
expect do
|
|
644
|
+
expect(html).to have_button('No such Button')
|
|
645
|
+
end.to raise_error(/expected to find button "No such Button"/)
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
it 'supports compounding' do
|
|
649
|
+
expect(html).to have_button('Not this button').or have_button('A button')
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
describe 'have_field matcher' do
|
|
654
|
+
let(:html) { '<p><label>Text field<input type="text" value="some value"/></label></p>' }
|
|
655
|
+
|
|
656
|
+
it 'gives proper description' do
|
|
657
|
+
expect(have_field('Text field').description).to eq('have visible field "Text field" that is not disabled')
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
it 'gives proper description for a given value' do
|
|
661
|
+
expect(have_field('Text field', with: 'some value').description).to eq('have visible field "Text field" that is not disabled with value "some value"')
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
it 'passes if there is such a field' do
|
|
665
|
+
expect(html).to have_field('Text field')
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
it 'passes if there is such a field with value' do
|
|
669
|
+
expect(html).to have_field('Text field', with: 'some value')
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
it 'fails if there is no such field' do
|
|
673
|
+
expect do
|
|
674
|
+
expect(html).to have_field('No such Field')
|
|
675
|
+
end.to raise_error(/expected to find field "No such Field"/)
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
it 'fails if there is such field but with false value' do
|
|
679
|
+
expect do
|
|
680
|
+
expect(html).to have_field('Text field', with: 'false value')
|
|
681
|
+
end.to raise_error(/expected to find visible field "Text field"/)
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
it 'treats a given value as a string' do
|
|
685
|
+
foo = Class.new do
|
|
686
|
+
def to_s
|
|
687
|
+
'some value'
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
expect(html).to have_field('Text field', with: foo.new)
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
it 'supports compounding' do
|
|
694
|
+
expect(html).to have_field('Not this one').or have_field('Text field')
|
|
695
|
+
end
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
describe 'have_checked_field matcher' do
|
|
699
|
+
let(:html) do
|
|
700
|
+
'<label>it is checked<input type="checkbox" checked="checked"/></label>
|
|
701
|
+
<label>unchecked field<input type="checkbox"/></label>'
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
it 'gives proper description' do
|
|
705
|
+
expect(have_checked_field('it is checked').description).to eq('have visible field "it is checked" that is not disabled that is checked')
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
context 'with should' do
|
|
709
|
+
it 'passes if there is such a field and it is checked' do
|
|
710
|
+
expect(html).to have_checked_field('it is checked')
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
it 'fails if there is such a field but it is not checked' do
|
|
714
|
+
expect do
|
|
715
|
+
expect(html).to have_checked_field('unchecked field')
|
|
716
|
+
end.to raise_error(/expected to find visible field "unchecked field"/)
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
it 'fails if there is no such field' do
|
|
720
|
+
expect do
|
|
721
|
+
expect(html).to have_checked_field('no such field')
|
|
722
|
+
end.to raise_error(/expected to find field "no such field"/)
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
context 'with should not' do
|
|
727
|
+
it 'fails if there is such a field and it is checked' do
|
|
728
|
+
expect do
|
|
729
|
+
expect(html).not_to have_checked_field('it is checked')
|
|
730
|
+
end.to raise_error(/expected not to find visible field "it is checked"/)
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
it 'passes if there is such a field but it is not checked' do
|
|
734
|
+
expect(html).not_to have_checked_field('unchecked field')
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
it 'passes if there is no such field' do
|
|
738
|
+
expect(html).not_to have_checked_field('no such field')
|
|
739
|
+
end
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
it 'supports compounding' do
|
|
743
|
+
expect(html).to have_checked_field('not this one').or have_checked_field('it is checked')
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
describe 'have_unchecked_field matcher' do
|
|
748
|
+
let(:html) do
|
|
749
|
+
'<label>it is checked<input type="checkbox" checked="checked"/></label>
|
|
750
|
+
<label>unchecked field<input type="checkbox"/></label>'
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
it 'gives proper description' do
|
|
754
|
+
expect(have_unchecked_field('unchecked field').description).to eq('have visible field "unchecked field" that is not disabled that is not checked')
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
context 'with should' do
|
|
758
|
+
it 'passes if there is such a field and it is not checked' do
|
|
759
|
+
expect(html).to have_unchecked_field('unchecked field')
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
it 'fails if there is such a field but it is checked' do
|
|
763
|
+
expect do
|
|
764
|
+
expect(html).to have_unchecked_field('it is checked')
|
|
765
|
+
end.to raise_error(/expected to find visible field "it is checked"/)
|
|
766
|
+
end
|
|
767
|
+
|
|
768
|
+
it 'fails if there is no such field' do
|
|
769
|
+
expect do
|
|
770
|
+
expect(html).to have_unchecked_field('no such field')
|
|
771
|
+
end.to raise_error(/expected to find field "no such field"/)
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
context 'with should not' do
|
|
776
|
+
it 'fails if there is such a field and it is not checked' do
|
|
777
|
+
expect do
|
|
778
|
+
expect(html).not_to have_unchecked_field('unchecked field')
|
|
779
|
+
end.to raise_error(/expected not to find visible field "unchecked field"/)
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
it 'passes if there is such a field but it is checked' do
|
|
783
|
+
expect(html).not_to have_unchecked_field('it is checked')
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
it 'passes if there is no such field' do
|
|
787
|
+
expect(html).not_to have_unchecked_field('no such field')
|
|
788
|
+
end
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
it 'supports compounding' do
|
|
792
|
+
expect(html).to have_unchecked_field('it is checked').or have_unchecked_field('unchecked field')
|
|
793
|
+
end
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
describe 'have_select matcher' do
|
|
797
|
+
let(:html) { '<label>Select Box<select></select></label>' }
|
|
798
|
+
|
|
799
|
+
it 'gives proper description' do
|
|
800
|
+
expect(have_select('Select Box').description).to eq('have visible select box "Select Box" that is not disabled')
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
it 'gives proper description for a given selected value' do
|
|
804
|
+
expect(have_select('Select Box', selected: 'some value').description).to eq('have visible select box "Select Box" that is not disabled with "some value" selected')
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
it 'passes if there is such a select' do
|
|
808
|
+
expect(html).to have_select('Select Box')
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
it 'fails if there is no such select' do
|
|
812
|
+
expect do
|
|
813
|
+
expect(html).to have_select('No such Select box')
|
|
814
|
+
end.to raise_error(/expected to find select box "No such Select box"/)
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
it 'supports compounding' do
|
|
818
|
+
expect(html).to have_select('Not this one').or have_select('Select Box')
|
|
819
|
+
end
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
describe 'have_table matcher' do
|
|
823
|
+
let(:html) { '<table><caption>Lovely table</caption></table>' }
|
|
824
|
+
|
|
825
|
+
it 'gives proper description' do
|
|
826
|
+
expect(have_table('Lovely table').description).to eq('have visible table "Lovely table"')
|
|
827
|
+
expect(have_table('Lovely table', caption: 'my caption').description).to eq('have visible table "Lovely table" with caption "my caption"')
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
it 'gives proper description when :visible option passed' do
|
|
831
|
+
expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"')
|
|
832
|
+
expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
|
|
833
|
+
expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
|
|
834
|
+
expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"')
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
it 'passes if there is such a table' do
|
|
838
|
+
expect(html).to have_table('Lovely table')
|
|
839
|
+
end
|
|
840
|
+
|
|
841
|
+
it 'fails if there is no such table' do
|
|
842
|
+
expect do
|
|
843
|
+
expect(html).to have_table('No such Table')
|
|
844
|
+
end.to raise_error(/expected to find table "No such Table"/)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
it 'supports compounding' do
|
|
848
|
+
expect(html).to have_table('nope').or have_table('Lovely table')
|
|
849
|
+
end
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
context 'compounding timing' do
|
|
853
|
+
let(:session) { session }
|
|
854
|
+
let(:el) { session.find(:css, '#reload-me') }
|
|
855
|
+
|
|
856
|
+
before do
|
|
857
|
+
session.visit('/with_js')
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
describe '#and' do
|
|
861
|
+
it "should run 'concurrently'" do
|
|
862
|
+
Capybara.using_wait_time(2) do
|
|
863
|
+
matcher = have_text('this is not there').and have_text('neither is this')
|
|
864
|
+
expect(Benchmark.realtime do
|
|
865
|
+
expect do
|
|
866
|
+
expect(el).to matcher
|
|
867
|
+
end.to raise_error RSpec::Expectations::ExpectationNotMetError
|
|
868
|
+
end).to be_between(2, 3)
|
|
869
|
+
end
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
it "should run 'concurrently' and retry" do
|
|
873
|
+
session.click_link('reload-link')
|
|
874
|
+
session.using_wait_time(2) do
|
|
875
|
+
expect(Benchmark.realtime do
|
|
876
|
+
expect do
|
|
877
|
+
expect(el).to have_text('waiting to be reloaded').and(have_text('has been reloaded'))
|
|
878
|
+
end.to raise_error RSpec::Expectations::ExpectationNotMetError, /expected to find text "waiting to be reloaded" in "has been reloaded"/
|
|
879
|
+
end).to be_between(2, 3)
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
it 'should ignore :wait options' do
|
|
884
|
+
session.using_wait_time(2) do
|
|
885
|
+
matcher = have_text('this is not there', wait: 5).and have_text('neither is this', wait: 6)
|
|
886
|
+
expect(Benchmark.realtime do
|
|
887
|
+
expect do
|
|
888
|
+
expect(el).to matcher
|
|
889
|
+
end.to raise_error RSpec::Expectations::ExpectationNotMetError
|
|
890
|
+
end).to be_between(2, 3)
|
|
891
|
+
end
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
it 'should work on the session' do
|
|
895
|
+
session.using_wait_time(2) do
|
|
896
|
+
session.click_link('reload-link')
|
|
897
|
+
expect(session).to have_selector(:css, 'h1', text: 'FooBar').and have_text('has been reloaded')
|
|
898
|
+
end
|
|
899
|
+
end
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
describe '#and_then' do
|
|
903
|
+
it 'should run sequentially' do
|
|
904
|
+
session.click_link('reload-link')
|
|
905
|
+
expect(el).to have_text('waiting to be reloaded').and_then have_text('has been reloaded')
|
|
906
|
+
end
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
describe '#or' do
|
|
910
|
+
it "should run 'concurrently'" do
|
|
911
|
+
session.using_wait_time(3) do
|
|
912
|
+
expect(Benchmark.realtime do
|
|
913
|
+
expect(el).to have_text('has been reloaded').or have_text('waiting to be reloaded')
|
|
914
|
+
end).to be < 1
|
|
915
|
+
end
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
it 'should retry' do
|
|
919
|
+
session.using_wait_time(3) do
|
|
920
|
+
expect(Benchmark.realtime do
|
|
921
|
+
expect do
|
|
922
|
+
expect(el).to have_text('has been reloaded').or have_text('random stuff')
|
|
923
|
+
end.to raise_error RSpec::Expectations::ExpectationNotMetError
|
|
924
|
+
end).to be > 3
|
|
925
|
+
end
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
it 'should ignore :wait options' do
|
|
929
|
+
session.using_wait_time(2) do
|
|
930
|
+
expect(Benchmark.realtime do
|
|
931
|
+
expect do
|
|
932
|
+
expect(el).to have_text('this is not there', wait: 10).or have_text('neither is this', wait: 15)
|
|
933
|
+
end.to raise_error RSpec::Expectations::ExpectationNotMetError
|
|
934
|
+
end).to be_between(2, 3)
|
|
935
|
+
end
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
it 'should work on the session' do
|
|
939
|
+
session.using_wait_time(2) do
|
|
940
|
+
session.click_link('reload-link')
|
|
941
|
+
expect(session).to have_selector(:css, 'h1', text: 'Not on the page').or have_text('has been reloaded')
|
|
942
|
+
end
|
|
943
|
+
end
|
|
944
|
+
end
|
|
945
|
+
end
|
|
946
|
+
end
|
|
947
|
+
# rubocop:enable RSpec/ExpectActual
|