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
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe 'capybara/rspec', type: :view do
|
|
6
|
+
it 'allows matchers to be used on strings' do
|
|
7
|
+
html = %(<h1>Test header</h1>)
|
|
8
|
+
expect(html).to have_css('h1', text: 'Test header')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "doesn't include RSpecMatcherProxies" do
|
|
12
|
+
expect(self.class.ancestors).not_to include(Capybara::RSpecMatcherProxies)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe 'Capybara RSpec Matchers', type: :feature do
|
|
6
|
+
context 'after called on session' do
|
|
7
|
+
it 'HaveSelector should allow getting a description of the matcher' do
|
|
8
|
+
visit('/with_html')
|
|
9
|
+
matcher = have_selector(:css, 'h2.head', minimum: 3)
|
|
10
|
+
expect(page).to matcher
|
|
11
|
+
expect { matcher.description }.not_to raise_error
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'HaveText should allow getting a description' do
|
|
15
|
+
visit('/with_html')
|
|
16
|
+
matcher = have_text('Lorem')
|
|
17
|
+
expect(page).to matcher
|
|
18
|
+
expect { matcher.description }.not_to raise_error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should produce the same error for .to have_no_xxx and .not_to have_xxx' do
|
|
22
|
+
visit('/with_html')
|
|
23
|
+
not_to_msg = error_msg_for { expect(page).not_to have_selector(:css, '#referrer') }
|
|
24
|
+
have_no_msg = error_msg_for { expect(page).to have_no_selector(:css, '#referrer') }
|
|
25
|
+
expect(not_to_msg).to eq have_no_msg
|
|
26
|
+
|
|
27
|
+
not_to_msg = error_msg_for { expect(page).not_to have_text('This is a test') }
|
|
28
|
+
have_no_msg = error_msg_for { expect(page).to have_no_text('This is a test') }
|
|
29
|
+
expect(not_to_msg).to eq have_no_msg
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'after called on element' do
|
|
34
|
+
it 'HaveSelector should allow getting a description' do
|
|
35
|
+
visit('/with_html')
|
|
36
|
+
el = find(:css, '#first')
|
|
37
|
+
matcher = have_selector(:css, 'a#foo')
|
|
38
|
+
expect(el).to matcher
|
|
39
|
+
expect { matcher.description }.not_to raise_error
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'MatchSelector should allow getting a description' do
|
|
43
|
+
visit('/with_html')
|
|
44
|
+
el = find(:css, '#first')
|
|
45
|
+
matcher = match_selector(:css, '#first')
|
|
46
|
+
expect(el).to matcher
|
|
47
|
+
expect { matcher.description }.not_to raise_error
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'HaveText should allow getting a description' do
|
|
51
|
+
visit('/with_html')
|
|
52
|
+
el = find(:css, '#first')
|
|
53
|
+
matcher = have_text('Lorem')
|
|
54
|
+
expect(el).to matcher
|
|
55
|
+
expect { matcher.description }.not_to raise_error
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def error_msg_for(&block)
|
|
60
|
+
expect(&block).to(raise_error { |e| return e.message })
|
|
61
|
+
end
|
|
62
|
+
end
|
data/spec/rspec_spec.rb
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe 'capybara/rspec' do
|
|
6
|
+
context 'Feature', type: :feature do
|
|
7
|
+
it 'should include Capybara in rspec' do
|
|
8
|
+
visit('/foo')
|
|
9
|
+
expect(page.body).to include('Another World')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'should include RSpec matcher proxies' do
|
|
13
|
+
expect(self.class.ancestors).to include Capybara::RSpecMatcherProxies
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'resetting session' do
|
|
17
|
+
it 'sets a cookie in one example...' do
|
|
18
|
+
visit('/set_cookie')
|
|
19
|
+
expect(page.body).to include('Cookie set to test_cookie')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it '...then it is not available in the next' do
|
|
23
|
+
visit('/get_cookie')
|
|
24
|
+
expect(page.body).not_to include('test_cookie')
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'setting the current driver' do
|
|
29
|
+
it 'sets the current driver in one example...' do
|
|
30
|
+
Capybara.current_driver = :selenium
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it '...then it has returned to the default in the next example' do
|
|
34
|
+
expect(Capybara.current_driver).to eq(:rack_test)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'switches to the javascript driver when giving it as metadata', js: true do
|
|
39
|
+
expect(Capybara.current_driver).to eq(Capybara.javascript_driver)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'switches to the given driver when giving it as metadata', driver: :culerity do
|
|
43
|
+
expect(Capybara.current_driver).to eq(:culerity)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '#all' do
|
|
47
|
+
it 'allows access to the Capybara finder' do
|
|
48
|
+
visit('/with_html')
|
|
49
|
+
found = all(:css, 'h2') { |element| element[:class] == 'head' }
|
|
50
|
+
expect(found.size).to eq(5)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'allows access to the RSpec matcher' do
|
|
54
|
+
visit('/with_html')
|
|
55
|
+
strings = %w[test1 test2]
|
|
56
|
+
expect(strings).to all(be_a(String))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe '#within' do
|
|
61
|
+
it 'allows access to the Capybara scoper' do
|
|
62
|
+
visit('/with_html')
|
|
63
|
+
expect do
|
|
64
|
+
within(:css, '#does_not_exist') { click_link 'Go to simple' }
|
|
65
|
+
end.to raise_error(Capybara::ElementNotFound)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'allows access to the RSpec matcher' do
|
|
69
|
+
visit('/with_html')
|
|
70
|
+
# This reads terribly, but must call #within
|
|
71
|
+
expect(find(:css, 'span.number').text.to_i).to within(1).of(41)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context 'Type: Other', type: :other do
|
|
77
|
+
context 'when RSpec::Matchers is included after Capybara::DSL' do
|
|
78
|
+
let(:test_class_instance) do
|
|
79
|
+
Class.new do
|
|
80
|
+
include Capybara::DSL
|
|
81
|
+
include RSpec::Matchers
|
|
82
|
+
end.new
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe '#all' do
|
|
86
|
+
it 'allows access to the Capybara finder' do
|
|
87
|
+
test_class_instance.visit('/with_html')
|
|
88
|
+
expect(test_class_instance.all(:css, 'h2.head').size).to eq(5)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'allows access to the RSpec matcher' do
|
|
92
|
+
test_class_instance.visit('/with_html')
|
|
93
|
+
strings = %w[test1 test2]
|
|
94
|
+
expect(strings).to test_class_instance.all(be_a(String))
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#within' do
|
|
99
|
+
it 'allows access to the Capybara scoper' do
|
|
100
|
+
test_class_instance.visit('/with_html')
|
|
101
|
+
expect do
|
|
102
|
+
test_class_instance.within(:css, '#does_not_exist') { test_class_instance.click_link 'Go to simple' }
|
|
103
|
+
end.to raise_error(Capybara::ElementNotFound)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'allows access to the RSpec matcher' do
|
|
107
|
+
test_class_instance.visit('/with_html')
|
|
108
|
+
# This reads terribly, but must call #within
|
|
109
|
+
expect(test_class_instance.find(:css, 'span.number').text.to_i).to test_class_instance.within(1).of(41)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'when `match_when_negated` is not defined in a matcher' do
|
|
114
|
+
before do
|
|
115
|
+
RSpec::Matchers.define :only_match_matcher do |expected|
|
|
116
|
+
match do |actual|
|
|
117
|
+
!(actual ^ expected)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'can be called with `not_to`' do
|
|
123
|
+
# This test is for a bug in jruby where `super` isn't defined correctly - https://github.com/jruby/jruby/issues/4678
|
|
124
|
+
# Reported in https://github.com/teamcapybara/capybara/issues/2115
|
|
125
|
+
test_class_instance.instance_eval do
|
|
126
|
+
expect do
|
|
127
|
+
expect(true).not_to only_match_matcher(false) # rubocop:disable RSpec/ExpectActual
|
|
128
|
+
end.not_to raise_error
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'should not include Capybara' do
|
|
135
|
+
expect { visit('/') }.to raise_error(NoMethodError)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
feature 'Feature DSL' do
|
|
141
|
+
scenario 'is pulled in' do
|
|
142
|
+
visit('/foo')
|
|
143
|
+
expect(page.body).to include('Another World')
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'selenium-webdriver'
|
|
5
|
+
|
|
6
|
+
require 'sauce_whisk'
|
|
7
|
+
# require 'shared_selenium_session'
|
|
8
|
+
# require 'shared_selenium_node'
|
|
9
|
+
# require 'rspec/shared_spec_matchers'
|
|
10
|
+
|
|
11
|
+
Capybara.register_driver :sauce_chrome do |app|
|
|
12
|
+
options = {
|
|
13
|
+
selenium_version: '3.141.59',
|
|
14
|
+
platform: 'macOS 10.12',
|
|
15
|
+
browser_name: 'chrome',
|
|
16
|
+
version: '65.0',
|
|
17
|
+
name: 'Capybara test',
|
|
18
|
+
build: ENV['TRAVIS_REPO_SLUG'] || "Ruby-RSpec-Selenium: Local-#{Time.now.to_i}",
|
|
19
|
+
username: ENV['SAUCE_USERNAME'],
|
|
20
|
+
access_key: ENV['SAUCE_ACCESS_KEY']
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
options.delete(:browser_name)
|
|
24
|
+
|
|
25
|
+
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(options)
|
|
26
|
+
url = 'https://ondemand.saucelabs.com:443/wd/hub'
|
|
27
|
+
|
|
28
|
+
Capybara::Selenium::Driver.new(app,
|
|
29
|
+
browser: :remote, url: url,
|
|
30
|
+
desired_capabilities: capabilities,
|
|
31
|
+
options: Selenium::WebDriver::Chrome::Options.new(args: ['']))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
CHROME_REMOTE_DRIVER = :sauce_chrome
|
|
35
|
+
|
|
36
|
+
module TestSessions
|
|
37
|
+
Chrome = Capybara::Session.new(CHROME_REMOTE_DRIVER, TestApp)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
skipped_tests = %i[response_headers status_code trigger download]
|
|
41
|
+
|
|
42
|
+
Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
|
|
43
|
+
end
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Capybara do
|
|
6
|
+
describe 'Selectors' do
|
|
7
|
+
let :string do
|
|
8
|
+
described_class.string <<-STRING
|
|
9
|
+
<html>
|
|
10
|
+
<head>
|
|
11
|
+
<title>selectors</title>
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<div class="aa" id="page">
|
|
15
|
+
<div class="bb" id="content">
|
|
16
|
+
<h1 class="aa">Totally awesome</h1>
|
|
17
|
+
<p>Yes it is</p>
|
|
18
|
+
</div>
|
|
19
|
+
<p class="bb cc">Some Content</p>
|
|
20
|
+
<p class="bb dd !mine"></p>
|
|
21
|
+
</div>
|
|
22
|
+
<div id="#special">
|
|
23
|
+
</div>
|
|
24
|
+
<div class="some random words" id="random_words">
|
|
25
|
+
Something
|
|
26
|
+
</div>
|
|
27
|
+
<input id="2checkbox" class="2checkbox" type="checkbox"/>
|
|
28
|
+
<input type="radio"/>
|
|
29
|
+
<label for="my_text_input">My Text Input</label>
|
|
30
|
+
<input type="text" name="form[my_text_input]" placeholder="my text" id="my_text_input"/>
|
|
31
|
+
<input type="file" id="file" class=".special file"/>
|
|
32
|
+
<input type="hidden" id="hidden_field" value="this is hidden"/>
|
|
33
|
+
<input type="submit" value="click me" title="submit button"/>
|
|
34
|
+
<input type="button" value="don't click me" title="Other button 1" style="line-height: 30px;"/>
|
|
35
|
+
<a href="#">link</a>
|
|
36
|
+
<fieldset></fieldset>
|
|
37
|
+
<select id="select">
|
|
38
|
+
<option value="a">A</option>
|
|
39
|
+
<option value="b" disabled>B</option>
|
|
40
|
+
<option value="c" selected>C</option>
|
|
41
|
+
</select>
|
|
42
|
+
<table>
|
|
43
|
+
<tr><td></td></tr>
|
|
44
|
+
</table>
|
|
45
|
+
<table id="rows">
|
|
46
|
+
<tr>
|
|
47
|
+
<td>A</td><td>B</td><td>C</td>
|
|
48
|
+
</tr>
|
|
49
|
+
<tr>
|
|
50
|
+
<td>D</td><td>E</td><td>F</td>
|
|
51
|
+
</tr>
|
|
52
|
+
</table>
|
|
53
|
+
<table id="cols">
|
|
54
|
+
<tbody>
|
|
55
|
+
<tr>
|
|
56
|
+
<td>A</td><td>D</td>
|
|
57
|
+
</tr>
|
|
58
|
+
<tr>
|
|
59
|
+
<td>B</td><td>E</td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td>C</td><td>F</td>
|
|
63
|
+
</tr>
|
|
64
|
+
</tbody>
|
|
65
|
+
</table>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
68
|
+
STRING
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
before do
|
|
72
|
+
described_class.add_selector :custom_selector do
|
|
73
|
+
css { |css_class| "div.#{css_class}" }
|
|
74
|
+
node_filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
described_class.add_selector :custom_css_selector do
|
|
78
|
+
css(:name, :other_name) do |selector, name: nil, **|
|
|
79
|
+
selector ||= ''
|
|
80
|
+
selector += "[name='#{name}']" if name
|
|
81
|
+
selector
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
expression_filter(:placeholder) do |expr, val|
|
|
85
|
+
expr + "[placeholder='#{val}']"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
expression_filter(:value) do |expr, val|
|
|
89
|
+
expr + "[value='#{val}']"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
expression_filter(:title) do |expr, val|
|
|
93
|
+
expr + "[title='#{val}']"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
described_class.add_selector :custom_xpath_selector do
|
|
98
|
+
xpath(:valid1, :valid2) { |selector| selector }
|
|
99
|
+
match { |value| value == 'match_me' }
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'supports `filter` as an alias for `node_filter`' do
|
|
104
|
+
expect do
|
|
105
|
+
described_class.add_selector :filter_alias_selector do
|
|
106
|
+
css { |_unused| 'div' }
|
|
107
|
+
filter(:something) { |_node, _value| true }
|
|
108
|
+
end
|
|
109
|
+
end.not_to raise_error
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe 'adding a selector' do
|
|
113
|
+
it 'can set default visiblity' do
|
|
114
|
+
described_class.add_selector :hidden_field do
|
|
115
|
+
visible :hidden
|
|
116
|
+
css { |_sel| 'input[type="hidden"]' }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
expect(string).to have_no_css('input[type="hidden"]')
|
|
120
|
+
expect(string).to have_selector(:hidden_field)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe 'modify_selector' do
|
|
125
|
+
it 'allows modifying a selector' do
|
|
126
|
+
el = string.find(:custom_selector, 'aa')
|
|
127
|
+
expect(el.tag_name).to eq 'div'
|
|
128
|
+
described_class.modify_selector :custom_selector do
|
|
129
|
+
css { |css_class| "h1.#{css_class}" }
|
|
130
|
+
end
|
|
131
|
+
el = string.find(:custom_selector, 'aa')
|
|
132
|
+
expect(el.tag_name).to eq 'h1'
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "doesn't change existing filters" do
|
|
136
|
+
described_class.modify_selector :custom_selector do
|
|
137
|
+
css { |css_class| "p.#{css_class}" }
|
|
138
|
+
end
|
|
139
|
+
expect(string).to have_selector(:custom_selector, 'bb', count: 1)
|
|
140
|
+
expect(string).to have_selector(:custom_selector, 'bb', not_empty: false, count: 1)
|
|
141
|
+
expect(string).to have_selector(:custom_selector, 'bb', not_empty: :all, count: 2)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe '::[]' do
|
|
146
|
+
it 'can find a selector' do
|
|
147
|
+
expect(Capybara::Selector[:field]).not_to be_nil
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'raises if no selector found' do
|
|
151
|
+
expect { Capybara::Selector[:no_exist] }.to raise_error(ArgumentError, /Unknown selector type/)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
describe '::for' do
|
|
156
|
+
it 'finds selector that matches the locator' do
|
|
157
|
+
expect(Capybara::Selector.for('match_me').name).to eq :custom_xpath_selector
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'returns nil if no match' do
|
|
161
|
+
expect(Capybara::Selector.for('nothing')).to be nil
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
describe 'xpath' do
|
|
166
|
+
it 'uses filter names passed in' do
|
|
167
|
+
described_class.add_selector :test do
|
|
168
|
+
xpath(:something, :other) { |_locator| XPath.descendant }
|
|
169
|
+
end
|
|
170
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
171
|
+
|
|
172
|
+
expect(selector.expression_filters.keys).to include(:something, :other)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it 'gets filter names from block if none passed to xpath method' do
|
|
176
|
+
described_class.add_selector :test do
|
|
177
|
+
xpath { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
178
|
+
end
|
|
179
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
180
|
+
|
|
181
|
+
expect(selector.expression_filters.keys).to include(:valid3, :valid4)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'ignores block parameters if names passed in' do
|
|
185
|
+
described_class.add_selector :test do
|
|
186
|
+
xpath(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
187
|
+
end
|
|
188
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
189
|
+
|
|
190
|
+
expect(selector.expression_filters.keys).to include(:valid1)
|
|
191
|
+
expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
describe 'css' do
|
|
196
|
+
it "supports filters specified in 'css' definition" do
|
|
197
|
+
expect(string).to have_selector(:custom_css_selector, 'input', name: 'form[my_text_input]')
|
|
198
|
+
expect(string).to have_no_selector(:custom_css_selector, 'input', name: 'form[not_my_text_input]')
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'supports explicitly defined expression filters' do
|
|
202
|
+
expect(string).to have_selector(:custom_css_selector, placeholder: 'my text')
|
|
203
|
+
expect(string).to have_no_selector(:custom_css_selector, placeholder: 'not my text')
|
|
204
|
+
expect(string).to have_selector(:custom_css_selector, value: 'click me', title: 'submit button')
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'uses filter names passed in' do
|
|
208
|
+
described_class.add_selector :test do
|
|
209
|
+
css(:name, :other_name) { |_locator| '' }
|
|
210
|
+
end
|
|
211
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
212
|
+
|
|
213
|
+
expect(selector.expression_filters.keys).to include(:name, :other_name)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it 'gets filter names from block if none passed to css method' do
|
|
217
|
+
described_class.add_selector :test do
|
|
218
|
+
css { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
219
|
+
end
|
|
220
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
221
|
+
|
|
222
|
+
expect(selector.expression_filters.keys).to include(:valid3, :valid4)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'ignores block parameters if names passed in' do
|
|
226
|
+
described_class.add_selector :test do
|
|
227
|
+
css(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
228
|
+
end
|
|
229
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
230
|
+
|
|
231
|
+
expect(selector.expression_filters.keys).to include(:valid1)
|
|
232
|
+
expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
describe 'builtin selectors' do
|
|
237
|
+
context 'when locator is nil' do
|
|
238
|
+
it 'devolves to just finding element types' do
|
|
239
|
+
selectors = {
|
|
240
|
+
field: ".//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]",
|
|
241
|
+
fieldset: './/fieldset',
|
|
242
|
+
link: './/a[./@href]',
|
|
243
|
+
link_or_button: ".//a[./@href] | .//input[./@type = 'submit' or ./@type = 'reset' or ./@type = 'image' or ./@type = 'button'] | .//button",
|
|
244
|
+
fillable_field: ".//*[self::input | self::textarea][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'radio' or ./@type = 'checkbox' or ./@type = 'hidden' or ./@type = 'file')]",
|
|
245
|
+
radio_button: ".//input[./@type = 'radio']",
|
|
246
|
+
checkbox: ".//input[./@type = 'checkbox']",
|
|
247
|
+
select: './/select',
|
|
248
|
+
option: './/option',
|
|
249
|
+
file_field: ".//input[./@type = 'file']",
|
|
250
|
+
table: './/table'
|
|
251
|
+
}
|
|
252
|
+
selectors.each do |selector, xpath|
|
|
253
|
+
results = string.all(selector, nil).to_a.map(&:native)
|
|
254
|
+
expect(results.size).to be > 0
|
|
255
|
+
expect(results).to eq string.all(:xpath, xpath).to_a.map(&:native)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
context 'with :id option' do
|
|
261
|
+
it 'works with compound css selectors' do
|
|
262
|
+
expect(string.all(:custom_css_selector, 'div, h1', id: 'page').size).to eq 1
|
|
263
|
+
expect(string.all(:custom_css_selector, 'h1, div', id: 'page').size).to eq 1
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "works with 'special' characters" do
|
|
267
|
+
expect(string.find(:custom_css_selector, 'div', id: '#special')[:id]).to eq '#special'
|
|
268
|
+
expect(string.find(:custom_css_selector, 'input', id: '2checkbox')[:id]).to eq '2checkbox'
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it 'accepts XPath expression for xpath based selectors' do
|
|
272
|
+
expect(string.find(:custom_xpath_selector, './/div', id: XPath.contains('peci'))[:id]).to eq '#special'
|
|
273
|
+
expect(string.find(:custom_xpath_selector, './/input', id: XPath.ends_with('box'))[:id]).to eq '2checkbox'
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it 'errors XPath expression for CSS based selectors' do
|
|
277
|
+
expect { string.find(:custom_css_selector, 'div', id: XPath.contains('peci')) }
|
|
278
|
+
.to raise_error(ArgumentError, /not supported/)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it 'accepts Regexp for xpath based selectors' do
|
|
282
|
+
expect(string.find(:custom_xpath_selector, './/div', id: /peci/)[:id]).to eq '#special'
|
|
283
|
+
expect(string.find(:custom_xpath_selector, './/div', id: /pEcI/i)[:id]).to eq '#special'
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it 'accepts Regexp for css based selectors' do
|
|
287
|
+
expect(string.find(:custom_css_selector, 'div', id: /sp.*al/)[:id]).to eq '#special'
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
context 'with :class option' do
|
|
292
|
+
it 'works with compound css selectors' do
|
|
293
|
+
expect(string.all(:custom_css_selector, 'div, h1', class: 'aa').size).to eq 2
|
|
294
|
+
expect(string.all(:custom_css_selector, 'h1, div', class: 'aa').size).to eq 2
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it 'handles negated classes' do
|
|
298
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['bb', '!cc']).size).to eq 2
|
|
299
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['!cc', '!dd', 'bb']).size).to eq 1
|
|
300
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['bb', '!cc']).size).to eq 2
|
|
301
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!cc', '!dd', 'bb']).size).to eq 1
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it 'handles classes starting with ! by requiring negated negated first' do
|
|
305
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['!!!mine']).size).to eq 1
|
|
306
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!!!mine']).size).to eq 1
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "works with 'special' characters" do
|
|
310
|
+
expect(string.find(:custom_css_selector, 'input', class: '.special')[:id]).to eq 'file'
|
|
311
|
+
expect(string.find(:custom_css_selector, 'input', class: '2checkbox')[:id]).to eq '2checkbox'
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it 'accepts XPath expression for xpath based selectors' do
|
|
315
|
+
expect(string.find(:custom_xpath_selector, './/div', class: XPath.contains('dom wor'))[:id]).to eq 'random_words'
|
|
316
|
+
expect(string.find(:custom_xpath_selector, './/div', class: XPath.ends_with('words'))[:id]).to eq 'random_words'
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
it 'errors XPath expression for CSS based selectors' do
|
|
320
|
+
expect { string.find(:custom_css_selector, 'div', class: XPath.contains('random')) }
|
|
321
|
+
.to raise_error(ArgumentError, /not supported/)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it 'accepts Regexp for XPath based selectors' do
|
|
325
|
+
expect(string.find(:custom_xpath_selector, './/div', class: /dom wor/)[:id]).to eq 'random_words'
|
|
326
|
+
expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it 'accepts Regexp for CSS base selectors' do
|
|
330
|
+
expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
context 'with :style option' do
|
|
335
|
+
it 'accepts string for CSS based selectors' do
|
|
336
|
+
expect(string.find(:custom_css_selector, 'input', style: 'line-height: 30px;')[:title]).to eq 'Other button 1'
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it 'accepts Regexp for CSS base selectors' do
|
|
340
|
+
expect(string.find(:custom_css_selector, 'input', style: /30px/)[:title]).to eq 'Other button 1'
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
|
|
345
|
+
# :option, :file_field, :label, :table, :frame
|
|
346
|
+
|
|
347
|
+
describe ':css selector' do
|
|
348
|
+
it 'finds by CSS locator' do
|
|
349
|
+
expect(string.find(:css, 'input#my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
describe ':xpath selector' do
|
|
354
|
+
it 'finds by XPath locator' do
|
|
355
|
+
expect(string.find(:xpath, './/input[@id="my_text_input"]')[:name]).to eq 'form[my_text_input]'
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
describe ':id selector' do
|
|
360
|
+
it 'finds by locator' do
|
|
361
|
+
expect(string.find(:id, 'my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
362
|
+
expect(string.find(:id, /my_text_input/)[:name]).to eq 'form[my_text_input]'
|
|
363
|
+
expect(string.find(:id, /_text_/)[:name]).to eq 'form[my_text_input]'
|
|
364
|
+
expect(string.find(:id, /i[nmo]/)[:name]).to eq 'form[my_text_input]'
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
describe ':field selector' do
|
|
369
|
+
it 'finds by locator' do
|
|
370
|
+
expect(string.find(:field, 'My Text Input')[:id]).to eq 'my_text_input'
|
|
371
|
+
expect(string.find(:field, 'my_text_input')[:id]).to eq 'my_text_input'
|
|
372
|
+
expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it 'finds by id string' do
|
|
376
|
+
expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it 'finds by id regexp' do
|
|
380
|
+
expect(string.find(:field, id: /my_text_inp/)[:name]).to eq 'form[my_text_input]'
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it 'finds by name' do
|
|
384
|
+
expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
it 'finds by placeholder' do
|
|
388
|
+
expect(string.find(:field, placeholder: 'my text')[:id]).to eq 'my_text_input'
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
it 'finds by type' do
|
|
392
|
+
expect(string.find(:field, type: 'file')[:id]).to eq 'file'
|
|
393
|
+
expect(string.find(:field, type: 'select')[:id]).to eq 'select'
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
describe ':option selector' do
|
|
398
|
+
it 'finds disabled options' do
|
|
399
|
+
expect(string.find(:option, disabled: true).value).to eq 'b'
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it 'finds selected options' do
|
|
403
|
+
expect(string.find(:option, selected: true).value).to eq 'c'
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
it 'finds not selected and not disabled options' do
|
|
407
|
+
expect(string.find(:option, disabled: false, selected: false).value).to eq 'a'
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
describe ':button selector' do
|
|
412
|
+
it 'finds by value' do
|
|
413
|
+
expect(string.find(:button, 'click me').value).to eq 'click me'
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
it 'finds by title' do
|
|
417
|
+
expect(string.find(:button, 'submit button').value).to eq 'click me'
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
it 'includes non-matching parameters in failure message' do
|
|
421
|
+
expect { string.find(:button, 'click me', title: 'click me') }.to raise_error(/with title click me/)
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
describe ':element selector' do
|
|
426
|
+
it 'finds by any attributes' do
|
|
427
|
+
expect(string.find(:element, 'input', type: 'submit').value).to eq 'click me'
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
it 'supports regexp matching' do
|
|
431
|
+
expect(string.find(:element, 'input', type: /sub/).value).to eq 'click me'
|
|
432
|
+
expect(string.find(:element, 'input', title: /sub\w.*button/).value).to eq 'click me'
|
|
433
|
+
expect(string.find(:element, 'input', title: /sub.* b.*ton/).value).to eq 'click me'
|
|
434
|
+
expect(string.find(:element, 'input', title: /sub.*mit.*/).value).to eq 'click me'
|
|
435
|
+
expect(string.find(:element, 'input', title: /^submit button$/).value).to eq 'click me'
|
|
436
|
+
expect(string.find(:element, 'input', title: /^(?:submit|other) button$/).value).to eq 'click me'
|
|
437
|
+
expect(string.find(:element, 'input', title: /SuB.*mIt/i).value).to eq 'click me'
|
|
438
|
+
expect(string.find(:element, 'input', title: /^Su.*Bm.*It/i).value).to eq 'click me'
|
|
439
|
+
expect(string.find(:element, 'input', title: /^Ot.*he.*r b.*\d/i).value).to eq "don't click me"
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it 'still works with system keys' do
|
|
443
|
+
expect { string.all(:element, 'input', type: 'submit', count: 1) }.not_to raise_error
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
it 'works without element type' do
|
|
447
|
+
expect(string.find(:element, type: 'submit').value).to eq 'click me'
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it 'validates attribute presence when true' do
|
|
451
|
+
expect(string.find(:element, name: true)[:id]).to eq 'my_text_input'
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it 'validates attribute absence when false' do
|
|
455
|
+
expect(string.find(:element, 'option', disabled: false, selected: false).value).to eq 'a'
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
it 'includes wildcarded keys in description' do
|
|
459
|
+
expect { string.find(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
|
|
460
|
+
.to(raise_error do |e|
|
|
461
|
+
expect(e).to be_a(Capybara::ElementNotFound)
|
|
462
|
+
expect(e.message).to include 'not_there => bad'
|
|
463
|
+
expect(e.message).to include 'with presence attribute'
|
|
464
|
+
expect(e.message).to include 'without absence attribute'
|
|
465
|
+
expect(e.message).not_to include 'count 1'
|
|
466
|
+
end)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it 'accepts XPath::Expression' do
|
|
470
|
+
expect(string.find(:element, 'input', type: XPath.starts_with('subm')).value).to eq 'click me'
|
|
471
|
+
expect(string.find(:element, 'input', type: XPath.ends_with('ext'))[:type]).to eq 'text'
|
|
472
|
+
expect(string.find(:element, 'input', type: XPath.contains('ckb'))[:type]).to eq 'checkbox'
|
|
473
|
+
expect(string.find(:element, 'input', title: XPath.contains_word('submit'))[:type]).to eq 'submit'
|
|
474
|
+
expect(string.find(:element, 'input', title: XPath.contains_word('button 1'))[:type]).to eq 'button'
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
describe ':link_or_button selector' do
|
|
479
|
+
around(:all) do |example|
|
|
480
|
+
described_class.modify_selector(:link_or_button) do
|
|
481
|
+
expression_filter(:random) { |xpath, _| xpath } # do nothing filter
|
|
482
|
+
end
|
|
483
|
+
example.run
|
|
484
|
+
Capybara::Selector[:link_or_button].expression_filters.delete(:random)
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it 'should not find links when disabled == true' do
|
|
488
|
+
expect(string.all(:link_or_button, disabled: true).size).to eq 0
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
context 'when modified' do
|
|
492
|
+
it 'should still work' do
|
|
493
|
+
filter = Capybara::Selector[:link_or_button].expression_filters[:random]
|
|
494
|
+
allow(filter).to receive(:apply_filter).and_call_original
|
|
495
|
+
|
|
496
|
+
expect(string.find(:link_or_button, 'click me', random: 'blah').value).to eq 'click me'
|
|
497
|
+
expect(filter).to have_received(:apply_filter).with(anything, :random, 'blah', anything)
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
describe ':table selector' do
|
|
503
|
+
it 'finds by rows' do
|
|
504
|
+
expect(string.find(:table, with_rows: [%w[D E F]])[:id]).to eq 'rows'
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
it 'finds by columns' do
|
|
508
|
+
expect(string.find(:table, with_cols: [%w[A B C]])[:id]).to eq 'cols'
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
end
|