capybara 3.0.0 → 3.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/History.md +777 -10
- data/License.txt +1 -1
- data/README.md +75 -58
- data/lib/capybara/config.rb +29 -10
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +22 -4
- data/lib/capybara/driver/node.rb +34 -9
- data/lib/capybara/dsl.rb +14 -6
- data/lib/capybara/helpers.rb +52 -7
- data/lib/capybara/minitest/spec.rb +173 -84
- data/lib/capybara/minitest.rb +250 -144
- data/lib/capybara/node/actions.rb +248 -124
- data/lib/capybara/node/base.rb +34 -20
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +13 -15
- data/lib/capybara/node/element.rb +339 -113
- data/lib/capybara/node/finders.rb +95 -82
- data/lib/capybara/node/matchers.rb +338 -157
- data/lib/capybara/node/simple.rb +54 -15
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +9 -10
- data/lib/capybara/queries/base_query.rb +25 -18
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +11 -0
- data/lib/capybara/queries/selector_query.rb +600 -103
- data/lib/capybara/queries/sibling_query.rb +9 -7
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +40 -22
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +47 -28
- data/lib/capybara/rack_test/driver.rb +12 -3
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +53 -50
- data/lib/capybara/rack_test/node.rb +114 -37
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +45 -0
- data/lib/capybara/result.rb +86 -52
- data/lib/capybara/rspec/features.rb +8 -10
- data/lib/capybara/rspec/matcher_proxies.rb +39 -18
- data/lib/capybara/rspec/matchers/base.rb +111 -0
- data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
- data/lib/capybara/rspec/matchers/compound.rb +88 -0
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
- data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +33 -0
- data/lib/capybara/rspec/matchers/have_title.rb +29 -0
- data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
- data/lib/capybara/rspec/matchers/match_style.rb +43 -0
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +138 -316
- data/lib/capybara/rspec.rb +3 -2
- data/lib/capybara/selector/builders/css_builder.rb +84 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
- data/lib/capybara/selector/css.rb +89 -12
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +54 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +279 -0
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +72 -27
- data/lib/capybara/selector/filters/base.rb +45 -2
- data/lib/capybara/selector/filters/expression_filter.rb +5 -6
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +18 -4
- data/lib/capybara/selector/regexp_disassembler.rb +214 -0
- data/lib/capybara/selector/selector.rb +85 -200
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +226 -537
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +296 -238
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +110 -0
- data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +76 -0
- data/lib/capybara/selenium/logger_suppressor.rb +40 -0
- data/lib/capybara/selenium/node.rb +436 -166
- data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +69 -0
- data/lib/capybara/server/checker.rb +44 -0
- data/lib/capybara/server/middleware.rb +71 -0
- data/lib/capybara/server.rb +58 -67
- data/lib/capybara/session/config.rb +38 -6
- data/lib/capybara/session/matchers.rb +26 -19
- data/lib/capybara/session.rb +258 -190
- data/lib/capybara/spec/public/jquery.js +5 -5
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +122 -8
- data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +135 -42
- data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
- data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
- data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
- data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
- data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +62 -38
- data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +120 -72
- data/lib/capybara/spec/session/body_spec.rb +11 -13
- data/lib/capybara/spec/session/check_spec.rb +111 -51
- data/lib/capybara/spec/session/choose_spec.rb +62 -30
- data/lib/capybara/spec/session/click_button_spec.rb +227 -161
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
- data/lib/capybara/spec/session/click_link_spec.rb +78 -55
- data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
- data/lib/capybara/spec/session/current_url_spec.rb +44 -37
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
- data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
- data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
- data/lib/capybara/spec/session/fill_in_spec.rb +104 -44
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
- data/lib/capybara/spec/session/find_field_spec.rb +33 -31
- data/lib/capybara/spec/session/find_link_spec.rb +32 -14
- data/lib/capybara/spec/session/find_spec.rb +236 -141
- data/lib/capybara/spec/session/first_spec.rb +44 -43
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +44 -19
- data/lib/capybara/spec/session/go_back_spec.rb +1 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +18 -18
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
- data/lib/capybara/spec/session/has_button_spec.rb +92 -12
- data/lib/capybara/spec/session/has_css_spec.rb +271 -137
- data/lib/capybara/spec/session/has_current_path_spec.rb +48 -33
- data/lib/capybara/spec/session/has_field_spec.rb +137 -58
- data/lib/capybara/spec/session/has_link_spec.rb +30 -6
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +26 -24
- data/lib/capybara/spec/session/has_select_spec.rb +75 -47
- data/lib/capybara/spec/session/has_selector_spec.rb +102 -69
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +170 -4
- data/lib/capybara/spec/session/has_text_spec.rb +108 -52
- data/lib/capybara/spec/session/has_title_spec.rb +19 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
- data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +1 -1
- data/lib/capybara/spec/session/html_spec.rb +13 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
- data/lib/capybara/spec/session/node_spec.rb +871 -122
- data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +52 -37
- data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +1 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +5 -4
- data/lib/capybara/spec/session/save_page_spec.rb +41 -38
- data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
- data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/scroll_spec.rb +117 -0
- data/lib/capybara/spec/session/select_spec.rb +102 -76
- data/lib/capybara/spec/session/selectors_spec.rb +51 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +26 -24
- data/lib/capybara/spec/session/title_spec.rb +8 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +40 -21
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +59 -53
- data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
- data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
- data/lib/capybara/spec/session/window/window_spec.rb +88 -54
- data/lib/capybara/spec/session/window/windows_spec.rb +10 -7
- data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
- data/lib/capybara/spec/session/within_spec.rb +69 -44
- data/lib/capybara/spec/spec_helper.rb +41 -53
- data/lib/capybara/spec/test_app.rb +79 -40
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +134 -42
- data/lib/capybara/spec/views/frame_child.erb +4 -3
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +47 -0
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +21 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +68 -1
- data/lib/capybara/spec/views/with_animation.erb +81 -0
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +43 -10
- data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +30 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +21 -0
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +31 -25
- data/lib/capybara.rb +120 -100
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +54 -52
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +80 -53
- data/spec/filter_set_spec.rb +24 -7
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
- data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
- data/spec/minitest_spec.rb +38 -5
- data/spec/minitest_spec_spec.rb +88 -62
- data/spec/per_session_config_spec.rb +5 -5
- data/spec/rack_test_spec.rb +169 -115
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +86 -33
- data/spec/rspec/features_spec.rb +26 -23
- data/spec/rspec/scenarios_spec.rb +8 -4
- data/spec/rspec/shared_spec_matchers.rb +393 -363
- data/spec/rspec/views_spec.rb +4 -3
- data/spec/rspec_matchers_spec.rb +10 -10
- data/spec/rspec_spec.rb +109 -85
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +391 -61
- data/spec/selenium_spec_chrome.rb +180 -41
- data/spec/selenium_spec_chrome_remote.rb +101 -0
- data/spec/selenium_spec_edge.rb +28 -8
- data/spec/selenium_spec_firefox.rb +211 -0
- data/spec/selenium_spec_firefox_remote.rb +80 -0
- data/spec/selenium_spec_ie.rb +127 -11
- data/spec/selenium_spec_safari.rb +156 -0
- data/spec/server_spec.rb +177 -78
- data/spec/session_spec.rb +52 -16
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +455 -123
- data/spec/spec_helper.rb +91 -2
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +343 -42
- data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
- data/.yard/templates_custom/default/class/html/setup.rb +0 -17
- data/.yard/yard_extensions.rb +0 -78
- data/lib/capybara/rspec/compound.rb +0 -90
- data/lib/capybara/spec/session/assert_selector.rb +0 -149
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
- data/spec/selenium_spec_marionette.rb +0 -143
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
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 'node' do
|
|
4
8
|
before do
|
|
5
9
|
@session.visit('/with_html')
|
|
6
10
|
end
|
|
7
11
|
|
|
8
|
-
it
|
|
12
|
+
it 'should act like a session object' do
|
|
9
13
|
@session.visit('/form')
|
|
10
14
|
@form = @session.find(:css, '#get-form')
|
|
11
15
|
expect(@form).to have_field('Middle Name')
|
|
@@ -15,59 +19,70 @@ Capybara::SpecHelper.spec "node" do
|
|
|
15
19
|
expect(extract_results(@session)['middle_name']).to eq('Monkey')
|
|
16
20
|
end
|
|
17
21
|
|
|
18
|
-
it
|
|
22
|
+
it 'should scope CSS selectors' do
|
|
19
23
|
expect(@session.find(:css, '#second')).to have_no_css('h1')
|
|
20
24
|
end
|
|
21
25
|
|
|
22
|
-
describe
|
|
23
|
-
it
|
|
24
|
-
|
|
25
|
-
expect(
|
|
26
|
-
expect(
|
|
26
|
+
describe '#query_scope' do
|
|
27
|
+
it 'should have a reference to the element the query was evaluated on if there is one' do
|
|
28
|
+
node = @session.find(:css, '#first')
|
|
29
|
+
expect(node.query_scope).to eq(node.session.document)
|
|
30
|
+
expect(node.find(:css, '#foo').query_scope).to eq(node)
|
|
27
31
|
end
|
|
28
32
|
end
|
|
29
33
|
|
|
30
|
-
describe
|
|
31
|
-
it
|
|
34
|
+
describe '#text' do
|
|
35
|
+
it 'should extract node texts' do
|
|
32
36
|
expect(@session.all('//a')[0].text).to eq('labore')
|
|
33
37
|
expect(@session.all('//a')[1].text).to eq('ullamco')
|
|
34
38
|
end
|
|
35
39
|
|
|
36
|
-
it
|
|
40
|
+
it 'should return document text on /html selector' do
|
|
37
41
|
@session.visit('/with_simple_html')
|
|
38
42
|
expect(@session.all('/html')[0].text).to eq('Bar')
|
|
39
43
|
end
|
|
40
44
|
end
|
|
41
45
|
|
|
42
|
-
describe
|
|
43
|
-
it
|
|
46
|
+
describe '#[]' do
|
|
47
|
+
it 'should extract node attributes' do
|
|
44
48
|
expect(@session.all('//a')[0][:class]).to eq('simple')
|
|
45
49
|
expect(@session.all('//a')[1][:id]).to eq('foo')
|
|
46
50
|
expect(@session.all('//input')[0][:type]).to eq('text')
|
|
47
51
|
end
|
|
48
52
|
|
|
49
|
-
it
|
|
53
|
+
it 'should extract boolean node attributes' do
|
|
50
54
|
expect(@session.find('//input[@id="checked_field"]')[:checked]).to be_truthy
|
|
51
55
|
end
|
|
52
56
|
end
|
|
53
57
|
|
|
54
|
-
describe
|
|
55
|
-
it
|
|
58
|
+
describe '#style', requires: [:css] do
|
|
59
|
+
it 'should return the computed style value' do
|
|
60
|
+
expect(@session.find(:css, '#first').style('display')).to eq('display' => 'block')
|
|
61
|
+
expect(@session.find(:css, '#second').style(:display)).to eq('display' => 'inline')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should return multiple style values' do
|
|
65
|
+
expect(@session.find(:css, '#first').style('display', :'line-height')).to eq('display' => 'block', 'line-height' => '25px')
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe '#value' do
|
|
70
|
+
it 'should allow retrieval of the value' do
|
|
56
71
|
expect(@session.find('//textarea[@id="normal"]').value).to eq('banana')
|
|
57
72
|
end
|
|
58
73
|
|
|
59
|
-
it
|
|
74
|
+
it 'should not swallow extra newlines in textarea' do
|
|
60
75
|
expect(@session.find('//textarea[@id="additional_newline"]').value).to eq("\nbanana")
|
|
61
76
|
end
|
|
62
77
|
|
|
63
|
-
it
|
|
78
|
+
it 'should not swallow leading newlines for set content in textarea' do
|
|
64
79
|
@session.find('//textarea[@id="normal"]').set("\nbanana")
|
|
65
80
|
expect(@session.find('//textarea[@id="normal"]').value).to eq("\nbanana")
|
|
66
81
|
end
|
|
67
82
|
|
|
68
|
-
it
|
|
69
|
-
@session.find('//textarea[1]').set(
|
|
70
|
-
expect(@session.find('//textarea[1]').value).to eq(
|
|
83
|
+
it 'return any HTML content in textarea' do
|
|
84
|
+
@session.find('//textarea[1]').set('some <em>html</em> here')
|
|
85
|
+
expect(@session.find('//textarea[1]').value).to eq('some <em>html</em> here')
|
|
71
86
|
end
|
|
72
87
|
|
|
73
88
|
it "defaults to 'on' for checkbox" do
|
|
@@ -81,28 +96,48 @@ Capybara::SpecHelper.spec "node" do
|
|
|
81
96
|
end
|
|
82
97
|
end
|
|
83
98
|
|
|
84
|
-
describe
|
|
85
|
-
it
|
|
99
|
+
describe '#set' do
|
|
100
|
+
it 'should allow assignment of field value' do
|
|
86
101
|
expect(@session.first('//input').value).to eq('monkey')
|
|
87
102
|
@session.first('//input').set('gorilla')
|
|
88
103
|
expect(@session.first('//input').value).to eq('gorilla')
|
|
89
104
|
end
|
|
90
105
|
|
|
91
|
-
it
|
|
106
|
+
it 'should fill the field even if the caret was not at the end', requires: [:js] do
|
|
92
107
|
@session.execute_script("var el = document.getElementById('test_field'); el.focus(); el.setSelectionRange(0, 0);")
|
|
93
108
|
@session.first('//input').set('')
|
|
94
109
|
expect(@session.first('//input').value).to eq('')
|
|
95
110
|
end
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
if ENV['CAPYBARA_THOROUGH']
|
|
113
|
+
it 'should raise if the text field is readonly' do
|
|
114
|
+
expect { @session.first('//input[@readonly]').set('changed') }.to raise_error(Capybara::ReadOnlyElementError)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'should raise if the textarea is readonly' do
|
|
118
|
+
expect { @session.first('//textarea[@readonly]').set('changed') }.to raise_error(Capybara::ReadOnlyElementError)
|
|
119
|
+
end
|
|
120
|
+
else
|
|
121
|
+
it 'should not change if the text field is readonly' do
|
|
122
|
+
@session.first('//input[@readonly]').set('changed')
|
|
123
|
+
expect(@session.first('//input[@readonly]').value).to eq 'should not change'
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should not change if the textarea is readonly' do
|
|
127
|
+
@session.first('//textarea[@readonly]').set('changed')
|
|
128
|
+
expect(@session.first('//textarea[@readonly]').value).to eq 'textarea should not change'
|
|
129
|
+
end
|
|
99
130
|
end
|
|
100
131
|
|
|
101
|
-
it
|
|
102
|
-
|
|
132
|
+
it 'should use global default options' do
|
|
133
|
+
Capybara.default_set_options = { clear: :backspace }
|
|
134
|
+
element = @session.first(:fillable_field, type: 'text')
|
|
135
|
+
allow(element.base).to receive(:set)
|
|
136
|
+
element.set('gorilla')
|
|
137
|
+
expect(element.base).to have_received(:set).with('gorilla', clear: :backspace)
|
|
103
138
|
end
|
|
104
139
|
|
|
105
|
-
context
|
|
140
|
+
context 'with a contenteditable element', requires: [:js] do
|
|
106
141
|
it 'should allow me to change the contents' do
|
|
107
142
|
@session.visit('/with_js')
|
|
108
143
|
@session.find(:css, '#existing_content_editable').set('WYSIWYG')
|
|
@@ -124,70 +159,83 @@ Capybara::SpecHelper.spec "node" do
|
|
|
124
159
|
end
|
|
125
160
|
end
|
|
126
161
|
|
|
127
|
-
describe
|
|
128
|
-
it
|
|
162
|
+
describe '#tag_name' do
|
|
163
|
+
it 'should extract node tag name' do
|
|
129
164
|
expect(@session.all('//a')[0].tag_name).to eq('a')
|
|
130
165
|
expect(@session.all('//a')[1].tag_name).to eq('a')
|
|
131
166
|
expect(@session.all('//p')[1].tag_name).to eq('p')
|
|
132
167
|
end
|
|
133
168
|
end
|
|
134
169
|
|
|
135
|
-
describe
|
|
136
|
-
it
|
|
170
|
+
describe '#disabled?' do
|
|
171
|
+
it 'should extract disabled node' do
|
|
137
172
|
@session.visit('/form')
|
|
138
173
|
expect(@session.find('//input[@id="customer_name"]')).to be_disabled
|
|
139
174
|
expect(@session.find('//input[@id="customer_email"]')).not_to be_disabled
|
|
140
175
|
end
|
|
141
176
|
|
|
142
|
-
it
|
|
177
|
+
it 'should see disabled options as disabled' do
|
|
143
178
|
@session.visit('/form')
|
|
144
179
|
expect(@session.find('//select[@id="form_title"]/option[1]')).not_to be_disabled
|
|
145
180
|
expect(@session.find('//select[@id="form_title"]/option[@disabled]')).to be_disabled
|
|
146
181
|
end
|
|
147
182
|
|
|
148
|
-
it
|
|
183
|
+
it 'should see enabled options in disabled select as disabled' do
|
|
149
184
|
@session.visit('/form')
|
|
150
185
|
expect(@session.find('//select[@id="form_disabled_select"]/option')).to be_disabled
|
|
151
186
|
expect(@session.find('//select[@id="form_disabled_select"]/optgroup/option')).to be_disabled
|
|
152
187
|
expect(@session.find('//select[@id="form_title"]/option[1]')).not_to be_disabled
|
|
153
188
|
end
|
|
154
189
|
|
|
155
|
-
it
|
|
190
|
+
it 'should see enabled options in disabled optgroup as disabled' do
|
|
191
|
+
@session.visit('/form')
|
|
192
|
+
expect(@session.find('//option', text: 'A.B.1')).to be_disabled
|
|
193
|
+
expect(@session.find('//option', text: 'A.2')).not_to be_disabled
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'should see a disabled fieldset as disabled' do
|
|
156
197
|
@session.visit('/form')
|
|
157
|
-
expect(@session.find(
|
|
158
|
-
expect(@session.find('//option', text: "A.2")).not_to be_disabled
|
|
198
|
+
expect(@session.find(:xpath, './/fieldset[@id="form_disabled_fieldset"]')).to be_disabled
|
|
159
199
|
end
|
|
160
200
|
|
|
161
|
-
context
|
|
201
|
+
context 'in a disabled fieldset' do
|
|
162
202
|
# https://html.spec.whatwg.org/#the-fieldset-element
|
|
163
|
-
it
|
|
203
|
+
it 'should see elements not in first legend as disabled' do
|
|
164
204
|
@session.visit('/form')
|
|
165
205
|
expect(@session.find('//input[@id="form_disabled_fieldset_child"]')).to be_disabled
|
|
166
206
|
expect(@session.find('//input[@id="form_disabled_fieldset_second_legend_child"]')).to be_disabled
|
|
167
207
|
expect(@session.find('//input[@id="form_enabled_fieldset_child"]')).not_to be_disabled
|
|
168
208
|
end
|
|
169
209
|
|
|
170
|
-
it
|
|
210
|
+
it 'should see elements in first legend as enabled' do
|
|
171
211
|
@session.visit('/form')
|
|
172
212
|
expect(@session.find('//input[@id="form_disabled_fieldset_legend_child"]')).not_to be_disabled
|
|
173
213
|
end
|
|
174
214
|
|
|
175
|
-
it
|
|
215
|
+
it 'should sees options not in first legend as disabled' do
|
|
176
216
|
@session.visit('/form')
|
|
177
217
|
expect(@session.find('//option', text: 'Disabled Child Option')).to be_disabled
|
|
178
218
|
end
|
|
179
219
|
end
|
|
180
|
-
|
|
220
|
+
|
|
221
|
+
it 'should be boolean' do
|
|
181
222
|
@session.visit('/form')
|
|
182
223
|
expect(@session.find('//select[@id="form_disabled_select"]/option').disabled?).to be true
|
|
183
224
|
expect(@session.find('//select[@id="form_disabled_select2"]/option').disabled?).to be true
|
|
184
225
|
expect(@session.find('//select[@id="form_title"]/option[1]').disabled?).to be false
|
|
185
226
|
end
|
|
227
|
+
|
|
228
|
+
it 'should be disabled for all elements that are CSS :disabled' do
|
|
229
|
+
@session.visit('/form')
|
|
230
|
+
# sanity check
|
|
231
|
+
expect(@session.all(:css, ':disabled')).to all(be_disabled)
|
|
232
|
+
end
|
|
186
233
|
end
|
|
187
234
|
|
|
188
|
-
describe
|
|
189
|
-
|
|
190
|
-
|
|
235
|
+
describe '#visible?' do
|
|
236
|
+
before { Capybara.ignore_hidden_elements = false }
|
|
237
|
+
|
|
238
|
+
it 'should extract node visibility' do
|
|
191
239
|
expect(@session.first('//a')).to be_visible
|
|
192
240
|
|
|
193
241
|
expect(@session.find('//div[@id="hidden"]')).not_to be_visible
|
|
@@ -197,22 +245,124 @@ Capybara::SpecHelper.spec "node" do
|
|
|
197
245
|
expect(@session.find('//input[@id="hidden_input"]')).not_to be_visible
|
|
198
246
|
end
|
|
199
247
|
|
|
200
|
-
it
|
|
201
|
-
|
|
248
|
+
it 'template elements should not be visible' do
|
|
249
|
+
expect(@session.find('//template')).not_to be_visible
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it 'should be boolean' do
|
|
202
253
|
expect(@session.first('//a').visible?).to be true
|
|
203
254
|
expect(@session.find('//div[@id="hidden"]').visible?).to be false
|
|
204
255
|
end
|
|
256
|
+
|
|
257
|
+
it 'closed details > summary elements and descendants should be visible' do
|
|
258
|
+
expect(@session.find(:css, '#closed_details summary')).to be_visible
|
|
259
|
+
expect(@session.find(:css, '#closed_details summary h6')).to be_visible
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'details non-summary descendants should be non-visible when closed' do
|
|
263
|
+
descendants = @session.all(:css, '#closed_details > *:not(summary), #closed_details > *:not(summary) *', minimum: 2)
|
|
264
|
+
expect(descendants).not_to include(be_visible)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it 'deatils descendants should be visible when open' do
|
|
268
|
+
descendants = @session.all(:css, '#open_details *')
|
|
269
|
+
expect(descendants).to all(be_visible)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
it 'works when details is toggled open and closed' do
|
|
273
|
+
@session.find(:css, '#closed_details > summary').click
|
|
274
|
+
expect(@session).to have_css('#closed_details *', visible: :visible, count: 5)
|
|
275
|
+
.and(have_no_css('#closed_details *', visible: :hidden))
|
|
276
|
+
|
|
277
|
+
@session.find(:css, '#closed_details > summary').click
|
|
278
|
+
descendants_css = '#closed_details > *:not(summary), #closed_details > *:not(summary) *'
|
|
279
|
+
expect(@session).to have_no_css(descendants_css, visible: :visible)
|
|
280
|
+
.and(have_css(descendants_css, visible: :hidden, count: 3))
|
|
281
|
+
end
|
|
205
282
|
end
|
|
206
283
|
|
|
207
|
-
describe
|
|
208
|
-
it
|
|
284
|
+
describe '#obscured?', requires: [:css] do
|
|
285
|
+
it 'should see non visible elements as obscured' do
|
|
286
|
+
Capybara.ignore_hidden_elements = false
|
|
287
|
+
expect(@session.find('//div[@id="hidden"]')).to be_obscured
|
|
288
|
+
expect(@session.find('//div[@id="hidden_via_ancestor"]')).to be_obscured
|
|
289
|
+
expect(@session.find('//div[@id="hidden_attr"]')).to be_obscured
|
|
290
|
+
expect(@session.find('//a[@id="hidden_attr_via_ancestor"]')).to be_obscured
|
|
291
|
+
expect(@session.find('//input[@id="hidden_input"]')).to be_obscured
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it 'should see non-overlapped elements as not obscured' do
|
|
295
|
+
@session.visit('/obscured')
|
|
296
|
+
expect(@session.find(:css, '#cover')).not_to be_obscured
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
it 'should see elements only overlapped by descendants as not obscured' do
|
|
300
|
+
expect(@session.first(:css, 'p:not(.para)')).not_to be_obscured
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it 'should see elements outside the viewport as obscured' do
|
|
304
|
+
@session.visit('/obscured')
|
|
305
|
+
off = @session.find(:css, '#offscreen')
|
|
306
|
+
off_wrapper = @session.find(:css, '#offscreen_wrapper')
|
|
307
|
+
expect(off).to be_obscured
|
|
308
|
+
expect(off_wrapper).to be_obscured
|
|
309
|
+
@session.scroll_to(off_wrapper)
|
|
310
|
+
expect(off_wrapper).not_to be_obscured
|
|
311
|
+
expect(off).to be_obscured
|
|
312
|
+
off_wrapper.scroll_to(off)
|
|
313
|
+
expect(off).not_to be_obscured
|
|
314
|
+
expect(off_wrapper).not_to be_obscured
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it 'should see overlapped elements as obscured' do
|
|
318
|
+
@session.visit('/obscured')
|
|
319
|
+
expect(@session.find(:css, '#obscured')).to be_obscured
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it 'should be boolean' do
|
|
323
|
+
Capybara.ignore_hidden_elements = false
|
|
324
|
+
expect(@session.first('//a').obscured?).to be false
|
|
325
|
+
expect(@session.find('//div[@id="hidden"]').obscured?).to be true
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'should work in frames' do
|
|
329
|
+
@session.visit('/obscured')
|
|
330
|
+
frame = @session.find(:css, '#frameOne')
|
|
331
|
+
@session.within_frame(frame) do
|
|
332
|
+
div = @session.find(:css, '#divInFrameOne')
|
|
333
|
+
expect(div).to be_obscured
|
|
334
|
+
@session.scroll_to div
|
|
335
|
+
expect(div).not_to be_obscured
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it 'should work in nested iframes' do
|
|
340
|
+
@session.visit('/obscured')
|
|
341
|
+
frame = @session.find(:css, '#nestedFrames')
|
|
342
|
+
@session.within_frame(frame) do
|
|
343
|
+
@session.within_frame(:css, '#childFrame') do
|
|
344
|
+
gcframe = @session.find(:css, '#grandchildFrame2')
|
|
345
|
+
@session.within_frame(gcframe) do
|
|
346
|
+
expect(@session.find(:css, '#divInFrameTwo')).to be_obscured
|
|
347
|
+
end
|
|
348
|
+
@session.scroll_to(gcframe)
|
|
349
|
+
@session.within_frame(gcframe) do
|
|
350
|
+
expect(@session.find(:css, '#divInFrameTwo')).not_to be_obscured
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
describe '#checked?' do
|
|
358
|
+
it 'should extract node checked state' do
|
|
209
359
|
@session.visit('/form')
|
|
210
360
|
expect(@session.find('//input[@id="gender_female"]')).to be_checked
|
|
211
361
|
expect(@session.find('//input[@id="gender_male"]')).not_to be_checked
|
|
212
362
|
expect(@session.first('//h1')).not_to be_checked
|
|
213
363
|
end
|
|
214
364
|
|
|
215
|
-
it
|
|
365
|
+
it 'should be boolean' do
|
|
216
366
|
@session.visit('/form')
|
|
217
367
|
expect(@session.find('//input[@id="gender_female"]').checked?).to be true
|
|
218
368
|
expect(@session.find('//input[@id="gender_male"]').checked?).to be false
|
|
@@ -220,15 +370,15 @@ Capybara::SpecHelper.spec "node" do
|
|
|
220
370
|
end
|
|
221
371
|
end
|
|
222
372
|
|
|
223
|
-
describe
|
|
224
|
-
it
|
|
373
|
+
describe '#selected?' do
|
|
374
|
+
it 'should extract node selected state' do
|
|
225
375
|
@session.visit('/form')
|
|
226
376
|
expect(@session.find('//option[@value="en"]')).to be_selected
|
|
227
377
|
expect(@session.find('//option[@value="sv"]')).not_to be_selected
|
|
228
378
|
expect(@session.first('//h1')).not_to be_selected
|
|
229
379
|
end
|
|
230
380
|
|
|
231
|
-
it
|
|
381
|
+
it 'should be boolean' do
|
|
232
382
|
@session.visit('/form')
|
|
233
383
|
expect(@session.find('//option[@value="en"]').selected?).to be true
|
|
234
384
|
expect(@session.find('//option[@value="sv"]').selected?).to be false
|
|
@@ -236,33 +386,44 @@ Capybara::SpecHelper.spec "node" do
|
|
|
236
386
|
end
|
|
237
387
|
end
|
|
238
388
|
|
|
239
|
-
describe
|
|
240
|
-
it
|
|
241
|
-
expect(@session.find('//h1') == @session.find('//h1')).to be true # rubocop:disable Lint/
|
|
242
|
-
expect(@session.find('//h1') === @session.find('//h1')).to be true # rubocop:disable Style/CaseEquality, Lint/
|
|
389
|
+
describe '#==' do
|
|
390
|
+
it 'preserve object identity' do
|
|
391
|
+
expect(@session.find('//h1') == @session.find('//h1')).to be true # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
|
|
392
|
+
expect(@session.find('//h1') === @session.find('//h1')).to be true # rubocop:disable Style/CaseEquality, Lint/BinaryOperatorWithIdenticalOperands
|
|
243
393
|
expect(@session.find('//h1').eql?(@session.find('//h1'))).to be false
|
|
244
394
|
end
|
|
245
395
|
|
|
246
|
-
it
|
|
247
|
-
expect(@session.find('//h1') ==
|
|
396
|
+
it 'returns false for unrelated object' do
|
|
397
|
+
expect(@session.find('//h1') == 'Not Capybara::Node::Base').to be false
|
|
248
398
|
end
|
|
249
399
|
end
|
|
250
400
|
|
|
251
|
-
describe
|
|
401
|
+
describe '#path' do
|
|
252
402
|
# Testing for specific XPaths here doesn't make sense since there
|
|
253
403
|
# are many that can refer to the same element
|
|
254
|
-
before
|
|
404
|
+
before do
|
|
255
405
|
@session.visit('/path')
|
|
256
406
|
end
|
|
257
407
|
|
|
258
|
-
it
|
|
408
|
+
it 'returns xpath which points to itself' do
|
|
259
409
|
element = @session.find(:link, 'Second Link')
|
|
260
410
|
expect(@session.find(:xpath, element.path)).to eq(element)
|
|
261
411
|
end
|
|
412
|
+
|
|
413
|
+
it 'reports when element in shadow dom', requires: [:shadow_dom] do
|
|
414
|
+
@session.visit('/with_js')
|
|
415
|
+
shadow = @session.find(:css, '#shadow')
|
|
416
|
+
element = @session.evaluate_script(<<~JS, shadow)
|
|
417
|
+
(function(root){
|
|
418
|
+
return root.shadowRoot.querySelector('span');
|
|
419
|
+
})(arguments[0])
|
|
420
|
+
JS
|
|
421
|
+
expect(element.path).to eq '(: Shadow DOM element - no XPath :)'
|
|
422
|
+
end
|
|
262
423
|
end
|
|
263
424
|
|
|
264
|
-
describe
|
|
265
|
-
it
|
|
425
|
+
describe '#trigger', requires: %i[js trigger] do
|
|
426
|
+
it 'should allow triggering of custom JS events' do
|
|
266
427
|
@session.visit('/with_js')
|
|
267
428
|
@session.find(:css, '#with_focus_event').trigger(:focus)
|
|
268
429
|
expect(@session).to have_css('#focus_event_triggered')
|
|
@@ -270,52 +431,313 @@ Capybara::SpecHelper.spec "node" do
|
|
|
270
431
|
end
|
|
271
432
|
|
|
272
433
|
describe '#drag_to', requires: %i[js drag] do
|
|
273
|
-
it
|
|
434
|
+
it 'should drag and drop an object' do
|
|
274
435
|
@session.visit('/with_js')
|
|
275
436
|
element = @session.find('//div[@id="drag"]')
|
|
276
437
|
target = @session.find('//div[@id="drop"]')
|
|
277
438
|
element.drag_to(target)
|
|
278
|
-
expect(@session.
|
|
439
|
+
expect(@session).to have_xpath('//div[contains(., "Dropped!")]')
|
|
279
440
|
end
|
|
280
441
|
|
|
281
|
-
it
|
|
442
|
+
it 'should drag and drop if scrolling is needed' do
|
|
282
443
|
@session.visit('/with_js')
|
|
283
444
|
element = @session.find('//div[@id="drag_scroll"]')
|
|
284
445
|
target = @session.find('//div[@id="drop_scroll"]')
|
|
285
446
|
element.drag_to(target)
|
|
286
|
-
expect(@session.
|
|
447
|
+
expect(@session).to have_xpath('//div[contains(., "Dropped!")]')
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it 'should drag a link' do
|
|
451
|
+
@session.visit('/with_js')
|
|
452
|
+
link = @session.find_link('drag_link')
|
|
453
|
+
target = @session.find(:id, 'drop')
|
|
454
|
+
link.drag_to target
|
|
455
|
+
expect(@session).to have_xpath('//div[contains(., "Dropped!")]')
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
it 'should work with Dragula' do
|
|
459
|
+
@session.visit('/with_dragula')
|
|
460
|
+
@session.within(:css, '#sortable.ready') do
|
|
461
|
+
src = @session.find('div', text: 'Item 1')
|
|
462
|
+
target = @session.find('div', text: 'Item 3')
|
|
463
|
+
src.drag_to target
|
|
464
|
+
expect(@session).to have_content(/Item 2.*Item 1/, normalize_ws: true)
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
it 'should work with jsTree' do
|
|
469
|
+
@session.visit('/with_jstree')
|
|
470
|
+
@session.within(:css, '#container') do
|
|
471
|
+
@session.assert_text(/A.*B.*C/m)
|
|
472
|
+
source = @session.find(:css, '#j1_1_anchor')
|
|
473
|
+
target = @session.find(:css, '#j1_2_anchor')
|
|
474
|
+
|
|
475
|
+
source.drag_to(target)
|
|
476
|
+
|
|
477
|
+
@session.assert_no_text(/A.*B.*C/m)
|
|
478
|
+
@session.assert_text(/B.*C/m)
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
it 'should simulate a single held down modifier key' do
|
|
483
|
+
%I[
|
|
484
|
+
alt
|
|
485
|
+
ctrl
|
|
486
|
+
meta
|
|
487
|
+
shift
|
|
488
|
+
].each do |modifier_key|
|
|
489
|
+
@session.visit('/with_js')
|
|
490
|
+
|
|
491
|
+
element = @session.find('//div[@id="drag"]')
|
|
492
|
+
target = @session.find('//div[@id="drop"]')
|
|
493
|
+
|
|
494
|
+
element.drag_to(target, drop_modifiers: modifier_key)
|
|
495
|
+
expect(@session).to have_css('div.drag_start', exact_text: 'Dragged!')
|
|
496
|
+
expect(@session).to have_xpath("//div[contains(., 'Dropped!-#{modifier_key}')]")
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
it 'should simulate multiple held down modifier keys' do
|
|
501
|
+
@session.visit('/with_js')
|
|
502
|
+
|
|
503
|
+
element = @session.find('//div[@id="drag"]')
|
|
504
|
+
target = @session.find('//div[@id="drop"]')
|
|
505
|
+
|
|
506
|
+
modifier_keys = %I[alt ctrl meta shift]
|
|
507
|
+
|
|
508
|
+
element.drag_to(target, drop_modifiers: modifier_keys)
|
|
509
|
+
expect(@session).to have_xpath("//div[contains(., 'Dropped!-#{modifier_keys.join('-')}')]")
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it 'should support key aliases' do
|
|
513
|
+
{ control: :ctrl,
|
|
514
|
+
command: :meta,
|
|
515
|
+
cmd: :meta }.each do |(key_alias, key)|
|
|
516
|
+
@session.visit('/with_js')
|
|
517
|
+
|
|
518
|
+
element = @session.find('//div[@id="drag"]')
|
|
519
|
+
target = @session.find('//div[@id="drop"]')
|
|
520
|
+
|
|
521
|
+
element.drag_to(target, drop_modifiers: [key_alias])
|
|
522
|
+
expect(target).to have_text("Dropped!-#{key}", exact: true)
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
context 'HTML5', requires: %i[js html5_drag] do
|
|
527
|
+
it 'should HTML5 drag and drop an object' do
|
|
528
|
+
@session.visit('/with_js')
|
|
529
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
530
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
531
|
+
element.drag_to(target)
|
|
532
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain drag_html5")]')
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
it 'should HTML5 drag and drop an object child' do
|
|
536
|
+
@session.visit('/with_js')
|
|
537
|
+
element = @session.find('//div[@id="drag_html5"]/p')
|
|
538
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
539
|
+
element.drag_to(target)
|
|
540
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain drag_html5")]')
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
it 'should set clientX/Y in dragover events' do
|
|
544
|
+
@session.visit('/with_js')
|
|
545
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
546
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
547
|
+
element.drag_to(target)
|
|
548
|
+
expect(@session).to have_css('div.log', text: /DragOver with client position: [1-9]\d*,[1-9]\d*/, count: 2)
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
it 'should preserve clientX/Y from last dragover event' do
|
|
552
|
+
@session.visit('/with_js')
|
|
553
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
554
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
555
|
+
element.drag_to(target)
|
|
556
|
+
|
|
557
|
+
conditions = %w[DragLeave Drop DragEnd].map do |text|
|
|
558
|
+
have_css('div.log', text: text)
|
|
559
|
+
end
|
|
560
|
+
expect(@session).to(conditions.reduce { |memo, cond| memo.and(cond) })
|
|
561
|
+
|
|
562
|
+
# The first "DragOver" div is inserted by the last dragover event dispatched
|
|
563
|
+
drag_over_div = @session.first('//div[@class="log" and starts-with(text(), "DragOver")]')
|
|
564
|
+
position = drag_over_div.text.sub('DragOver ', '')
|
|
565
|
+
|
|
566
|
+
expect(@session).to have_css('div.log', text: /DragLeave #{position}/, count: 1)
|
|
567
|
+
expect(@session).to have_css('div.log', text: /Drop #{position}/, count: 1)
|
|
568
|
+
expect(@session).to have_css('div.log', text: /DragEnd #{position}/, count: 1)
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
it 'should not HTML5 drag and drop on a non HTML5 drop element' do
|
|
572
|
+
@session.visit('/with_js')
|
|
573
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
574
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
575
|
+
target.execute_script("$(this).removeClass('drop');")
|
|
576
|
+
element.drag_to(target)
|
|
577
|
+
sleep 1
|
|
578
|
+
expect(@session).not_to have_xpath('//div[contains(., "HTML5 Dropped")]')
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
it 'should HTML5 drag and drop when scrolling needed' do
|
|
582
|
+
@session.visit('/with_js')
|
|
583
|
+
element = @session.find('//div[@id="drag_html5_scroll"]')
|
|
584
|
+
target = @session.find('//div[@id="drop_html5_scroll"]')
|
|
585
|
+
element.drag_to(target)
|
|
586
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain drag_html5_scroll")]')
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
it 'should drag HTML5 default draggable elements' do
|
|
590
|
+
@session.visit('/with_js')
|
|
591
|
+
link = @session.find_link('drag_link_html5')
|
|
592
|
+
target = @session.find(:id, 'drop_html5')
|
|
593
|
+
link.drag_to target
|
|
594
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped")]')
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
it 'should work with SortableJS' do
|
|
598
|
+
@session.visit('/with_sortable_js')
|
|
599
|
+
@session.within(:css, '#sortable') do
|
|
600
|
+
src = @session.find('div', text: 'Item 1')
|
|
601
|
+
target = @session.find('div', text: 'Item 3')
|
|
602
|
+
src.drag_to target
|
|
603
|
+
expect(@session).to have_content(/Item 3.*Item 1/, normalize_ws: true)
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
it 'should drag HTML5 default draggable element child' do
|
|
608
|
+
@session.visit('/with_js')
|
|
609
|
+
source = @session.find_link('drag_link_html5').find(:css, 'p')
|
|
610
|
+
target = @session.find(:id, 'drop_html5')
|
|
611
|
+
source.drag_to target
|
|
612
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped")]')
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
it 'should simulate a single held down modifier key' do
|
|
616
|
+
%I[alt ctrl meta shift].each do |modifier_key|
|
|
617
|
+
@session.visit('/with_js')
|
|
618
|
+
|
|
619
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
620
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
621
|
+
|
|
622
|
+
element.drag_to(target, drop_modifiers: modifier_key)
|
|
623
|
+
|
|
624
|
+
expect(@session).to have_css('div.drag_start', exact_text: 'HTML5 Dragged!')
|
|
625
|
+
expect(@session).to have_xpath("//div[contains(., 'HTML5 Dropped string: text/plain drag_html5-#{modifier_key}')]")
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
it 'should simulate multiple held down modifier keys' do
|
|
630
|
+
@session.visit('/with_js')
|
|
631
|
+
|
|
632
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
633
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
634
|
+
|
|
635
|
+
modifier_keys = %I[alt ctrl meta shift]
|
|
636
|
+
|
|
637
|
+
element.drag_to(target, drop_modifiers: modifier_keys)
|
|
638
|
+
expect(@session).to have_xpath("//div[contains(., 'HTML5 Dropped string: text/plain drag_html5-#{modifier_keys.join('-')}')]")
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
it 'should support key aliases' do
|
|
642
|
+
{ control: :ctrl,
|
|
643
|
+
command: :meta,
|
|
644
|
+
cmd: :meta }.each do |(key_alias, key)|
|
|
645
|
+
@session.visit('/with_js')
|
|
646
|
+
|
|
647
|
+
element = @session.find('//div[@id="drag_html5"]')
|
|
648
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
649
|
+
|
|
650
|
+
element.drag_to(target, drop_modifiers: [key_alias])
|
|
651
|
+
expect(target).to have_text(%r{^HTML5 Dropped string: text/plain drag_html5-#{key}$}m, exact: true)
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
describe 'Element#drop', requires: %i[js html5_drag] do
|
|
658
|
+
it 'can drop a file' do
|
|
659
|
+
@session.visit('/with_js')
|
|
660
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
661
|
+
target.drop(
|
|
662
|
+
with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__)))
|
|
663
|
+
)
|
|
664
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped file: capybara.jpg")]')
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
it 'can drop multiple files' do
|
|
668
|
+
@session.visit('/with_js')
|
|
669
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
670
|
+
target.drop(
|
|
671
|
+
with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__))),
|
|
672
|
+
with_os_path_separators(File.expand_path('../fixtures/test_file.txt', File.dirname(__FILE__)))
|
|
673
|
+
)
|
|
674
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped file: capybara.jpg")]')
|
|
675
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped file: test_file.txt")]')
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
it 'can drop strings' do
|
|
679
|
+
@session.visit('/with_js')
|
|
680
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
681
|
+
target.drop('text/plain' => 'Some dropped text')
|
|
682
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain Some dropped text")]')
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
it 'can drop a pathname' do
|
|
686
|
+
@session.visit('/with_js')
|
|
687
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
688
|
+
target.drop(
|
|
689
|
+
Pathname.new(with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__))))
|
|
690
|
+
)
|
|
691
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped file: capybara.jpg")]')
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
it 'can drop multiple strings' do
|
|
695
|
+
@session.visit('/with_js')
|
|
696
|
+
target = @session.find('//div[@id="drop_html5"]')
|
|
697
|
+
target.drop('text/plain' => 'Some dropped text', 'text/url' => 'http://www.google.com')
|
|
698
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain Some dropped text")]')
|
|
699
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/url http://www.google.com")]')
|
|
287
700
|
end
|
|
288
701
|
end
|
|
289
702
|
|
|
290
703
|
describe '#hover', requires: [:hover] do
|
|
291
|
-
it
|
|
704
|
+
it 'should allow hovering on an element' do
|
|
292
705
|
@session.visit('/with_hover')
|
|
293
706
|
expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible
|
|
294
707
|
@session.find(:css, '.wrapper:not(.scroll_needed)').hover
|
|
295
708
|
expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
|
|
296
709
|
end
|
|
297
710
|
|
|
298
|
-
it
|
|
711
|
+
it 'should allow hovering on an element that needs to be scrolled into view' do
|
|
299
712
|
@session.visit('/with_hover')
|
|
300
713
|
expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible
|
|
301
714
|
@session.find(:css, '.wrapper.scroll_needed').hover
|
|
302
715
|
expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible
|
|
303
716
|
end
|
|
717
|
+
|
|
718
|
+
it 'should hover again after following a link and back' do
|
|
719
|
+
@session.visit('/with_hover')
|
|
720
|
+
@session.find(:css, '.wrapper:not(.scroll_needed)').hover
|
|
721
|
+
@session.click_link('Other hover page')
|
|
722
|
+
@session.click_link('Go back')
|
|
723
|
+
@session.find(:css, '.wrapper:not(.scroll_needed)').hover
|
|
724
|
+
expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
|
|
725
|
+
end
|
|
304
726
|
end
|
|
305
727
|
|
|
306
728
|
describe '#click' do
|
|
307
|
-
it
|
|
729
|
+
it 'should not follow a link if no href' do
|
|
308
730
|
@session.find(:css, '#link_placeholder').click
|
|
309
731
|
expect(@session.current_url).to match(%r{/with_html$})
|
|
310
732
|
end
|
|
311
733
|
|
|
312
|
-
it
|
|
734
|
+
it 'should go to the same page if href is blank' do
|
|
313
735
|
@session.find(:css, '#link_blank_href').click
|
|
314
736
|
sleep 1
|
|
315
737
|
expect(@session).to have_current_path('/with_html')
|
|
316
738
|
end
|
|
317
739
|
|
|
318
|
-
it
|
|
740
|
+
it 'should be able to check a checkbox' do
|
|
319
741
|
@session.visit('form')
|
|
320
742
|
cbox = @session.find(:checkbox, 'form_terms_of_use')
|
|
321
743
|
expect(cbox).not_to be_checked
|
|
@@ -323,7 +745,7 @@ Capybara::SpecHelper.spec "node" do
|
|
|
323
745
|
expect(cbox).to be_checked
|
|
324
746
|
end
|
|
325
747
|
|
|
326
|
-
it
|
|
748
|
+
it 'should be able to uncheck a checkbox' do
|
|
327
749
|
@session.visit('/form')
|
|
328
750
|
cbox = @session.find(:checkbox, 'form_pets_dog')
|
|
329
751
|
expect(cbox).to be_checked
|
|
@@ -331,7 +753,7 @@ Capybara::SpecHelper.spec "node" do
|
|
|
331
753
|
expect(cbox).not_to be_checked
|
|
332
754
|
end
|
|
333
755
|
|
|
334
|
-
it
|
|
756
|
+
it 'should be able to select a radio button' do
|
|
335
757
|
@session.visit('/form')
|
|
336
758
|
radio = @session.find(:radio_button, 'gender_male')
|
|
337
759
|
expect(radio).not_to be_checked
|
|
@@ -339,118 +761,450 @@ Capybara::SpecHelper.spec "node" do
|
|
|
339
761
|
expect(radio).to be_checked
|
|
340
762
|
end
|
|
341
763
|
|
|
342
|
-
it
|
|
764
|
+
it 'should allow modifiers', requires: [:js] do
|
|
343
765
|
@session.visit('/with_js')
|
|
344
766
|
@session.find(:css, '#click-test').click(:shift)
|
|
345
767
|
expect(@session).to have_link('Has been shift clicked')
|
|
346
768
|
end
|
|
347
769
|
|
|
348
|
-
it
|
|
770
|
+
it 'should allow multiple modifiers', requires: [:js] do
|
|
349
771
|
@session.visit('with_js')
|
|
350
772
|
@session.find(:css, '#click-test').click(:control, :alt, :meta, :shift)
|
|
351
773
|
# Selenium with Chrome on OSX ctrl-click generates a right click so just verify all keys but not click type
|
|
352
|
-
expect(@session).to have_link(
|
|
774
|
+
expect(@session).to have_link('alt control meta shift')
|
|
353
775
|
end
|
|
354
776
|
|
|
355
|
-
it
|
|
777
|
+
it 'should allow to adjust the click offset', requires: [:js] do
|
|
356
778
|
@session.visit('with_js')
|
|
357
779
|
@session.find(:css, '#click-test').click(x: 5, y: 5)
|
|
358
780
|
link = @session.find(:link, 'has-been-clicked')
|
|
359
|
-
locations = link.text.match(/^Has been clicked at (?<x>[\d
|
|
781
|
+
locations = link.text.match(/^Has been clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
|
360
782
|
# Resulting click location should be very close to 0, 0 relative to top left corner of the element, but may not be exact due to
|
|
361
783
|
# integer/float conversions and rounding.
|
|
362
784
|
expect(locations[:x].to_f).to be_within(1).of(5)
|
|
363
785
|
expect(locations[:y].to_f).to be_within(1).of(5)
|
|
364
786
|
end
|
|
365
|
-
end
|
|
366
787
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
788
|
+
it 'should raise error if both x and y values are not passed' do
|
|
789
|
+
@session.visit('with_js')
|
|
790
|
+
el = @session.find(:css, '#click-test')
|
|
791
|
+
expect { el.click(x: 5) }.to raise_error ArgumentError
|
|
792
|
+
expect { el.click(x: nil, y: 3) }.to raise_error ArgumentError
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
it 'should be able to click a table row', requires: [:js] do
|
|
796
|
+
@session.visit('/tables')
|
|
797
|
+
tr = @session.find(:css, '#agent_table tr:first-child').click
|
|
798
|
+
expect(tr).to have_css('label', text: 'Clicked')
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
it 'should retry clicking', requires: [:js] do
|
|
802
|
+
@session.visit('/animated')
|
|
803
|
+
obscured = @session.find(:css, '#obscured')
|
|
804
|
+
@session.execute_script <<~JS
|
|
805
|
+
setTimeout(function(){ $('#cover').hide(); }, 700)
|
|
806
|
+
JS
|
|
807
|
+
expect { obscured.click }.not_to raise_error
|
|
370
808
|
end
|
|
371
809
|
|
|
372
|
-
it
|
|
810
|
+
it 'should allow to retry longer', requires: [:js] do
|
|
811
|
+
@session.visit('/animated')
|
|
812
|
+
obscured = @session.find(:css, '#obscured')
|
|
813
|
+
@session.execute_script <<~JS
|
|
814
|
+
setTimeout(function(){ $('#cover').hide(); }, 3000)
|
|
815
|
+
JS
|
|
816
|
+
expect { obscured.click(wait: 4) }.not_to raise_error
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
it 'should not retry clicking when wait is disabled', requires: [:js] do
|
|
820
|
+
@session.visit('/animated')
|
|
821
|
+
obscured = @session.find(:css, '#obscured')
|
|
822
|
+
@session.execute_script <<~JS
|
|
823
|
+
setTimeout(function(){ $('#cover').hide(); }, 2000)
|
|
824
|
+
JS
|
|
825
|
+
expect { obscured.click(wait: 0) }.to(raise_error { |e| expect(e).to be_an_invalid_element_error(@session) })
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
context 'offset', requires: [:js] do
|
|
829
|
+
before do
|
|
830
|
+
@session.visit('/offset')
|
|
831
|
+
end
|
|
832
|
+
|
|
833
|
+
let :clicker do
|
|
834
|
+
@session.find(:id, 'clicker')
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
context 'when w3c_click_offset is false' do
|
|
838
|
+
before do
|
|
839
|
+
Capybara.w3c_click_offset = false
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
it 'should offset from top left of element' do
|
|
843
|
+
clicker.click(x: 10, y: 5)
|
|
844
|
+
expect(@session).to have_text(/clicked at 110,105/)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
it 'should offset outside the element' do
|
|
848
|
+
clicker.click(x: -15, y: -10)
|
|
849
|
+
expect(@session).to have_text(/clicked at 85,90/)
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
it 'should default to click the middle' do
|
|
853
|
+
clicker.click
|
|
854
|
+
expect(@session).to have_text(/clicked at 150,150/)
|
|
855
|
+
end
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
context 'when w3c_click_offset is true' do
|
|
859
|
+
before do
|
|
860
|
+
Capybara.w3c_click_offset = true
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
it 'should offset from center of element' do
|
|
864
|
+
clicker.click(x: 10, y: 5)
|
|
865
|
+
expect(@session).to have_text(/clicked at 160,155/)
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
it 'should offset outside from center of element' do
|
|
869
|
+
clicker.click(x: -65, y: -60)
|
|
870
|
+
expect(@session).to have_text(/clicked at 85,90/)
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
it 'should default to click the middle' do
|
|
874
|
+
clicker.click
|
|
875
|
+
expect(@session).to have_text(/clicked at 150,150/)
|
|
876
|
+
end
|
|
877
|
+
end
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
context 'delay', requires: [:js] do
|
|
881
|
+
it 'should delay the mouse up' do
|
|
882
|
+
@session.visit('with_js')
|
|
883
|
+
@session.find(:css, '#click-test').click(delay: 2)
|
|
884
|
+
delay = @session.evaluate_script('window.click_delay')
|
|
885
|
+
expect(delay).to be >= 2
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
describe '#double_click', requires: [:js] do
|
|
891
|
+
it 'should double click an element' do
|
|
373
892
|
@session.visit('/with_js')
|
|
374
893
|
@session.find(:css, '#click-test').double_click
|
|
375
|
-
expect(@session.find(:css, '#has-been-double-clicked')).to
|
|
894
|
+
expect(@session.find(:css, '#has-been-double-clicked')).to be_truthy
|
|
376
895
|
end
|
|
377
896
|
|
|
378
|
-
it
|
|
897
|
+
it 'should allow modifiers', requires: [:js] do
|
|
379
898
|
@session.visit('/with_js')
|
|
380
899
|
@session.find(:css, '#click-test').double_click(:alt)
|
|
381
900
|
expect(@session).to have_link('Has been alt double clicked')
|
|
382
901
|
end
|
|
383
902
|
|
|
384
|
-
it
|
|
903
|
+
it 'should allow to adjust the offset', requires: [:js] do
|
|
385
904
|
@session.visit('with_js')
|
|
386
905
|
@session.find(:css, '#click-test').double_click(x: 10, y: 5)
|
|
387
906
|
link = @session.find(:link, 'has-been-double-clicked')
|
|
388
|
-
locations = link.text.match(/^Has been double clicked at (?<x>[\d
|
|
907
|
+
locations = link.text.match(/^Has been double clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
|
389
908
|
# Resulting click location should be very close to 10, 5 relative to top left corner of the element, but may not be exact due
|
|
390
909
|
# to integer/float conversions and rounding.
|
|
391
910
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
|
392
911
|
expect(locations[:y].to_f).to be_within(1).of(5)
|
|
393
912
|
end
|
|
913
|
+
|
|
914
|
+
it 'should retry clicking', requires: [:js] do
|
|
915
|
+
@session.visit('/animated')
|
|
916
|
+
obscured = @session.find(:css, '#obscured')
|
|
917
|
+
@session.execute_script <<~JS
|
|
918
|
+
setTimeout(function(){ $('#cover').hide(); }, 700)
|
|
919
|
+
JS
|
|
920
|
+
expect { obscured.double_click }.not_to raise_error
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
context 'offset', requires: [:js] do
|
|
924
|
+
before do
|
|
925
|
+
@session.visit('/offset')
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
let :clicker do
|
|
929
|
+
@session.find(:id, 'clicker')
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
context 'when w3c_click_offset is false' do
|
|
933
|
+
before do
|
|
934
|
+
Capybara.w3c_click_offset = false
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
it 'should offset from top left of element' do
|
|
938
|
+
clicker.double_click(x: 10, y: 5)
|
|
939
|
+
expect(@session).to have_text(/clicked at 110,105/)
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
it 'should offset outside the element' do
|
|
943
|
+
clicker.double_click(x: -15, y: -10)
|
|
944
|
+
expect(@session).to have_text(/clicked at 85,90/)
|
|
945
|
+
end
|
|
946
|
+
|
|
947
|
+
it 'should default to click the middle' do
|
|
948
|
+
clicker.double_click
|
|
949
|
+
expect(@session).to have_text(/clicked at 150,150/)
|
|
950
|
+
end
|
|
951
|
+
end
|
|
952
|
+
|
|
953
|
+
context 'when w3c_click_offset is true' do
|
|
954
|
+
before do
|
|
955
|
+
Capybara.w3c_click_offset = true
|
|
956
|
+
end
|
|
957
|
+
|
|
958
|
+
it 'should offset from center of element' do
|
|
959
|
+
clicker.double_click(x: 10, y: 5)
|
|
960
|
+
expect(@session).to have_text(/clicked at 160,155/)
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
it 'should offset outside from center of element' do
|
|
964
|
+
clicker.double_click(x: -65, y: -60)
|
|
965
|
+
expect(@session).to have_text(/clicked at 85,90/)
|
|
966
|
+
end
|
|
967
|
+
|
|
968
|
+
it 'should default to click the middle' do
|
|
969
|
+
clicker.double_click
|
|
970
|
+
expect(@session).to have_text(/clicked at 150,150/)
|
|
971
|
+
end
|
|
972
|
+
end
|
|
973
|
+
end
|
|
394
974
|
end
|
|
395
975
|
|
|
396
976
|
describe '#right_click', requires: [:js] do
|
|
397
|
-
it
|
|
977
|
+
it 'should right click an element' do
|
|
398
978
|
@session.visit('/with_js')
|
|
399
979
|
@session.find(:css, '#click-test').right_click
|
|
400
|
-
expect(@session.find(:css, '#has-been-right-clicked')).to
|
|
980
|
+
expect(@session.find(:css, '#has-been-right-clicked')).to be_truthy
|
|
401
981
|
end
|
|
402
982
|
|
|
403
|
-
it
|
|
983
|
+
it 'should allow modifiers', requires: [:js] do
|
|
404
984
|
@session.visit('/with_js')
|
|
405
985
|
@session.find(:css, '#click-test').right_click(:meta)
|
|
406
986
|
expect(@session).to have_link('Has been meta right clicked')
|
|
407
987
|
end
|
|
408
988
|
|
|
409
|
-
it
|
|
989
|
+
it 'should allow to adjust the offset', requires: [:js] do
|
|
410
990
|
@session.visit('with_js')
|
|
411
991
|
@session.find(:css, '#click-test').right_click(x: 10, y: 10)
|
|
412
992
|
link = @session.find(:link, 'has-been-right-clicked')
|
|
413
|
-
locations = link.text.match(/^Has been right clicked at (?<x>[\d
|
|
993
|
+
locations = link.text.match(/^Has been right clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
|
414
994
|
# Resulting click location should be very close to 10, 10 relative to top left corner of the element, but may not be exact due
|
|
415
995
|
# to integer/float conversions and rounding
|
|
416
996
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
|
417
997
|
expect(locations[:y].to_f).to be_within(1).of(10)
|
|
418
998
|
end
|
|
999
|
+
|
|
1000
|
+
it 'should retry clicking', requires: [:js] do
|
|
1001
|
+
@session.visit('/animated')
|
|
1002
|
+
obscured = @session.find(:css, '#obscured')
|
|
1003
|
+
@session.execute_script <<~JS
|
|
1004
|
+
setTimeout(function(){ $('#cover').hide(); }, 700)
|
|
1005
|
+
JS
|
|
1006
|
+
expect { obscured.right_click }.not_to raise_error
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
context 'offset', requires: [:js] do
|
|
1010
|
+
before do
|
|
1011
|
+
@session.visit('/offset')
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
let :clicker do
|
|
1015
|
+
@session.find(:id, 'clicker')
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
context 'when w3c_click_offset is false' do
|
|
1019
|
+
before do
|
|
1020
|
+
Capybara.w3c_click_offset = false
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
it 'should offset from top left of element' do
|
|
1024
|
+
clicker.right_click(x: 10, y: 5)
|
|
1025
|
+
expect(@session).to have_text(/clicked at 110,105/)
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
it 'should offset outside the element' do
|
|
1029
|
+
clicker.right_click(x: -15, y: -10)
|
|
1030
|
+
expect(@session).to have_text(/clicked at 85,90/)
|
|
1031
|
+
end
|
|
1032
|
+
|
|
1033
|
+
it 'should default to click the middle' do
|
|
1034
|
+
clicker.right_click
|
|
1035
|
+
expect(@session).to have_text(/clicked at 150,150/)
|
|
1036
|
+
end
|
|
1037
|
+
end
|
|
1038
|
+
|
|
1039
|
+
context 'when w3c_click_offset is true' do
|
|
1040
|
+
before do
|
|
1041
|
+
Capybara.w3c_click_offset = true
|
|
1042
|
+
end
|
|
1043
|
+
|
|
1044
|
+
it 'should offset from center of element' do
|
|
1045
|
+
clicker.right_click(x: 10, y: 5)
|
|
1046
|
+
expect(@session).to have_text(/clicked at 160,155/)
|
|
1047
|
+
end
|
|
1048
|
+
|
|
1049
|
+
it 'should offset outside from center of element' do
|
|
1050
|
+
clicker.right_click(x: -65, y: -60)
|
|
1051
|
+
expect(@session).to have_text(/clicked at 85,90/)
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
it 'should default to click the middle' do
|
|
1055
|
+
clicker.right_click
|
|
1056
|
+
expect(@session).to have_text(/clicked at 150,150/)
|
|
1057
|
+
end
|
|
1058
|
+
end
|
|
1059
|
+
end
|
|
1060
|
+
|
|
1061
|
+
context 'delay', requires: [:js] do
|
|
1062
|
+
it 'should delay the mouse up' do
|
|
1063
|
+
@session.visit('with_js')
|
|
1064
|
+
@session.find(:css, '#click-test').right_click(delay: 2)
|
|
1065
|
+
delay = @session.evaluate_script('window.right_click_delay')
|
|
1066
|
+
expect(delay).to be >= 2
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
419
1069
|
end
|
|
420
1070
|
|
|
421
1071
|
describe '#send_keys', requires: [:send_keys] do
|
|
422
|
-
it
|
|
1072
|
+
it 'should send a string of keys to an element' do
|
|
423
1073
|
@session.visit('/form')
|
|
424
1074
|
@session.find(:css, '#address1_city').send_keys('Oceanside')
|
|
425
1075
|
expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'
|
|
426
1076
|
end
|
|
427
1077
|
|
|
428
|
-
it
|
|
429
|
-
pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
|
|
1078
|
+
it 'should send special characters' do
|
|
430
1079
|
@session.visit('/form')
|
|
431
1080
|
@session.find(:css, '#address1_city').send_keys('Ocean', :space, 'sie', :left, 'd')
|
|
432
1081
|
expect(@session.find(:css, '#address1_city').value).to eq 'Ocean side'
|
|
433
1082
|
end
|
|
434
1083
|
|
|
435
|
-
it
|
|
436
|
-
pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
|
|
1084
|
+
it 'should allow for multiple simultaneous keys' do
|
|
437
1085
|
@session.visit('/form')
|
|
438
1086
|
@session.find(:css, '#address1_city').send_keys([:shift, 'o'], 'ceanside')
|
|
439
1087
|
expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'
|
|
440
1088
|
end
|
|
441
1089
|
|
|
442
|
-
it
|
|
443
|
-
|
|
1090
|
+
it 'should hold modifiers at top level' do
|
|
1091
|
+
@session.visit('/form')
|
|
1092
|
+
@session.find(:css, '#address1_city').send_keys('ocean', :shift, 'side')
|
|
1093
|
+
expect(@session.find(:css, '#address1_city').value).to eq 'oceanSIDE'
|
|
1094
|
+
end
|
|
1095
|
+
|
|
1096
|
+
it 'should generate key events', requires: %i[send_keys js] do
|
|
444
1097
|
@session.visit('/with_js')
|
|
445
1098
|
@session.find(:css, '#with-key-events').send_keys([:shift, 't'], [:shift, 'w'])
|
|
446
1099
|
expect(@session.find(:css, '#key-events-output')).to have_text('keydown:16 keydown:84 keydown:16 keydown:87')
|
|
447
1100
|
end
|
|
448
1101
|
end
|
|
449
1102
|
|
|
1103
|
+
describe '#execute_script', requires: %i[js es_args] do
|
|
1104
|
+
it 'should execute the given script in the context of the element and return nothing' do
|
|
1105
|
+
@session.visit('/with_js')
|
|
1106
|
+
expect(@session.find(:css, '#change').execute_script("this.textContent = 'Funky Doodle'")).to be_nil
|
|
1107
|
+
expect(@session).to have_css('#change', text: 'Funky Doodle')
|
|
1108
|
+
end
|
|
1109
|
+
|
|
1110
|
+
it 'should pass arguments to the script' do
|
|
1111
|
+
@session.visit('/with_js')
|
|
1112
|
+
@session.find(:css, '#change').execute_script('this.textContent = arguments[0]', 'Doodle Funk')
|
|
1113
|
+
expect(@session).to have_css('#change', text: 'Doodle Funk')
|
|
1114
|
+
end
|
|
1115
|
+
end
|
|
1116
|
+
|
|
1117
|
+
describe '#evaluate_script', requires: %i[js es_args] do
|
|
1118
|
+
it 'should evaluate the given script in the context of the element and return whatever it produces' do
|
|
1119
|
+
@session.visit('/with_js')
|
|
1120
|
+
el = @session.find(:css, '#with_change_event')
|
|
1121
|
+
expect(el.evaluate_script('this.value')).to eq('default value')
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1124
|
+
it 'should ignore leading whitespace' do
|
|
1125
|
+
@session.visit('/with_js')
|
|
1126
|
+
expect(@session.find(:css, '#change').evaluate_script('
|
|
1127
|
+
2 + 3
|
|
1128
|
+
')).to eq 5
|
|
1129
|
+
end
|
|
1130
|
+
|
|
1131
|
+
it 'should pass arguments to the script' do
|
|
1132
|
+
@session.visit('/with_js')
|
|
1133
|
+
@session.find(:css, '#change').evaluate_script('this.textContent = arguments[0]', 'Doodle Funk')
|
|
1134
|
+
expect(@session).to have_css('#change', text: 'Doodle Funk')
|
|
1135
|
+
end
|
|
1136
|
+
|
|
1137
|
+
it 'should pass multiple arguments' do
|
|
1138
|
+
@session.visit('/with_js')
|
|
1139
|
+
change = @session.find(:css, '#change')
|
|
1140
|
+
expect(change.evaluate_script('arguments[0] + arguments[1]', 2, 3)).to eq 5
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
it 'should support returning elements' do
|
|
1144
|
+
@session.visit('/with_js')
|
|
1145
|
+
change = @session.find(:css, '#change') # ensure page has loaded and element is available
|
|
1146
|
+
el = change.evaluate_script('this')
|
|
1147
|
+
expect(el).to be_instance_of(Capybara::Node::Element)
|
|
1148
|
+
expect(el).to eq(change)
|
|
1149
|
+
end
|
|
1150
|
+
|
|
1151
|
+
it 'should support multiple statements via IIFE' do
|
|
1152
|
+
@session.visit('/with_js')
|
|
1153
|
+
change = @session.find(:css, '#change') # ensure page has loaded and element is available
|
|
1154
|
+
res = change.evaluate_script(<<~JS, 3)
|
|
1155
|
+
(function(n){
|
|
1156
|
+
var el = this;
|
|
1157
|
+
return [el, n];
|
|
1158
|
+
}).apply(this, arguments)
|
|
1159
|
+
JS
|
|
1160
|
+
expect(res).to eq [change, 3]
|
|
1161
|
+
end
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
describe '#evaluate_async_script', requires: %i[js es_args] do
|
|
1165
|
+
it 'should evaluate the given script in the context of the element' do
|
|
1166
|
+
@session.visit('/with_js')
|
|
1167
|
+
el = @session.find(:css, '#with_change_event')
|
|
1168
|
+
expect(el.evaluate_async_script('arguments[0](this.value)')).to eq('default value')
|
|
1169
|
+
end
|
|
1170
|
+
|
|
1171
|
+
it 'should support returning elements after asynchronous operation' do
|
|
1172
|
+
@session.visit('/with_js')
|
|
1173
|
+
change = @session.find(:css, '#change') # ensure page has loaded and element is available
|
|
1174
|
+
el = change.evaluate_async_script('var cb = arguments[0]; setTimeout(function(el){ cb(el) }, 100, this)')
|
|
1175
|
+
expect(el).to eq(change)
|
|
1176
|
+
end
|
|
1177
|
+
end
|
|
1178
|
+
|
|
450
1179
|
describe '#reload', requires: [:js] do
|
|
451
|
-
|
|
1180
|
+
it 'should reload elements found via ancestor with CSS' do
|
|
1181
|
+
@session.visit('/with_js')
|
|
1182
|
+
node = @session.find(:css, '#reload-me em').ancestor(:css, 'div')
|
|
1183
|
+
node.reload
|
|
1184
|
+
expect(node[:id]).to eq 'reload-me'
|
|
1185
|
+
end
|
|
1186
|
+
|
|
1187
|
+
it 'should reload elements found via ancestor with XPath' do
|
|
1188
|
+
@session.visit('/with_js')
|
|
1189
|
+
node = @session.find(:css, '#reload-me em').ancestor(:xpath, './/div')
|
|
1190
|
+
node.reload
|
|
1191
|
+
expect(node[:id]).to eq 'reload-me'
|
|
1192
|
+
end
|
|
1193
|
+
|
|
1194
|
+
it 'should reload elements found via sibling' do
|
|
1195
|
+
@session.visit('/with_js')
|
|
1196
|
+
node = @session.find(:css, '#the-list li', text: 'Item 1').sibling(:css, 'li')
|
|
1197
|
+
expect(node.text).to eq 'Item 2'
|
|
1198
|
+
node.reload
|
|
1199
|
+
expect(node.text).to eq 'Item 2'
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
context 'without automatic reload' do
|
|
452
1203
|
before { Capybara.automatic_reload = false }
|
|
453
|
-
|
|
1204
|
+
|
|
1205
|
+
after { Capybara.automatic_reload = true }
|
|
1206
|
+
|
|
1207
|
+
it 'should reload the current context of the node' do
|
|
454
1208
|
@session.visit('/with_js')
|
|
455
1209
|
node = @session.find(:css, '#reload-me')
|
|
456
1210
|
@session.click_link('Reload!')
|
|
@@ -459,7 +1213,7 @@ Capybara::SpecHelper.spec "node" do
|
|
|
459
1213
|
expect(node.text).to eq('has been reloaded')
|
|
460
1214
|
end
|
|
461
1215
|
|
|
462
|
-
it
|
|
1216
|
+
it 'should reload a parent node' do
|
|
463
1217
|
@session.visit('/with_js')
|
|
464
1218
|
node = @session.find(:css, '#reload-me').find(:css, 'em')
|
|
465
1219
|
@session.click_link('Reload!')
|
|
@@ -468,7 +1222,7 @@ Capybara::SpecHelper.spec "node" do
|
|
|
468
1222
|
expect(node.text).to eq('has been reloaded')
|
|
469
1223
|
end
|
|
470
1224
|
|
|
471
|
-
it
|
|
1225
|
+
it 'should not automatically reload' do
|
|
472
1226
|
@session.visit('/with_js')
|
|
473
1227
|
node = @session.find(:css, '#reload-me')
|
|
474
1228
|
@session.click_link('Reload!')
|
|
@@ -479,15 +1233,14 @@ Capybara::SpecHelper.spec "node" do
|
|
|
479
1233
|
expect(error).to be_an_invalid_element_error(@session)
|
|
480
1234
|
end)
|
|
481
1235
|
end
|
|
482
|
-
after { Capybara.automatic_reload = true }
|
|
483
1236
|
end
|
|
484
1237
|
|
|
485
|
-
context
|
|
1238
|
+
context 'with automatic reload' do
|
|
486
1239
|
before do
|
|
487
1240
|
Capybara.default_max_wait_time = 4
|
|
488
1241
|
end
|
|
489
1242
|
|
|
490
|
-
it
|
|
1243
|
+
it 'should reload the current context of the node automatically' do
|
|
491
1244
|
@session.visit('/with_js')
|
|
492
1245
|
node = @session.find(:css, '#reload-me')
|
|
493
1246
|
@session.click_link('Reload!')
|
|
@@ -495,7 +1248,7 @@ Capybara::SpecHelper.spec "node" do
|
|
|
495
1248
|
expect(node.text).to eq('has been reloaded')
|
|
496
1249
|
end
|
|
497
1250
|
|
|
498
|
-
it
|
|
1251
|
+
it 'should reload a parent node automatically' do
|
|
499
1252
|
@session.visit('/with_js')
|
|
500
1253
|
node = @session.find(:css, '#reload-me').find(:css, 'em')
|
|
501
1254
|
@session.click_link('Reload!')
|
|
@@ -503,7 +1256,7 @@ Capybara::SpecHelper.spec "node" do
|
|
|
503
1256
|
expect(node.text).to eq('has been reloaded')
|
|
504
1257
|
end
|
|
505
1258
|
|
|
506
|
-
it
|
|
1259
|
+
it 'should reload a node automatically when using find' do
|
|
507
1260
|
@session.visit('/with_js')
|
|
508
1261
|
node = @session.find(:css, '#reload-me')
|
|
509
1262
|
@session.click_link('Reload!')
|
|
@@ -525,9 +1278,9 @@ Capybara::SpecHelper.spec "node" do
|
|
|
525
1278
|
end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })
|
|
526
1279
|
end
|
|
527
1280
|
|
|
528
|
-
it
|
|
1281
|
+
it 'should reload nodes with options' do
|
|
529
1282
|
@session.visit('/with_js')
|
|
530
|
-
node = @session.find(:css, 'em', text:
|
|
1283
|
+
node = @session.find(:css, 'em', text: 'reloaded')
|
|
531
1284
|
@session.click_link('Reload!')
|
|
532
1285
|
sleep(1)
|
|
533
1286
|
expect(node.text).to eq('has been reloaded')
|
|
@@ -535,9 +1288,9 @@ Capybara::SpecHelper.spec "node" do
|
|
|
535
1288
|
end
|
|
536
1289
|
end
|
|
537
1290
|
|
|
538
|
-
context
|
|
539
|
-
it
|
|
540
|
-
quietly { @session.visit(
|
|
1291
|
+
context 'when #synchronize raises server errors' do
|
|
1292
|
+
it 'sets an explanatory exception as the cause of server exceptions', requires: %i[server js] do
|
|
1293
|
+
quietly { @session.visit('/error') }
|
|
541
1294
|
expect do
|
|
542
1295
|
@session.find(:css, 'span')
|
|
543
1296
|
end.to(raise_error(TestApp::TestAppError) do |e|
|
|
@@ -546,8 +1299,8 @@ Capybara::SpecHelper.spec "node" do
|
|
|
546
1299
|
end)
|
|
547
1300
|
end
|
|
548
1301
|
|
|
549
|
-
it
|
|
550
|
-
quietly { @session.visit(
|
|
1302
|
+
it 'sets an explanatory exception as the cause of server exceptions with errors with initializers', requires: %i[server js] do
|
|
1303
|
+
quietly { @session.visit('/other_error') }
|
|
551
1304
|
expect do
|
|
552
1305
|
@session.find(:css, 'span')
|
|
553
1306
|
end.to(raise_error(TestApp::TestAppOtherError) do |e|
|
|
@@ -556,8 +1309,4 @@ Capybara::SpecHelper.spec "node" do
|
|
|
556
1309
|
end)
|
|
557
1310
|
end
|
|
558
1311
|
end
|
|
559
|
-
|
|
560
|
-
def be_an_invalid_element_error(session)
|
|
561
|
-
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
|
562
|
-
end
|
|
563
1312
|
end
|