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