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,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
|
4
|
+
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
|
5
|
+
# using Capybara provided assertions with builtin waiting behavior.
|
|
6
|
+
|
|
7
|
+
Capybara::SpecHelper.spec '#windows', requires: [:windows] do
|
|
8
|
+
before do
|
|
9
|
+
@window = @session.current_window
|
|
10
|
+
@session.visit('/with_windows')
|
|
11
|
+
@session.find(:css, '#openTwoWindows').click
|
|
12
|
+
|
|
13
|
+
@session.document.synchronize(3, errors: [Capybara::CapybaraError]) do
|
|
14
|
+
raise Capybara::CapybaraError if @session.windows.size != 3
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
after do
|
|
19
|
+
(@session.windows - [@window]).each(&:close)
|
|
20
|
+
@session.switch_to_window(@window)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should return objects of Capybara::Window class' do
|
|
24
|
+
expect(@session.windows.map { |window| window.instance_of?(Capybara::Window) }).to eq([true] * 3)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should be able to switch to windows' do
|
|
28
|
+
sleep 1 # give windows enough time to fully load
|
|
29
|
+
titles = @session.windows.map do |window|
|
|
30
|
+
@session.within_window(window) { @session.title }
|
|
31
|
+
end
|
|
32
|
+
expect(titles).to match_array(['With Windows', 'Title of the first popup', 'Title of popup two'])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
|
|
4
|
+
before do
|
|
5
|
+
@window = @session.current_window
|
|
6
|
+
@session.visit('/with_windows')
|
|
7
|
+
@session.find(:css, '#openTwoWindows').click
|
|
8
|
+
|
|
9
|
+
@session.document.synchronize(3, errors: [Capybara::CapybaraError]) do
|
|
10
|
+
raise Capybara::CapybaraError if @session.windows.size != 3
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
after do
|
|
15
|
+
(@session.windows - [@window]).each do |w|
|
|
16
|
+
@session.switch_to_window w
|
|
17
|
+
w.close
|
|
18
|
+
end
|
|
19
|
+
@session.switch_to_window(@window)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context 'with an instance of Capybara::Window' do
|
|
23
|
+
it 'should not invoke driver#switch_to_window when given current window' do
|
|
24
|
+
allow(@session.driver).to receive(:switch_to_window).and_call_original
|
|
25
|
+
@session.within_window @window do
|
|
26
|
+
expect(@session.title).to eq('With Windows')
|
|
27
|
+
end
|
|
28
|
+
expect(@session.driver).not_to have_received(:switch_to_window)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should be able to switch to another window' do
|
|
32
|
+
window = (@session.windows - [@window]).first
|
|
33
|
+
@session.within_window window do
|
|
34
|
+
expect(@session).to have_title(/Title of the first popup|Title of popup two/)
|
|
35
|
+
end
|
|
36
|
+
expect(@session.title).to eq('With Windows')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'returns value from the block' do
|
|
40
|
+
window = (@session.windows - [@window]).first
|
|
41
|
+
value = @session.within_window window do
|
|
42
|
+
43252003274489856000
|
|
43
|
+
end
|
|
44
|
+
expect(value).to eq(43252003274489856000)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'should switch back if exception was raised inside block' do
|
|
48
|
+
window = (@session.windows - [@window]).first
|
|
49
|
+
expect do
|
|
50
|
+
@session.within_window(window) do
|
|
51
|
+
@session.within 'html' do
|
|
52
|
+
raise 'some error'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end.to raise_error(StandardError, 'some error')
|
|
56
|
+
expect(@session.current_window).to eq(@window)
|
|
57
|
+
expect(@session).to have_css('#doesNotOpenWindows')
|
|
58
|
+
expect(@session.send(:scopes)).to eq([nil])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'should leave correct scopes after execution in case of error', requires: %i[windows frames] do
|
|
62
|
+
window = (@session.windows - [@window]).first
|
|
63
|
+
expect do
|
|
64
|
+
@session.within_frame 'frameOne' do
|
|
65
|
+
@session.within_window(window) {}
|
|
66
|
+
end
|
|
67
|
+
end.to raise_error(Capybara::ScopeError)
|
|
68
|
+
expect(@session.current_window).to eq(@window)
|
|
69
|
+
expect(@session).to have_css('#doesNotOpenWindows')
|
|
70
|
+
expect(@session.send(:scopes)).to eq([nil])
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'should raise error if closed window was passed' do
|
|
74
|
+
other_window = (@session.windows - [@window]).first
|
|
75
|
+
@session.within_window other_window do
|
|
76
|
+
other_window.close
|
|
77
|
+
end
|
|
78
|
+
expect do
|
|
79
|
+
@session.within_window(other_window) do
|
|
80
|
+
raise 'should not be invoked'
|
|
81
|
+
end
|
|
82
|
+
end.to raise_error(@session.driver.no_such_window_error)
|
|
83
|
+
expect(@session.current_window).to eq(@window)
|
|
84
|
+
expect(@session).to have_css('#doesNotOpenWindows')
|
|
85
|
+
expect(@session.send(:scopes)).to eq([nil])
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context 'with lambda' do
|
|
90
|
+
it 'should find the div in another window' do
|
|
91
|
+
@session.within_window(-> { @session.title == 'Title of the first popup' }) do
|
|
92
|
+
expect(@session).to have_css('#divInPopupOne')
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should find divs in both windows' do
|
|
97
|
+
@session.within_window(-> { @session.title == 'Title of popup two' }) do
|
|
98
|
+
expect(@session).to have_css('#divInPopupTwo')
|
|
99
|
+
end
|
|
100
|
+
@session.within_window(-> { @session.title == 'Title of the first popup' }) do
|
|
101
|
+
expect(@session).to have_css('#divInPopupOne')
|
|
102
|
+
end
|
|
103
|
+
expect(@session.title).to eq('With Windows')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'should be able to nest within_window' do
|
|
107
|
+
@session.within_window(-> { @session.title == 'Title of popup two' }) do
|
|
108
|
+
expect(@session).to have_css('#divInPopupTwo')
|
|
109
|
+
@session.within_window(-> { @session.title == 'Title of the first popup' }) do
|
|
110
|
+
expect(@session).to have_css('#divInPopupOne')
|
|
111
|
+
end
|
|
112
|
+
expect(@session).to have_css('#divInPopupTwo')
|
|
113
|
+
expect(@session).not_to have_css('divInPopupOne')
|
|
114
|
+
end
|
|
115
|
+
expect(@session).not_to have_css('#divInPopupTwo')
|
|
116
|
+
expect(@session).not_to have_css('divInPopupOne')
|
|
117
|
+
expect(@session.title).to eq('With Windows')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should work inside a normal scope' do
|
|
121
|
+
expect(@session).to have_css('#openWindow')
|
|
122
|
+
@session.within(:css, '#scope') do
|
|
123
|
+
@session.within_window(-> { @session.title == 'Title of the first popup' }) do
|
|
124
|
+
expect(@session).to have_css('#divInPopupOne')
|
|
125
|
+
end
|
|
126
|
+
expect(@session).to have_content('My scoped content')
|
|
127
|
+
expect(@session).not_to have_css('#openWindow')
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should raise error if window wasn't found" do
|
|
132
|
+
expect do
|
|
133
|
+
@session.within_window(-> { @session.title == 'Invalid title' }) do
|
|
134
|
+
expect(@session).to have_css('#divInPopupOne')
|
|
135
|
+
end
|
|
136
|
+
end.to raise_error(Capybara::WindowError, 'Could not find a window matching block/lambda')
|
|
137
|
+
expect(@session.current_window).to eq(@window)
|
|
138
|
+
expect(@session).to have_css('#doesNotOpenWindows')
|
|
139
|
+
expect(@session.send(:scopes)).to eq([nil])
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'returns value from the block' do
|
|
143
|
+
value = @session.within_window(-> { @session.title == 'Title of popup two' }) { 42 }
|
|
144
|
+
expect(value).to eq(42)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'should switch back if exception was raised inside block' do
|
|
148
|
+
expect do
|
|
149
|
+
@session.within_window(-> { @session.title == 'Title of popup two' }) do
|
|
150
|
+
raise 'some error'
|
|
151
|
+
end
|
|
152
|
+
end.to raise_error(StandardError, 'some error')
|
|
153
|
+
expect(@session.current_window).to eq(@window)
|
|
154
|
+
expect(@session.send(:scopes)).to eq([nil])
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Capybara::SpecHelper.spec '#within' do
|
|
4
|
+
before do
|
|
5
|
+
@session.visit('/with_scope')
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context 'with CSS selector' do
|
|
9
|
+
it 'should click links in the given scope' do
|
|
10
|
+
@session.within(:css, '#for_bar li:first-child') do
|
|
11
|
+
@session.click_link('Go')
|
|
12
|
+
end
|
|
13
|
+
expect(@session).to have_content('Bar')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should assert content in the given scope' do
|
|
17
|
+
@session.within(:css, '#for_foo') do
|
|
18
|
+
expect(@session).not_to have_content('First Name')
|
|
19
|
+
end
|
|
20
|
+
expect(@session).to have_content('First Name')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should accept additional options' do
|
|
24
|
+
@session.within(:css, '#for_bar li', text: 'With Simple HTML') do
|
|
25
|
+
@session.click_link('Go')
|
|
26
|
+
end
|
|
27
|
+
expect(@session).to have_content('Bar')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'should reload the node if the page is changed' do
|
|
31
|
+
@session.within(:css, '#for_foo') do
|
|
32
|
+
@session.visit('/with_scope_other')
|
|
33
|
+
expect(@session).to have_content('Different text')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should reload multiple nodes if the page is changed' do
|
|
38
|
+
@session.within(:css, '#for_bar') do
|
|
39
|
+
@session.within(:css, 'form[action="/redirect"]') do
|
|
40
|
+
@session.refresh
|
|
41
|
+
expect(@session).to have_content('First Name')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should error if the page is changed and a matching node no longer exists' do
|
|
47
|
+
@session.within(:css, '#for_foo') do
|
|
48
|
+
@session.visit('/')
|
|
49
|
+
expect { @session.text }.to raise_error(StandardError)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'with XPath selector' do
|
|
55
|
+
it 'should click links in the given scope' do
|
|
56
|
+
@session.within(:xpath, "//div[@id='for_bar']//li[contains(.,'With Simple HTML')]") do
|
|
57
|
+
@session.click_link('Go')
|
|
58
|
+
end
|
|
59
|
+
expect(@session).to have_content('Bar')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'with the default selector' do
|
|
64
|
+
it 'should use XPath' do
|
|
65
|
+
@session.within("//div[@id='for_bar']//li[contains(.,'With Simple HTML')]") do
|
|
66
|
+
@session.click_link('Go')
|
|
67
|
+
end
|
|
68
|
+
expect(@session).to have_content('Bar')
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'with Node rather than selector' do
|
|
73
|
+
it 'should click links in the given scope' do
|
|
74
|
+
node_of_interest = @session.find(:css, '#for_bar li', text: 'With Simple HTML')
|
|
75
|
+
|
|
76
|
+
@session.within(node_of_interest) do
|
|
77
|
+
@session.click_link('Go')
|
|
78
|
+
end
|
|
79
|
+
expect(@session).to have_content('Bar')
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'with the default selector set to CSS' do
|
|
84
|
+
before { Capybara.default_selector = :css }
|
|
85
|
+
|
|
86
|
+
after { Capybara.default_selector = :xpath }
|
|
87
|
+
|
|
88
|
+
it 'should use CSS' do
|
|
89
|
+
@session.within('#for_bar li', text: 'With Simple HTML') do
|
|
90
|
+
@session.click_link('Go')
|
|
91
|
+
end
|
|
92
|
+
expect(@session).to have_content('Bar')
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context 'with nested scopes' do
|
|
97
|
+
it 'should respect the inner scope' do
|
|
98
|
+
@session.within("//div[@id='for_bar']") do
|
|
99
|
+
@session.within(".//li[contains(.,'Bar')]") do
|
|
100
|
+
@session.click_link('Go')
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
expect(@session).to have_content('Another World')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'should respect the outer scope' do
|
|
107
|
+
@session.within("//div[@id='another_foo']") do
|
|
108
|
+
@session.within(".//li[contains(.,'With Simple HTML')]") do
|
|
109
|
+
@session.click_link('Go')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
expect(@session).to have_content('Hello world')
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'should raise an error if the scope is not found on the page' do
|
|
117
|
+
expect do
|
|
118
|
+
@session.within("//div[@id='doesnotexist']") do
|
|
119
|
+
end
|
|
120
|
+
end.to raise_error(Capybara::ElementNotFound)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'should restore the scope when an error is raised' do
|
|
124
|
+
expect do
|
|
125
|
+
@session.within("//div[@id='for_bar']") do
|
|
126
|
+
expect do
|
|
127
|
+
expect do
|
|
128
|
+
@session.within(".//div[@id='doesnotexist']") do
|
|
129
|
+
end
|
|
130
|
+
end.to raise_error(Capybara::ElementNotFound)
|
|
131
|
+
end.not_to change { @session.has_xpath?(".//div[@id='another_foo']") }.from(false)
|
|
132
|
+
end
|
|
133
|
+
end.not_to change { @session.has_xpath?(".//div[@id='another_foo']") }.from(true)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'should fill in a field and click a button' do
|
|
137
|
+
@session.within("//li[contains(.,'Bar')]") do
|
|
138
|
+
@session.click_button('Go')
|
|
139
|
+
end
|
|
140
|
+
expect(extract_results(@session)['first_name']).to eq('Peter')
|
|
141
|
+
@session.visit('/with_scope')
|
|
142
|
+
@session.within("//li[contains(.,'Bar')]") do
|
|
143
|
+
@session.fill_in('First Name', with: 'Dagobert')
|
|
144
|
+
@session.click_button('Go')
|
|
145
|
+
end
|
|
146
|
+
expect(extract_results(@session)['first_name']).to eq('Dagobert')
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'should have #within_element as an alias' do
|
|
150
|
+
expect(Capybara::Session.instance_method(:within)).to eq Capybara::Session.instance_method(:within_element)
|
|
151
|
+
@session.within_element(:css, '#for_foo') do
|
|
152
|
+
expect(@session).not_to have_content('First Name')
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
Capybara::SpecHelper.spec '#within_fieldset' do
|
|
158
|
+
before do
|
|
159
|
+
@session.visit('/fieldsets')
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'should restrict scope to a fieldset given by id' do
|
|
163
|
+
@session.within_fieldset('villain_fieldset') do
|
|
164
|
+
@session.fill_in('Name', with: 'Goldfinger')
|
|
165
|
+
@session.click_button('Create')
|
|
166
|
+
end
|
|
167
|
+
expect(extract_results(@session)['villain_name']).to eq('Goldfinger')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'should restrict scope to a fieldset given by legend' do
|
|
171
|
+
@session.within_fieldset('Villain') do
|
|
172
|
+
@session.fill_in('Name', with: 'Goldfinger')
|
|
173
|
+
@session.click_button('Create')
|
|
174
|
+
end
|
|
175
|
+
expect(extract_results(@session)['villain_name']).to eq('Goldfinger')
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
Capybara::SpecHelper.spec '#within_table' do
|
|
180
|
+
before do
|
|
181
|
+
@session.visit('/tables')
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'should restrict scope to a fieldset given by id' do
|
|
185
|
+
@session.within_table('girl_table') do
|
|
186
|
+
@session.fill_in('Name', with: 'Christmas')
|
|
187
|
+
@session.click_button('Create')
|
|
188
|
+
end
|
|
189
|
+
expect(extract_results(@session)['girl_name']).to eq('Christmas')
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'should restrict scope to a fieldset given by legend' do
|
|
193
|
+
@session.within_table('Villain') do
|
|
194
|
+
@session.fill_in('Name', with: 'Quantum')
|
|
195
|
+
@session.click_button('Create')
|
|
196
|
+
end
|
|
197
|
+
expect(extract_results(@session)['villain_name']).to eq('Quantum')
|
|
198
|
+
end
|
|
199
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec'
|
|
4
|
+
require 'rspec/expectations'
|
|
5
|
+
require 'capybara'
|
|
6
|
+
require 'capybara/rspec' # Required here instead of in rspec_spec to avoid RSpec deprecation warning
|
|
7
|
+
require 'capybara/spec/test_app'
|
|
8
|
+
require 'nokogiri'
|
|
9
|
+
|
|
10
|
+
Capybara.save_path = File.join(Dir.pwd, 'save_path_tmp')
|
|
11
|
+
|
|
12
|
+
module Capybara
|
|
13
|
+
module SpecHelper
|
|
14
|
+
class << self
|
|
15
|
+
def configure(config)
|
|
16
|
+
config.filter_run_excluding requires: method(:filter).to_proc
|
|
17
|
+
config.before { Capybara::SpecHelper.reset! }
|
|
18
|
+
config.after { Capybara::SpecHelper.reset! }
|
|
19
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reset!
|
|
23
|
+
Capybara.app = TestApp
|
|
24
|
+
Capybara.app_host = nil
|
|
25
|
+
Capybara.default_selector = :xpath
|
|
26
|
+
Capybara.default_max_wait_time = 1
|
|
27
|
+
Capybara.ignore_hidden_elements = true
|
|
28
|
+
Capybara.exact = false
|
|
29
|
+
Capybara.raise_server_errors = true
|
|
30
|
+
Capybara.visible_text_only = false
|
|
31
|
+
Capybara.match = :smart
|
|
32
|
+
Capybara.enable_aria_label = false
|
|
33
|
+
Capybara.default_set_options = {}
|
|
34
|
+
Capybara.disable_animation = false
|
|
35
|
+
Capybara.test_id = nil
|
|
36
|
+
Capybara.predicates_wait = true
|
|
37
|
+
Capybara.default_normalize_ws = false
|
|
38
|
+
Capybara.allow_gumbo = true
|
|
39
|
+
Capybara.w3c_click_offset = false
|
|
40
|
+
reset_threadsafe
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def filter(requires, metadata)
|
|
44
|
+
if requires && metadata[:capybara_skip]
|
|
45
|
+
requires.any? do |require|
|
|
46
|
+
metadata[:capybara_skip].include?(require)
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def spec(name, *options, &block)
|
|
54
|
+
@specs ||= []
|
|
55
|
+
@specs << [name, options, block]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def run_specs(session, name, **options, &filter_block)
|
|
59
|
+
specs = @specs
|
|
60
|
+
RSpec.describe Capybara::Session, name, options do # rubocop:disable RSpec/EmptyExampleGroup
|
|
61
|
+
include Capybara::SpecHelper
|
|
62
|
+
include Capybara::RSpecMatchers
|
|
63
|
+
|
|
64
|
+
before do |example|
|
|
65
|
+
@session = session
|
|
66
|
+
instance_exec(example, &filter_block) if filter_block
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
after do
|
|
70
|
+
session.reset_session!
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
before :each, psc: true do
|
|
74
|
+
SpecHelper.reset_threadsafe(true, session)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
after psc: true do
|
|
78
|
+
SpecHelper.reset_threadsafe(false, session)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
before :each, :exact_false do
|
|
82
|
+
Capybara.exact = false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
specs.each do |spec_name, spec_options, block|
|
|
86
|
+
describe spec_name, *spec_options do # rubocop:disable RSpec/EmptyExampleGroup
|
|
87
|
+
class_eval(&block)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def reset_threadsafe(bool = false, session = nil)
|
|
94
|
+
Capybara::Session.class_variable_set(:@@instance_created, false) # Work around limit on when threadsafe can be changed
|
|
95
|
+
Capybara.threadsafe = bool
|
|
96
|
+
session = session.current_session if session.respond_to?(:current_session)
|
|
97
|
+
session&.instance_variable_set(:@config, nil)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def silence_stream(stream)
|
|
102
|
+
old_stream = stream.dup
|
|
103
|
+
stream.reopen(RbConfig::CONFIG['host_os'].match?(/rmswin|mingw/) ? 'NUL:' : '/dev/null')
|
|
104
|
+
stream.sync = true
|
|
105
|
+
yield
|
|
106
|
+
ensure
|
|
107
|
+
stream.reopen(old_stream)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def quietly
|
|
111
|
+
silence_stream(STDOUT) do
|
|
112
|
+
silence_stream(STDERR) do
|
|
113
|
+
yield
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def extract_results(session)
|
|
119
|
+
expect(session).to have_xpath("//pre[@id='results']")
|
|
120
|
+
# YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
|
|
121
|
+
YAML.load Capybara::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def be_an_invalid_element_error(session)
|
|
125
|
+
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def with_os_path_separators(path)
|
|
129
|
+
Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
Dir[File.dirname(__FILE__) + '/session/**/*.rb'].each { |file| require_relative file }
|