capybara 3.13.2 → 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 +587 -16
- data/README.md +240 -90
- data/lib/capybara/config.rb +24 -11
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +8 -0
- data/lib/capybara/driver/node.rb +20 -4
- data/lib/capybara/dsl.rb +5 -3
- data/lib/capybara/helpers.rb +25 -4
- data/lib/capybara/minitest/spec.rb +174 -90
- data/lib/capybara/minitest.rb +256 -142
- data/lib/capybara/node/actions.rb +123 -77
- data/lib/capybara/node/base.rb +20 -12
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +223 -117
- data/lib/capybara/node/finders.rb +81 -71
- data/lib/capybara/node/matchers.rb +271 -134
- data/lib/capybara/node/simple.rb +18 -5
- 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 +3 -2
- data/lib/capybara/queries/current_path_query.rb +15 -5
- data/lib/capybara/queries/selector_query.rb +364 -54
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +2 -2
- data/lib/capybara/queries/text_query.rb +13 -1
- data/lib/capybara/queries/title_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +76 -11
- data/lib/capybara/rack_test/driver.rb +10 -5
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +31 -9
- data/lib/capybara/rack_test/node.rb +74 -23
- 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 +44 -20
- data/lib/capybara/rspec/matcher_proxies.rb +13 -11
- data/lib/capybara/rspec/matchers/base.rb +31 -16
- data/lib/capybara/rspec/matchers/compound.rb +1 -1
- 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 +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +21 -21
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +4 -4
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +7 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +111 -68
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/selector/builders/css_builder.rb +11 -7
- data/lib/capybara/selector/builders/xpath_builder.rb +5 -3
- data/lib/capybara/selector/css.rb +11 -9
- 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_set.rb +19 -18
- data/lib/capybara/selector/filters/base.rb +11 -2
- data/lib/capybara/selector/filters/locator_filter.rb +13 -3
- data/lib/capybara/selector/regexp_disassembler.rb +11 -7
- data/lib/capybara/selector/selector.rb +50 -440
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +473 -482
- 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 +174 -62
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +74 -18
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +37 -3
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
- 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 +68 -45
- data/lib/capybara/selenium/extensions/html5_drag.rb +192 -22
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/node.rb +268 -72
- data/lib/capybara/selenium/nodes/chrome_node.rb +105 -9
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +51 -61
- 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 +1 -1
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +43 -21
- data/lib/capybara/server/checker.rb +6 -2
- data/lib/capybara/server/middleware.rb +25 -13
- data/lib/capybara/server.rb +20 -4
- data/lib/capybara/session/config.rb +15 -11
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/session.rb +162 -131
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +105 -6
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +89 -15
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
- data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
- data/lib/capybara/spec/session/attach_file_spec.rb +64 -31
- data/lib/capybara/spec/session/check_spec.rb +26 -4
- data/lib/capybara/spec/session/choose_spec.rb +14 -2
- data/lib/capybara/spec/session/click_button_spec.rb +109 -61
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/click_link_spec.rb +23 -1
- data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
- data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +46 -5
- data/lib/capybara/spec/session/find_link_spec.rb +10 -0
- data/lib/capybara/spec/session/find_spec.rb +80 -7
- data/lib/capybara/spec/session/first_spec.rb +2 -2
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
- data/lib/capybara/spec/session/has_button_spec.rb +81 -0
- data/lib/capybara/spec/session/has_css_spec.rb +45 -8
- data/lib/capybara/spec/session/has_current_path_spec.rb +22 -7
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +59 -1
- data/lib/capybara/spec/session/has_link_spec.rb +40 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
- data/lib/capybara/spec/session/has_select_spec.rb +42 -8
- data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +177 -0
- data/lib/capybara/spec/session/has_text_spec.rb +31 -3
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +6 -4
- data/lib/capybara/spec/session/node_spec.rb +697 -23
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +21 -7
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/scroll_spec.rb +9 -7
- data/lib/capybara/spec/session/select_spec.rb +5 -10
- data/lib/capybara/spec/session/selectors_spec.rb +24 -3
- data/lib/capybara/spec/session/uncheck_spec.rb +3 -3
- data/lib/capybara/spec/session/unselect_spec.rb +1 -1
- data/lib/capybara/spec/session/visit_spec.rb +20 -0
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +54 -57
- data/lib/capybara/spec/session/window/windows_spec.rb +2 -2
- data/lib/capybara/spec/session/within_spec.rb +36 -0
- data/lib/capybara/spec/spec_helper.rb +30 -19
- data/lib/capybara/spec/test_app.rb +122 -34
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +86 -8
- data/lib/capybara/spec/views/frame_child.erb +3 -2
- 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 +10 -10
- 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 +2 -1
- 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 +34 -6
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +7 -4
- 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 +14 -18
- data/lib/capybara.rb +91 -126
- data/spec/basic_node_spec.rb +30 -16
- data/spec/capybara_spec.rb +40 -28
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +3 -1
- data/spec/css_splitter_spec.rb +1 -1
- data/spec/dsl_spec.rb +33 -22
- data/spec/filter_set_spec.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_failure.rb +3 -3
- data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
- data/spec/minitest_spec.rb +24 -2
- data/spec/minitest_spec_spec.rb +60 -45
- data/spec/per_session_config_spec.rb +1 -1
- data/spec/rack_test_spec.rb +131 -98
- data/spec/regexp_dissassembler_spec.rb +53 -39
- data/spec/result_spec.rb +68 -66
- data/spec/rspec/features_spec.rb +9 -4
- data/spec/rspec/scenarios_spec.rb +6 -2
- data/spec/rspec/shared_spec_matchers.rb +137 -98
- data/spec/rspec_matchers_spec.rb +25 -0
- data/spec/rspec_spec.rb +23 -21
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +77 -21
- data/spec/selenium_spec_chrome.rb +141 -39
- data/spec/selenium_spec_chrome_remote.rb +32 -17
- data/spec/selenium_spec_edge.rb +36 -8
- data/spec/selenium_spec_firefox.rb +110 -68
- data/spec/selenium_spec_firefox_remote.rb +22 -15
- data/spec/selenium_spec_ie.rb +29 -22
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +153 -81
- data/spec/session_spec.rb +11 -4
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +179 -74
- data/spec/spec_helper.rb +80 -5
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +3 -1
- metadata +218 -30
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -1,93 +1,91 @@
|
|
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
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
7
7
|
Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
8
|
+
let!(:orig_window) { @session.current_window }
|
8
9
|
before do
|
9
|
-
@window = @session.current_window
|
10
10
|
@session.visit('/with_windows')
|
11
11
|
end
|
12
12
|
|
13
13
|
after do
|
14
|
-
(@session.windows - [
|
14
|
+
(@session.windows - [orig_window]).each do |w|
|
15
15
|
@session.switch_to_window w
|
16
16
|
w.close
|
17
17
|
end
|
18
|
-
@session.switch_to_window(
|
18
|
+
@session.switch_to_window(orig_window)
|
19
19
|
end
|
20
20
|
|
21
21
|
describe '#exists?' do
|
22
|
-
|
23
|
-
|
22
|
+
it 'should become false after window was closed' do
|
23
|
+
other_window = @session.window_opened_by do
|
24
24
|
@session.find(:css, '#openWindow').click
|
25
25
|
end
|
26
|
-
end
|
27
26
|
|
28
|
-
it 'should become false after window was closed' do
|
29
27
|
expect do
|
30
|
-
@session.switch_to_window
|
31
|
-
|
32
|
-
end.to change
|
28
|
+
@session.switch_to_window other_window
|
29
|
+
other_window.close
|
30
|
+
end.to change(other_window, :exists?).from(true).to(false)
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
36
34
|
describe '#closed?' do
|
37
35
|
it 'should become true after window was closed' do
|
38
|
-
|
36
|
+
other_window = @session.window_opened_by do
|
39
37
|
@session.find(:css, '#openWindow').click
|
40
38
|
end
|
41
39
|
expect do
|
42
|
-
@session.switch_to_window
|
43
|
-
|
44
|
-
end.to change {
|
40
|
+
@session.switch_to_window other_window
|
41
|
+
other_window.close
|
42
|
+
end.to change { other_window.closed? }.from(false).to(true)
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
48
46
|
describe '#current?' do
|
49
|
-
|
50
|
-
@
|
47
|
+
let(:other_window) do
|
48
|
+
@session.window_opened_by do
|
51
49
|
@session.find(:css, '#openWindow').click
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
55
53
|
it 'should become true after switching to window' do
|
56
54
|
expect do
|
57
|
-
@session.switch_to_window(
|
58
|
-
end.to change
|
55
|
+
@session.switch_to_window(other_window)
|
56
|
+
end.to change(other_window, :current?).from(false).to(true)
|
59
57
|
end
|
60
58
|
|
61
59
|
it 'should return false if window is closed' do
|
62
|
-
@session.switch_to_window(
|
63
|
-
|
64
|
-
expect(
|
60
|
+
@session.switch_to_window(other_window)
|
61
|
+
other_window.close
|
62
|
+
expect(other_window.current?).to be(false)
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
68
66
|
describe '#close' do
|
69
|
-
|
70
|
-
@
|
67
|
+
let!(:other_window) do
|
68
|
+
@session.window_opened_by do
|
71
69
|
@session.find(:css, '#openWindow').click
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
75
73
|
it 'should switch to original window if invoked not for current window' do
|
76
74
|
expect(@session.windows.size).to eq(2)
|
77
|
-
expect(@session.current_window).to eq(
|
78
|
-
|
75
|
+
expect(@session.current_window).to eq(orig_window)
|
76
|
+
other_window.close
|
79
77
|
expect(@session.windows.size).to eq(1)
|
80
|
-
expect(@session.current_window).to eq(
|
78
|
+
expect(@session.current_window).to eq(orig_window)
|
81
79
|
end
|
82
80
|
|
83
81
|
it 'should make subsequent invocations of other methods raise no_such_window_error if invoked for current window' do
|
84
|
-
@session.switch_to_window(
|
85
|
-
expect(@session.current_window).to eq(
|
86
|
-
|
82
|
+
@session.switch_to_window(other_window)
|
83
|
+
expect(@session.current_window).to eq(other_window)
|
84
|
+
other_window.close
|
87
85
|
expect do
|
88
86
|
@session.find(:css, '#some_id')
|
89
87
|
end.to raise_error(@session.driver.no_such_window_error)
|
90
|
-
@session.switch_to_window(
|
88
|
+
@session.switch_to_window(orig_window)
|
91
89
|
end
|
92
90
|
end
|
93
91
|
|
@@ -101,55 +99,54 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
101
99
|
end
|
102
100
|
|
103
101
|
it 'should switch to original window if invoked not for current window' do
|
104
|
-
|
102
|
+
other_window = @session.window_opened_by do
|
105
103
|
@session.find(:css, '#openWindow').click
|
106
104
|
end
|
107
105
|
sleep 1
|
108
|
-
size = @session.within_window(
|
106
|
+
size = @session.within_window(other_window) do
|
109
107
|
win_size
|
110
108
|
end
|
111
|
-
expect(
|
112
|
-
expect(@session.current_window).to eq(
|
109
|
+
expect(other_window.size).to eq(size)
|
110
|
+
expect(@session.current_window).to eq(orig_window)
|
113
111
|
end
|
114
112
|
end
|
115
113
|
|
116
114
|
describe '#resize_to' do
|
117
|
-
|
118
|
-
@initial_size = @session.current_window.size
|
119
|
-
end
|
115
|
+
let!(:initial_size) { @session.current_window.size }
|
120
116
|
|
121
117
|
after do
|
122
|
-
@session.current_window.resize_to(
|
118
|
+
@session.current_window.resize_to(*initial_size)
|
123
119
|
sleep 1
|
124
120
|
end
|
125
121
|
|
126
122
|
it 'should be able to resize window', requires: %i[windows js] do
|
127
|
-
width, height =
|
123
|
+
width, height = initial_size
|
128
124
|
@session.current_window.resize_to(width - 100, height - 100)
|
129
125
|
sleep 1
|
130
126
|
expect(@session.current_window.size).to eq([width - 100, height - 100])
|
131
127
|
end
|
132
128
|
|
133
129
|
it 'should stay on current window if invoked not for current window', requires: %i[windows js] do
|
134
|
-
|
130
|
+
other_window = @session.window_opened_by do
|
135
131
|
@session.find(:css, '#openWindow').click
|
136
132
|
end
|
137
|
-
@other_window.resize_to(600, 300)
|
138
|
-
expect(@session.current_window).to eq(@window)
|
139
133
|
|
140
|
-
|
141
|
-
|
134
|
+
other_window.resize_to(600, 400)
|
135
|
+
expect(@session.current_window).to eq(orig_window)
|
136
|
+
|
137
|
+
@session.within_window(other_window) do
|
138
|
+
expect(@session.current_window.size).to eq([600, 400])
|
142
139
|
end
|
143
140
|
end
|
144
141
|
end
|
145
142
|
|
146
143
|
describe '#maximize' do
|
147
|
-
|
148
|
-
@
|
144
|
+
let! :initial_size do
|
145
|
+
@session.current_window.size
|
149
146
|
end
|
150
147
|
|
151
148
|
after do
|
152
|
-
@session.current_window.resize_to(
|
149
|
+
@session.current_window.resize_to(*initial_size)
|
153
150
|
sleep 0.5
|
154
151
|
end
|
155
152
|
|
@@ -169,31 +166,31 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
169
166
|
end
|
170
167
|
|
171
168
|
it 'should stay on current window if invoked not for current window', requires: %i[windows js] do
|
172
|
-
|
169
|
+
other_window = @session.window_opened_by do
|
173
170
|
@session.find(:css, '#openWindow').click
|
174
171
|
end
|
175
|
-
|
172
|
+
other_window.resize_to(400, 300)
|
176
173
|
sleep 0.5
|
177
|
-
|
174
|
+
other_window.maximize
|
178
175
|
sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur
|
179
176
|
|
180
|
-
expect(@session.current_window).to eq(
|
177
|
+
expect(@session.current_window).to eq(orig_window)
|
181
178
|
# Maximizing the browser affects all tabs so this may not be valid in real browsers
|
182
|
-
# expect(@session.current_window.size).to eq(
|
179
|
+
# expect(@session.current_window.size).to eq(initial_size)
|
183
180
|
|
184
|
-
ow_width, ow_height =
|
181
|
+
ow_width, ow_height = other_window.size
|
185
182
|
expect(ow_width).to be > 400
|
186
183
|
expect(ow_height).to be > 300
|
187
184
|
end
|
188
185
|
end
|
189
186
|
|
190
187
|
describe '#fullscreen' do
|
191
|
-
|
192
|
-
@
|
188
|
+
let! :initial_size do
|
189
|
+
@session.current_window.size
|
193
190
|
end
|
194
191
|
|
195
192
|
after do
|
196
|
-
@session.current_window.resize_to(
|
193
|
+
@session.current_window.resize_to(*initial_size)
|
197
194
|
sleep 1
|
198
195
|
end
|
199
196
|
|
@@ -1,6 +1,6 @@
|
|
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
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -29,6 +29,6 @@ Capybara::SpecHelper.spec '#windows', requires: [:windows] do
|
|
29
29
|
titles = @session.windows.map do |window|
|
30
30
|
@session.within_window(window) { @session.title }
|
31
31
|
end
|
32
|
-
expect(titles).to match_array(['With Windows', 'Title of the first popup', 'Title of popup two'])
|
32
|
+
expect(titles).to match_array(['With Windows', 'Title of the first popup', 'Title of popup two']) # rubocop:disable RSpec/MatchArray
|
33
33
|
end
|
34
34
|
end
|
@@ -26,6 +26,42 @@ Capybara::SpecHelper.spec '#within' do
|
|
26
26
|
end
|
27
27
|
expect(@session).to have_content('Bar')
|
28
28
|
end
|
29
|
+
|
30
|
+
it 'should reload the node if the page is changed' do
|
31
|
+
@session.within(:css, '#for_foo') do
|
32
|
+
@session.visit('/with_scope_other')
|
33
|
+
expect(@session).to have_content('Different text')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should reload multiple nodes if the page is changed' do
|
38
|
+
@session.within(:css, '#for_bar') do
|
39
|
+
@session.within(:css, 'form[action="/redirect"]') do
|
40
|
+
@session.refresh
|
41
|
+
expect(@session).to have_content('First Name')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should error if the page is changed and a matching node no longer exists' do
|
47
|
+
@session.within(:css, '#for_foo') do
|
48
|
+
@session.visit('/')
|
49
|
+
expect { @session.text }.to raise_error(StandardError)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should pass scope element to the block' do
|
54
|
+
@session.within(:css, '#another_foo') do |scope|
|
55
|
+
expect(scope).to match_css('#another_foo')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should scope click', requires: [:js] do
|
60
|
+
@session.within(:css, '#another_foo') do |scope|
|
61
|
+
@session.click
|
62
|
+
expect(scope).to have_text('I was clicked')
|
63
|
+
end
|
64
|
+
end
|
29
65
|
end
|
30
66
|
|
31
67
|
context 'with XPath selector' do
|
@@ -24,18 +24,21 @@ module Capybara
|
|
24
24
|
Capybara.app_host = nil
|
25
25
|
Capybara.default_selector = :xpath
|
26
26
|
Capybara.default_max_wait_time = 1
|
27
|
+
Capybara.default_retry_interval = 0.01
|
27
28
|
Capybara.ignore_hidden_elements = true
|
28
29
|
Capybara.exact = false
|
29
30
|
Capybara.raise_server_errors = true
|
30
31
|
Capybara.visible_text_only = false
|
31
32
|
Capybara.match = :smart
|
32
33
|
Capybara.enable_aria_label = false
|
34
|
+
Capybara.enable_aria_role = false
|
33
35
|
Capybara.default_set_options = {}
|
34
36
|
Capybara.disable_animation = false
|
35
37
|
Capybara.test_id = nil
|
36
38
|
Capybara.predicates_wait = true
|
37
39
|
Capybara.default_normalize_ws = false
|
38
|
-
Capybara.
|
40
|
+
Capybara.use_html5_parsing = !ENV['HTML5_PARSING'].nil?
|
41
|
+
Capybara.w3c_click_offset = true
|
39
42
|
reset_threadsafe
|
40
43
|
end
|
41
44
|
|
@@ -56,10 +59,10 @@ module Capybara
|
|
56
59
|
|
57
60
|
def run_specs(session, name, **options, &filter_block)
|
58
61
|
specs = @specs
|
59
|
-
RSpec.describe Capybara::Session, name, options do
|
62
|
+
RSpec.describe Capybara::Session, name, options do
|
60
63
|
include Capybara::SpecHelper
|
61
64
|
include Capybara::RSpecMatchers
|
62
|
-
|
65
|
+
|
63
66
|
before do |example|
|
64
67
|
@session = session
|
65
68
|
instance_exec(example, &filter_block) if filter_block
|
@@ -69,29 +72,29 @@ module Capybara
|
|
69
72
|
session.reset_session!
|
70
73
|
end
|
71
74
|
|
72
|
-
before :each, psc
|
73
|
-
SpecHelper.reset_threadsafe(true, session)
|
75
|
+
before :each, :psc do
|
76
|
+
SpecHelper.reset_threadsafe(bool: true, session: session)
|
74
77
|
end
|
75
78
|
|
76
79
|
after psc: true do
|
77
|
-
SpecHelper.reset_threadsafe(
|
80
|
+
SpecHelper.reset_threadsafe(session: session)
|
78
81
|
end
|
79
82
|
|
80
83
|
before :each, :exact_false do
|
81
84
|
Capybara.exact = false
|
82
85
|
end
|
83
|
-
# rubocop:enable RSpec/ScatteredSetup
|
84
86
|
|
85
87
|
specs.each do |spec_name, spec_options, block|
|
86
|
-
describe spec_name, *spec_options do
|
88
|
+
describe spec_name, *spec_options do
|
87
89
|
class_eval(&block)
|
88
90
|
end
|
89
91
|
end
|
90
92
|
end
|
91
93
|
end
|
92
94
|
|
93
|
-
def reset_threadsafe(bool
|
94
|
-
|
95
|
+
def reset_threadsafe(bool: false, session: nil)
|
96
|
+
# Work around limit on when threadsafe can be changed
|
97
|
+
Capybara::Session.class_variable_set(:@@instance_created, false) # rubocop:disable Style/ClassVars
|
95
98
|
Capybara.threadsafe = bool
|
96
99
|
session = session.current_session if session.respond_to?(:current_session)
|
97
100
|
session&.instance_variable_set(:@config, nil)
|
@@ -100,31 +103,39 @@ module Capybara
|
|
100
103
|
|
101
104
|
def silence_stream(stream)
|
102
105
|
old_stream = stream.dup
|
103
|
-
stream.reopen(RbConfig::CONFIG['host_os']
|
106
|
+
stream.reopen(RbConfig::CONFIG['host_os'].match?(/rmswin|mingw/) ? 'NUL:' : '/dev/null')
|
104
107
|
stream.sync = true
|
105
108
|
yield
|
106
109
|
ensure
|
107
110
|
stream.reopen(old_stream)
|
108
111
|
end
|
109
112
|
|
110
|
-
def quietly
|
111
|
-
silence_stream(
|
112
|
-
silence_stream(
|
113
|
-
yield
|
114
|
-
end
|
113
|
+
def quietly(&block)
|
114
|
+
silence_stream($stdout) do
|
115
|
+
silence_stream($stderr, &block)
|
115
116
|
end
|
116
117
|
end
|
117
118
|
|
118
119
|
def extract_results(session)
|
119
120
|
expect(session).to have_xpath("//pre[@id='results']")
|
120
|
-
|
121
|
-
|
121
|
+
perms = [(::Sinatra::IndifferentHash if defined? ::Sinatra::IndifferentHash)].compact
|
122
|
+
results = Capybara::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
|
123
|
+
YAML.safe_load results, permitted_classes: perms
|
124
|
+
end
|
125
|
+
|
126
|
+
def extract_content_type(session)
|
127
|
+
expect(session).to have_xpath("//pre[@id='content_type']")
|
128
|
+
Capybara::HTML(session.body).xpath("//pre[@id='content_type']").first.text
|
122
129
|
end
|
123
130
|
|
124
131
|
def be_an_invalid_element_error(session)
|
125
132
|
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
126
133
|
end
|
134
|
+
|
135
|
+
def with_os_path_separators(path)
|
136
|
+
Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s
|
137
|
+
end
|
127
138
|
end
|
128
139
|
end
|
129
140
|
|
130
|
-
Dir[File.dirname(__FILE__)
|
141
|
+
Dir["#{File.dirname(__FILE__)}/session/**/*.rb"].each { |file| require_relative file }
|
@@ -6,9 +6,11 @@ require 'rack'
|
|
6
6
|
require 'yaml'
|
7
7
|
|
8
8
|
class TestApp < Sinatra::Base
|
9
|
-
class TestAppError <
|
10
|
-
|
9
|
+
class TestAppError < Exception; end # rubocop:disable Lint/InheritException
|
10
|
+
|
11
|
+
class TestAppOtherError < Exception # rubocop:disable Lint/InheritException
|
11
12
|
def initialize(string1, msg)
|
13
|
+
super()
|
12
14
|
@something = string1
|
13
15
|
@message = msg
|
14
16
|
end
|
@@ -18,7 +20,6 @@ class TestApp < Sinatra::Base
|
|
18
20
|
set :raise_errors, true
|
19
21
|
set :show_exceptions, false
|
20
22
|
|
21
|
-
@@form_post_count = 0
|
22
23
|
# Also check lib/capybara/spec/views/*.erb for pages not listed here
|
23
24
|
|
24
25
|
get '/' do
|
@@ -34,6 +35,10 @@ class TestApp < Sinatra::Base
|
|
34
35
|
redirect '/redirect_again'
|
35
36
|
end
|
36
37
|
|
38
|
+
get '/redirect_with_fragment' do
|
39
|
+
redirect '/landed#with_fragment'
|
40
|
+
end
|
41
|
+
|
37
42
|
get '/redirect_again' do
|
38
43
|
redirect '/landed'
|
39
44
|
end
|
@@ -48,8 +53,8 @@ class TestApp < Sinatra::Base
|
|
48
53
|
|
49
54
|
get '/referer_base' do
|
50
55
|
'<a href="/get_referer">direct link</a>' \
|
51
|
-
|
52
|
-
|
56
|
+
'<a href="/redirect_to_get_referer">link via redirect</a>' \
|
57
|
+
'<form action="/get_referer" method="get"><input type="submit"></form>'
|
53
58
|
end
|
54
59
|
|
55
60
|
get '/redirect_to_get_referer' do
|
@@ -86,11 +91,11 @@ class TestApp < Sinatra::Base
|
|
86
91
|
end
|
87
92
|
|
88
93
|
get '/form/get' do
|
89
|
-
|
94
|
+
%(<pre id="results">#{params[:form].to_yaml}</pre>)
|
90
95
|
end
|
91
96
|
|
92
97
|
post '/relative' do
|
93
|
-
|
98
|
+
%(<pre id="results">#{params[:form].to_yaml}</pre>)
|
94
99
|
end
|
95
100
|
|
96
101
|
get '/favicon.ico' do
|
@@ -158,60 +163,143 @@ class TestApp < Sinatra::Base
|
|
158
163
|
|
159
164
|
get '/with_title' do
|
160
165
|
<<-HTML
|
161
|
-
|
162
|
-
<
|
163
|
-
<
|
164
|
-
|
166
|
+
<!DOCTYPE html>
|
167
|
+
<html lang="en">
|
168
|
+
<head>
|
169
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
170
|
+
<title>#{params[:title] || 'Test Title'}</title>
|
171
|
+
</head>
|
172
|
+
|
173
|
+
<body>
|
174
|
+
<svg><title>abcdefg</title></svg>
|
175
|
+
</body>
|
176
|
+
</html>
|
177
|
+
HTML
|
178
|
+
end
|
179
|
+
|
180
|
+
get '/with_iframe' do
|
181
|
+
<<-HTML
|
182
|
+
<!DOCTYPE html>
|
183
|
+
<html lang="en">
|
184
|
+
<head>
|
185
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
186
|
+
<title>Test with Iframe</title>
|
187
|
+
</head>
|
188
|
+
|
189
|
+
<body>
|
190
|
+
<iframe src="#{params[:url]}" id="#{params[:id]}"></iframe>
|
191
|
+
</body>
|
192
|
+
</html>
|
193
|
+
HTML
|
194
|
+
end
|
195
|
+
|
196
|
+
get '/base/with_base' do
|
197
|
+
<<-HTML
|
198
|
+
<!DOCTYPE html>
|
199
|
+
<html>
|
200
|
+
<head>
|
201
|
+
<base href="/">
|
202
|
+
<title>Origin</title>
|
203
|
+
</head>
|
204
|
+
<body>
|
205
|
+
<a href="with_title">Title page</a>
|
206
|
+
<a href="?a=3">Bare query</a>
|
207
|
+
</body>
|
208
|
+
</html>
|
209
|
+
HTML
|
210
|
+
end
|
211
|
+
|
212
|
+
get '/base/with_other_base' do
|
213
|
+
<<-HTML
|
214
|
+
<!DOCTYPE html>
|
215
|
+
<html>
|
216
|
+
<head>
|
217
|
+
<base href="/base/">
|
218
|
+
<title>Origin</title>
|
219
|
+
</head>
|
220
|
+
<body>
|
221
|
+
<a href="with_title">Title page</a>
|
222
|
+
<a href="?a=3">Bare query</a>
|
223
|
+
</body>
|
224
|
+
</html>
|
225
|
+
HTML
|
226
|
+
end
|
227
|
+
|
228
|
+
get '/csp' do
|
229
|
+
response.headers['Content-Security-Policy'] = "default-src 'none'; connect-src 'self'; base-uri 'none'; font-src 'self'; img-src 'self' data:; object-src 'none'; script-src 'self' 'nonce-jAviMuMisoTisVXjgLoWdA=='; style-src 'self' 'nonce-jAviMuMisoTisVXjgLoWdA=='; form-action 'self';"
|
230
|
+
<<-HTML
|
231
|
+
<!DOCTYPE html>
|
232
|
+
<html lang="en">
|
233
|
+
<head>
|
234
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
235
|
+
<title>CSP</title>
|
236
|
+
</head>
|
237
|
+
|
238
|
+
<body>
|
239
|
+
<div>CSP</div>
|
240
|
+
</body>
|
241
|
+
</html>
|
165
242
|
HTML
|
166
243
|
end
|
167
244
|
|
168
245
|
get '/download.csv' do
|
169
246
|
content_type 'text/csv'
|
170
247
|
'This, is, comma, separated' \
|
171
|
-
|
248
|
+
'Thomas, Walpole, was , here'
|
249
|
+
end
|
250
|
+
|
251
|
+
get %r{/apple-touch-.*\.png/} do
|
252
|
+
halt(404)
|
172
253
|
end
|
173
254
|
|
174
255
|
get '/:view' do |view|
|
175
|
-
|
256
|
+
view_template = "#{__dir__}/views/#{view}.erb"
|
257
|
+
has_layout = File.exist?(view_template) && File.open(view_template) { |f| f.first.downcase.include?('doctype') }
|
258
|
+
erb view.to_sym, locals: { referrer: request.referrer }, layout: !has_layout
|
176
259
|
end
|
177
260
|
|
178
261
|
post '/form' do
|
179
|
-
|
180
|
-
|
262
|
+
self.class.form_post_count += 1
|
263
|
+
%(
|
264
|
+
<pre id="content_type">#{request.content_type}</pre>
|
265
|
+
<pre id="results">#{params.fetch(:form, {}).merge('post_count' => self.class.form_post_count).to_yaml}</pre>
|
266
|
+
)
|
181
267
|
end
|
182
268
|
|
183
269
|
post '/upload_empty' do
|
184
270
|
if params[:form][:file].nil?
|
185
|
-
|
271
|
+
"Successfully ignored empty file field. Content type was #{request.content_type}"
|
186
272
|
else
|
187
273
|
'Something went wrong.'
|
188
274
|
end
|
189
275
|
end
|
190
276
|
|
191
277
|
post '/upload' do
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
'No file uploaded'
|
199
|
-
end
|
278
|
+
buffer = []
|
279
|
+
buffer << "Content-type: #{params.dig(:form, :document, :type)}"
|
280
|
+
buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
|
281
|
+
buffer.join(' | ')
|
282
|
+
rescue StandardError
|
283
|
+
'No file uploaded'
|
200
284
|
end
|
201
285
|
|
202
286
|
post '/upload_multiple' do
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
buffer << "File content: #{doc[:tempfile].read}"
|
209
|
-
end
|
210
|
-
buffer.join(' | ')
|
211
|
-
rescue StandardError
|
212
|
-
'No files uploaded'
|
287
|
+
docs = params.dig(:form, :multiple_documents)
|
288
|
+
buffer = [docs.size.to_s]
|
289
|
+
docs.each do |doc|
|
290
|
+
buffer << "Content-type: #{doc[:type]}"
|
291
|
+
buffer << "File content: #{doc[:tempfile].read}"
|
213
292
|
end
|
293
|
+
buffer.join(' | ')
|
294
|
+
rescue StandardError
|
295
|
+
'No files uploaded'
|
214
296
|
end
|
297
|
+
|
298
|
+
class << self
|
299
|
+
attr_accessor :form_post_count
|
300
|
+
end
|
301
|
+
|
302
|
+
@form_post_count = 0
|
215
303
|
end
|
216
304
|
|
217
305
|
Rack::Handler::Puma.run TestApp, Port: 8070 if $PROGRAM_NAME == __FILE__
|