capybara 3.29.0 → 3.33.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +91 -1
- data/README.md +10 -3
- data/lib/capybara.rb +17 -7
- data/lib/capybara/config.rb +7 -3
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/dsl.rb +10 -2
- data/lib/capybara/helpers.rb +3 -1
- data/lib/capybara/minitest.rb +232 -144
- data/lib/capybara/minitest/spec.rb +153 -97
- data/lib/capybara/node/actions.rb +35 -35
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +23 -16
- data/lib/capybara/node/finders.rb +17 -11
- data/lib/capybara/node/matchers.rb +64 -51
- data/lib/capybara/node/simple.rb +4 -2
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/base_query.rb +2 -1
- data/lib/capybara/queries/selector_query.rb +25 -5
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +6 -0
- data/lib/capybara/rack_test/browser.rb +7 -2
- data/lib/capybara/rack_test/driver.rb +1 -1
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +34 -9
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/servers.rb +1 -1
- data/lib/capybara/result.rb +29 -5
- data/lib/capybara/rspec/matcher_proxies.rb +4 -4
- data/lib/capybara/rspec/matchers.rb +27 -27
- data/lib/capybara/rspec/matchers/base.rb +12 -6
- data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
- data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +15 -7
- data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
- data/lib/capybara/rspec/matchers/have_text.rb +3 -3
- 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 +2 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
- data/lib/capybara/selector.rb +34 -17
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition.rb +7 -6
- data/lib/capybara/selector/definition/button.rb +8 -2
- data/lib/capybara/selector/definition/checkbox.rb +2 -2
- data/lib/capybara/selector/definition/css.rb +3 -1
- data/lib/capybara/selector/definition/datalist_input.rb +1 -1
- data/lib/capybara/selector/definition/datalist_option.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +1 -1
- data/lib/capybara/selector/definition/field.rb +1 -1
- data/lib/capybara/selector/definition/file_field.rb +1 -1
- data/lib/capybara/selector/definition/fillable_field.rb +2 -2
- data/lib/capybara/selector/definition/label.rb +4 -2
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/radio_button.rb +2 -2
- data/lib/capybara/selector/definition/select.rb +32 -13
- data/lib/capybara/selector/definition/table.rb +6 -3
- data/lib/capybara/selector/filter_set.rb +11 -9
- data/lib/capybara/selector/filters/base.rb +6 -1
- data/lib/capybara/selector/filters/locator_filter.rb +1 -1
- data/lib/capybara/selector/selector.rb +8 -2
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
- data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
- data/lib/capybara/selenium/driver.rb +22 -11
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +8 -10
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +7 -9
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
- data/lib/capybara/selenium/extensions/html5_drag.rb +30 -13
- data/lib/capybara/selenium/node.rb +97 -18
- data/lib/capybara/selenium/nodes/chrome_node.rb +11 -14
- data/lib/capybara/selenium/nodes/edge_node.rb +4 -2
- data/lib/capybara/selenium/nodes/firefox_node.rb +4 -4
- data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
- data/lib/capybara/selenium/patches/logs.rb +3 -5
- data/lib/capybara/server.rb +15 -3
- data/lib/capybara/server/checker.rb +1 -1
- data/lib/capybara/server/middleware.rb +20 -10
- data/lib/capybara/session.rb +43 -26
- data/lib/capybara/session/config.rb +9 -3
- data/lib/capybara/session/matchers.rb +6 -6
- data/lib/capybara/spec/public/test.js +69 -6
- data/lib/capybara/spec/session/all_spec.rb +60 -5
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
- data/lib/capybara/spec/session/click_button_spec.rb +16 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +29 -0
- data/lib/capybara/spec/session/find_spec.rb +31 -8
- data/lib/capybara/spec/session/has_button_spec.rb +16 -0
- data/lib/capybara/spec/session/has_css_spec.rb +12 -9
- data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
- data/lib/capybara/spec/session/has_field_spec.rb +16 -0
- data/lib/capybara/spec/session/has_select_spec.rb +32 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
- data/lib/capybara/spec/session/has_table_spec.rb +51 -5
- data/lib/capybara/spec/session/has_text_spec.rb +35 -0
- data/lib/capybara/spec/session/node_spec.rb +160 -29
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/selectors_spec.rb +15 -2
- data/lib/capybara/spec/session/window/window_spec.rb +7 -7
- data/lib/capybara/spec/spec_helper.rb +2 -2
- data/lib/capybara/spec/test_app.rb +14 -18
- data/lib/capybara/spec/views/form.erb +18 -2
- data/lib/capybara/spec/views/with_dragula.erb +3 -1
- data/lib/capybara/spec/views/with_html.erb +2 -2
- data/lib/capybara/spec/views/with_js.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/capybara_spec.rb +1 -1
- data/spec/dsl_spec.rb +16 -3
- data/spec/minitest_spec.rb +1 -1
- data/spec/minitest_spec_spec.rb +46 -46
- data/spec/rack_test_spec.rb +13 -1
- data/spec/regexp_dissassembler_spec.rb +40 -36
- data/spec/result_spec.rb +43 -32
- data/spec/rspec/features_spec.rb +1 -0
- data/spec/rspec/shared_spec_matchers.rb +68 -56
- data/spec/rspec_spec.rb +4 -4
- data/spec/selector_spec.rb +1 -1
- data/spec/selenium_spec_chrome.rb +9 -6
- data/spec/selenium_spec_chrome_remote.rb +2 -0
- data/spec/selenium_spec_firefox.rb +7 -2
- data/spec/server_spec.rb +65 -31
- data/spec/session_spec.rb +1 -1
- data/spec/shared_selenium_node.rb +21 -3
- data/spec/shared_selenium_session.rb +33 -14
- data/spec/spec_helper.rb +1 -1
- metadata +6 -4
@@ -39,6 +39,14 @@ Capybara::SpecHelper.spec '#has_button?' do
|
|
39
39
|
expect(@session).to have_button('awe123', type: 'submit')
|
40
40
|
expect(@session).not_to have_button('awe123', type: 'reset')
|
41
41
|
end
|
42
|
+
|
43
|
+
it 'should be true for role=button when enable_aria_role: true' do
|
44
|
+
expect(@session).to have_button('ARIA button', enable_aria_role: true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should be false for role=button when enable_aria_role: false' do
|
48
|
+
expect(@session).not_to have_button('ARIA button', enable_aria_role: false)
|
49
|
+
end
|
42
50
|
end
|
43
51
|
|
44
52
|
Capybara::SpecHelper.spec '#has_no_button?' do
|
@@ -66,4 +74,12 @@ Capybara::SpecHelper.spec '#has_no_button?' do
|
|
66
74
|
it 'should be false for disabled buttons if disabled: false' do
|
67
75
|
expect(@session).to have_no_button('Disabled button', disabled: false)
|
68
76
|
end
|
77
|
+
|
78
|
+
it 'should be true for role=button when enable_aria_role: false' do
|
79
|
+
expect(@session).to have_no_button('ARIA button', enable_aria_role: false)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should be false for role=button when enable_aria_role: true' do
|
83
|
+
expect(@session).not_to have_no_button('ARIA button', enable_aria_role: true)
|
84
|
+
end
|
69
85
|
end
|
@@ -185,10 +185,10 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
185
185
|
end
|
186
186
|
|
187
187
|
it 'should be false when content occurs more times than given' do
|
188
|
-
expect(@session).not_to have_css('h2.head', maximum: 4) # edge case
|
189
|
-
expect(@session).not_to have_css('h2', maximum: 3)
|
188
|
+
# expect(@session).not_to have_css('h2.head', maximum: 4) # edge case
|
189
|
+
# expect(@session).not_to have_css('h2', maximum: 3)
|
190
190
|
expect(@session).not_to have_css('h2').at_most(3).times
|
191
|
-
expect(@session).not_to have_css('p', maximum: 1)
|
191
|
+
# expect(@session).not_to have_css('p', maximum: 1)
|
192
192
|
end
|
193
193
|
|
194
194
|
it 'should coerce maximum to an integer' do
|
@@ -234,18 +234,21 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
234
234
|
context 'with spatial requirements', requires: [:spatial] do
|
235
235
|
before do
|
236
236
|
@session.visit('/spatial')
|
237
|
-
|
237
|
+
end
|
238
|
+
|
239
|
+
let :center do
|
240
|
+
@session.find(:css, '.center')
|
238
241
|
end
|
239
242
|
|
240
243
|
it 'accepts spatial options' do
|
241
|
-
expect(@session).to have_css('div', above:
|
242
|
-
expect(@session).to have_css('div', above:
|
244
|
+
expect(@session).to have_css('div', above: center).thrice
|
245
|
+
expect(@session).to have_css('div', above: center, right_of: center).once
|
243
246
|
end
|
244
247
|
|
245
248
|
it 'supports spatial sugar' do
|
246
|
-
expect(@session).to have_css('div').left_of(
|
247
|
-
expect(@session).to have_css('div').below(
|
248
|
-
expect(@session).to have_css('div').near(
|
249
|
+
expect(@session).to have_css('div').left_of(center).thrice
|
250
|
+
expect(@session).to have_css('div').below(center).right_of(center).once
|
251
|
+
expect(@session).to have_css('div').near(center).exactly(8).times
|
249
252
|
end
|
250
253
|
end
|
251
254
|
|
@@ -128,11 +128,11 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
|
|
128
128
|
# Without ignore_query option
|
129
129
|
expect do
|
130
130
|
expect(@session).not_to have_current_path('/with_js')
|
131
|
-
end.
|
131
|
+
end.not_to raise_exception
|
132
132
|
|
133
133
|
# With ignore_query option
|
134
134
|
expect do
|
135
135
|
expect(@session).not_to have_current_path('/with_js', ignore_query: true)
|
136
|
-
end.
|
136
|
+
end.not_to raise_exception
|
137
137
|
end
|
138
138
|
end
|
@@ -60,6 +60,22 @@ Capybara::SpecHelper.spec '#has_field' do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
context 'with validation message', requires: [:html_validation] do
|
64
|
+
it 'should accept a regexp' do
|
65
|
+
@session.fill_in('form_zipcode', with: '1234')
|
66
|
+
expect(@session).to have_field('form_zipcode', validation_message: /match the requested format/)
|
67
|
+
expect(@session).not_to have_field('form_zipcode', validation_message: /random/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should accept a string' do
|
71
|
+
@session.fill_in('form_zipcode', with: '1234')
|
72
|
+
expect(@session).to have_field('form_zipcode', validation_message: 'Please match the requested format.')
|
73
|
+
expect(@session).not_to have_field('form_zipcode', validation_message: 'match the requested format.')
|
74
|
+
@session.fill_in('form_zipcode', with: '12345')
|
75
|
+
expect(@session).to have_field('form_zipcode', validation_message: '')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
63
79
|
context 'with type' do
|
64
80
|
it 'should be true if a field with the given type is on the page' do
|
65
81
|
expect(@session).to have_field('First Name', type: 'text')
|
@@ -63,7 +63,7 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should be true even when the selected option invisible, regardless of the select's visibility" do
|
66
|
-
expect(@session).to have_select('Icecream', visible:
|
66
|
+
expect(@session).to have_select('Icecream', visible: :hidden, selected: 'Chocolate')
|
67
67
|
expect(@session).to have_select('Sorbet', selected: 'Vanilla')
|
68
68
|
end
|
69
69
|
end
|
@@ -88,7 +88,7 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
it "should be true even when the selected values are invisible, regardless of the select's visibility" do
|
91
|
-
expect(@session).to have_select('Dessert', visible:
|
91
|
+
expect(@session).to have_select('Dessert', visible: :hidden, with_options: %w[Pudding Tiramisu])
|
92
92
|
expect(@session).to have_select('Cake', with_selected: ['Chocolate Cake', 'Sponge Cake'])
|
93
93
|
end
|
94
94
|
|
@@ -113,7 +113,35 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'should be true even when the options are invisible, if the select itself is invisible' do
|
116
|
-
expect(@session).to have_select('Icecream', visible:
|
116
|
+
expect(@session).to have_select('Icecream', visible: :hidden, options: %w[Chocolate Vanilla Strawberry])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with enabled options' do
|
121
|
+
it 'should be true if the listed options exist and are enabled' do
|
122
|
+
expect(@session).to have_select('form_title', enabled_options: %w[Mr Mrs Miss])
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should be false if the listed options do not exist' do
|
126
|
+
expect(@session).not_to have_select('form_title', enabled_options: ['Not there'])
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should be false if the listed option exists but is not enabled' do
|
130
|
+
expect(@session).not_to have_select('form_title', enabled_options: %w[Mr Mrs Miss Other])
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'with disabled options' do
|
135
|
+
it 'should be true if the listed options exist and are disabled' do
|
136
|
+
expect(@session).to have_select('form_title', disabled_options: ['Other'])
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should be false if the listed options do not exist' do
|
140
|
+
expect(@session).not_to have_select('form_title', disabled_options: ['Not there'])
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should be false if the listed option exists but is not disabled' do
|
144
|
+
expect(@session).not_to have_select('form_title', disabled_options: %w[Other Mrs])
|
117
145
|
end
|
118
146
|
end
|
119
147
|
|
@@ -130,7 +158,7 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
130
158
|
end
|
131
159
|
|
132
160
|
it 'should be true even when the options are invisible, if the select itself is invisible' do
|
133
|
-
expect(@session).to have_select('Icecream', visible:
|
161
|
+
expect(@session).to have_select('Icecream', visible: :hidden, with_options: %w[Vanilla Strawberry])
|
134
162
|
end
|
135
163
|
end
|
136
164
|
|
@@ -61,12 +61,12 @@ Capybara::SpecHelper.spec '#has_selector?' do
|
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'should respect visibility setting' do
|
64
|
-
expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible:
|
65
|
-
expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible:
|
64
|
+
expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
|
65
|
+
expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
|
66
66
|
Capybara.ignore_hidden_elements = false
|
67
|
-
expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible:
|
67
|
+
expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
|
68
68
|
Capybara.visible_text_only = true
|
69
|
-
expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible:
|
69
|
+
expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'should discard all matches where the given regexp is not matched' do
|
@@ -143,10 +143,56 @@ Capybara::SpecHelper.spec '#has_no_table?' do
|
|
143
143
|
])
|
144
144
|
end
|
145
145
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
146
|
+
context 'using :with_cols' do
|
147
|
+
it 'should consider a single column' do
|
148
|
+
expect(@session).to have_no_table('Vertical Headers', with_cols:
|
149
|
+
[
|
150
|
+
{ 'First Name' => 'Joe' }
|
151
|
+
])
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should be true even if the last column does exist' do
|
155
|
+
expect(@session).to have_no_table('Vertical Headers', with_cols:
|
156
|
+
[
|
157
|
+
{
|
158
|
+
'First Name' => 'What?',
|
159
|
+
'What?' => 'Walpole',
|
160
|
+
'City' => 'Oceanside' # This line makes the example fail
|
161
|
+
}
|
162
|
+
])
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should be true if none of the columns exist' do
|
166
|
+
expect(@session).to have_no_table('Vertical Headers', with_cols:
|
167
|
+
[
|
168
|
+
{
|
169
|
+
'First Name' => 'What?',
|
170
|
+
'What?' => 'Walpole',
|
171
|
+
'City' => 'What?'
|
172
|
+
}
|
173
|
+
])
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should be true if the first column does match' do
|
177
|
+
expect(@session).to have_no_table('Vertical Headers', with_cols:
|
178
|
+
[
|
179
|
+
{
|
180
|
+
'First Name' => 'Thomas',
|
181
|
+
'Last Name' => 'What',
|
182
|
+
'City' => 'What'
|
183
|
+
}
|
184
|
+
])
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should be true if none of the columns match' do
|
188
|
+
expect(@session).to have_no_table('Vertical Headers', with_cols:
|
189
|
+
[
|
190
|
+
{
|
191
|
+
'First Name' => 'What',
|
192
|
+
'Last Name' => 'What',
|
193
|
+
'City' => 'What'
|
194
|
+
}
|
195
|
+
])
|
196
|
+
end
|
151
197
|
end
|
152
198
|
end
|
@@ -111,6 +111,41 @@ Capybara::SpecHelper.spec '#has_text?' do
|
|
111
111
|
expect(@session).not_to have_text(/xxxxyzzz/)
|
112
112
|
end
|
113
113
|
|
114
|
+
context 'with object implementing to_s and to_hash' do
|
115
|
+
it 'should work if the object is passed alone' do
|
116
|
+
with_to_hash = Class.new do
|
117
|
+
def to_s; '42' end
|
118
|
+
def to_hash; { value: 'Other hash' } end
|
119
|
+
end.new
|
120
|
+
@session.visit('/with_html')
|
121
|
+
expect(@session).to have_text(with_to_hash)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should work if passed with empty options' do
|
125
|
+
with_to_hash = Class.new do
|
126
|
+
def to_s; '42' end
|
127
|
+
def to_hash; { value: 'Other hash' } end
|
128
|
+
end.new
|
129
|
+
@session.visit('/with_html')
|
130
|
+
if RUBY_VERSION >= '2.7'
|
131
|
+
expect(@session).to have_text(:visible, with_to_hash, **{})
|
132
|
+
else
|
133
|
+
expect(@session).to have_text(:visible, with_to_hash, {})
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should fail if passed without empty options' do
|
138
|
+
with_to_hash = Class.new do
|
139
|
+
def to_s; '42' end
|
140
|
+
def to_hash; { blah: 'Other hash' } end
|
141
|
+
end.new
|
142
|
+
@session.visit('/with_html')
|
143
|
+
expect do
|
144
|
+
expect(@session).to have_text(:visible, with_to_hash)
|
145
|
+
end.to raise_error(ArgumentError)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
114
149
|
context 'with exact: true option' do
|
115
150
|
it 'should be true if text matches exactly' do
|
116
151
|
@session.visit('/with_html')
|
@@ -270,13 +270,13 @@ Capybara::SpecHelper.spec 'node' do
|
|
270
270
|
end
|
271
271
|
|
272
272
|
it 'works when details is toggled open and closed' do
|
273
|
-
@session.find(:css, '#closed_details').click
|
274
|
-
expect(@session).to have_css('#closed_details *', visible:
|
273
|
+
@session.find(:css, '#closed_details > summary').click
|
274
|
+
expect(@session).to have_css('#closed_details *', visible: :visible, count: 5)
|
275
275
|
.and(have_no_css('#closed_details *', visible: :hidden))
|
276
276
|
|
277
|
-
@session.find(:css, '#closed_details').click
|
277
|
+
@session.find(:css, '#closed_details > summary').click
|
278
278
|
descendants_css = '#closed_details > *:not(summary), #closed_details > *:not(summary) *'
|
279
|
-
expect(@session).to have_no_css(descendants_css, visible:
|
279
|
+
expect(@session).to have_no_css(descendants_css, visible: :visible)
|
280
280
|
.and(have_css(descendants_css, visible: :hidden, count: 3))
|
281
281
|
end
|
282
282
|
end
|
@@ -446,7 +446,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
446
446
|
|
447
447
|
it 'should work with Dragula' do
|
448
448
|
@session.visit('/with_dragula')
|
449
|
-
@session.within(:css, '#sortable') do
|
449
|
+
@session.within(:css, '#sortable.ready') do
|
450
450
|
src = @session.find('div', text: 'Item 1')
|
451
451
|
target = @session.find('div', text: 'Item 3')
|
452
452
|
src.drag_to target
|
@@ -468,6 +468,50 @@ Capybara::SpecHelper.spec 'node' do
|
|
468
468
|
end
|
469
469
|
end
|
470
470
|
|
471
|
+
it 'should simulate a single held down modifier key' do
|
472
|
+
%I[
|
473
|
+
alt
|
474
|
+
ctrl
|
475
|
+
meta
|
476
|
+
shift
|
477
|
+
].each do |modifier_key|
|
478
|
+
@session.visit('/with_js')
|
479
|
+
|
480
|
+
element = @session.find('//div[@id="drag"]')
|
481
|
+
target = @session.find('//div[@id="drop"]')
|
482
|
+
|
483
|
+
element.drag_to(target, drop_modifiers: modifier_key)
|
484
|
+
expect(@session).to have_css('div.drag_start', exact_text: 'Dragged!')
|
485
|
+
expect(@session).to have_xpath("//div[contains(., 'Dropped!-#{modifier_key}')]")
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
it 'should simulate multiple held down modifier keys' do
|
490
|
+
@session.visit('/with_js')
|
491
|
+
|
492
|
+
element = @session.find('//div[@id="drag"]')
|
493
|
+
target = @session.find('//div[@id="drop"]')
|
494
|
+
|
495
|
+
modifier_keys = %I[alt ctrl meta shift]
|
496
|
+
|
497
|
+
element.drag_to(target, drop_modifiers: modifier_keys)
|
498
|
+
expect(@session).to have_xpath("//div[contains(., 'Dropped!-#{modifier_keys.join('-')}')]")
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'should support key aliases' do
|
502
|
+
{ control: :ctrl,
|
503
|
+
command: :meta,
|
504
|
+
cmd: :meta }.each do |(key_alias, key)|
|
505
|
+
@session.visit('/with_js')
|
506
|
+
|
507
|
+
element = @session.find('//div[@id="drag"]')
|
508
|
+
target = @session.find('//div[@id="drop"]')
|
509
|
+
|
510
|
+
element.drag_to(target, drop_modifiers: [key_alias])
|
511
|
+
expect(target).to have_text("Dropped!-#{key}", exact: true)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
471
515
|
context 'HTML5', requires: %i[js html5_drag] do
|
472
516
|
it 'should HTML5 drag and drop an object' do
|
473
517
|
@session.visit('/with_js')
|
@@ -493,6 +537,26 @@ Capybara::SpecHelper.spec 'node' do
|
|
493
537
|
expect(@session).to have_css('div.log', text: /DragOver with client position: [1-9]\d*,[1-9]\d*/, count: 2)
|
494
538
|
end
|
495
539
|
|
540
|
+
it 'should preserve clientX/Y from last dragover event' do
|
541
|
+
@session.visit('/with_js')
|
542
|
+
element = @session.find('//div[@id="drag_html5"]')
|
543
|
+
target = @session.find('//div[@id="drop_html5"]')
|
544
|
+
element.drag_to(target)
|
545
|
+
|
546
|
+
conditions = %w[DragLeave Drop DragEnd].map do |text|
|
547
|
+
have_css('div.log', text: text)
|
548
|
+
end
|
549
|
+
expect(@session).to(conditions.reduce { |memo, cond| memo.and(cond) })
|
550
|
+
|
551
|
+
# The first "DragOver" div is inserted by the last dragover event dispatched
|
552
|
+
drag_over_div = @session.first('//div[@class="log" and starts-with(text(), "DragOver")]')
|
553
|
+
position = drag_over_div.text.sub('DragOver ', '')
|
554
|
+
|
555
|
+
expect(@session).to have_css('div.log', text: /DragLeave #{position}/, count: 1)
|
556
|
+
expect(@session).to have_css('div.log', text: /Drop #{position}/, count: 1)
|
557
|
+
expect(@session).to have_css('div.log', text: /DragEnd #{position}/, count: 1)
|
558
|
+
end
|
559
|
+
|
496
560
|
it 'should not HTML5 drag and drop on a non HTML5 drop element' do
|
497
561
|
@session.visit('/with_js')
|
498
562
|
element = @session.find('//div[@id="drag_html5"]')
|
@@ -536,6 +600,46 @@ Capybara::SpecHelper.spec 'node' do
|
|
536
600
|
source.drag_to target
|
537
601
|
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped")]')
|
538
602
|
end
|
603
|
+
|
604
|
+
it 'should simulate a single held down modifier key' do
|
605
|
+
%I[alt ctrl meta shift].each do |modifier_key|
|
606
|
+
@session.visit('/with_js')
|
607
|
+
|
608
|
+
element = @session.find('//div[@id="drag_html5"]')
|
609
|
+
target = @session.find('//div[@id="drop_html5"]')
|
610
|
+
|
611
|
+
element.drag_to(target, drop_modifiers: modifier_key)
|
612
|
+
|
613
|
+
expect(@session).to have_css('div.drag_start', exact_text: 'HTML5 Dragged!')
|
614
|
+
expect(@session).to have_xpath("//div[contains(., 'HTML5 Dropped string: text/plain drag_html5-#{modifier_key}')]")
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
it 'should simulate multiple held down modifier keys' do
|
619
|
+
@session.visit('/with_js')
|
620
|
+
|
621
|
+
element = @session.find('//div[@id="drag_html5"]')
|
622
|
+
target = @session.find('//div[@id="drop_html5"]')
|
623
|
+
|
624
|
+
modifier_keys = %I[alt ctrl meta shift]
|
625
|
+
|
626
|
+
element.drag_to(target, drop_modifiers: modifier_keys)
|
627
|
+
expect(@session).to have_xpath("//div[contains(., 'HTML5 Dropped string: text/plain drag_html5-#{modifier_keys.join('-')}')]")
|
628
|
+
end
|
629
|
+
|
630
|
+
it 'should support key aliases' do
|
631
|
+
{ control: :ctrl,
|
632
|
+
command: :meta,
|
633
|
+
cmd: :meta }.each do |(key_alias, key)|
|
634
|
+
@session.visit('/with_js')
|
635
|
+
|
636
|
+
element = @session.find('//div[@id="drag_html5"]')
|
637
|
+
target = @session.find('//div[@id="drop_html5"]')
|
638
|
+
|
639
|
+
element.drag_to(target, drop_modifiers: [key_alias])
|
640
|
+
expect(target).to have_text(%r{^HTML5 Dropped string: text/plain drag_html5-#{key}$}m, exact: true)
|
641
|
+
end
|
642
|
+
end
|
539
643
|
end
|
540
644
|
end
|
541
645
|
|
@@ -654,7 +758,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
654
758
|
@session.visit('with_js')
|
655
759
|
@session.find(:css, '#click-test').click(x: 5, y: 5)
|
656
760
|
link = @session.find(:link, 'has-been-clicked')
|
657
|
-
locations = link.text.match(/^Has been clicked at (?<x>[\d
|
761
|
+
locations = link.text.match(/^Has been clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
658
762
|
# 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
|
659
763
|
# integer/float conversions and rounding.
|
660
764
|
expect(locations[:x].to_f).to be_within(1).of(5)
|
@@ -704,7 +808,10 @@ Capybara::SpecHelper.spec 'node' do
|
|
704
808
|
context 'offset', requires: [:js] do
|
705
809
|
before do
|
706
810
|
@session.visit('/offset')
|
707
|
-
|
811
|
+
end
|
812
|
+
|
813
|
+
let :clicker do
|
814
|
+
@session.find(:id, 'clicker')
|
708
815
|
end
|
709
816
|
|
710
817
|
context 'when w3c_click_offset is false' do
|
@@ -713,17 +820,17 @@ Capybara::SpecHelper.spec 'node' do
|
|
713
820
|
end
|
714
821
|
|
715
822
|
it 'should offset from top left of element' do
|
716
|
-
|
823
|
+
clicker.click(x: 10, y: 5)
|
717
824
|
expect(@session).to have_text(/clicked at 110,105/)
|
718
825
|
end
|
719
826
|
|
720
827
|
it 'should offset outside the element' do
|
721
|
-
|
828
|
+
clicker.click(x: -15, y: -10)
|
722
829
|
expect(@session).to have_text(/clicked at 85,90/)
|
723
830
|
end
|
724
831
|
|
725
832
|
it 'should default to click the middle' do
|
726
|
-
|
833
|
+
clicker.click
|
727
834
|
expect(@session).to have_text(/clicked at 150,150/)
|
728
835
|
end
|
729
836
|
end
|
@@ -734,21 +841,30 @@ Capybara::SpecHelper.spec 'node' do
|
|
734
841
|
end
|
735
842
|
|
736
843
|
it 'should offset from center of element' do
|
737
|
-
|
844
|
+
clicker.click(x: 10, y: 5)
|
738
845
|
expect(@session).to have_text(/clicked at 160,155/)
|
739
846
|
end
|
740
847
|
|
741
848
|
it 'should offset outside from center of element' do
|
742
|
-
|
849
|
+
clicker.click(x: -65, y: -60)
|
743
850
|
expect(@session).to have_text(/clicked at 85,90/)
|
744
851
|
end
|
745
852
|
|
746
853
|
it 'should default to click the middle' do
|
747
|
-
|
854
|
+
clicker.click
|
748
855
|
expect(@session).to have_text(/clicked at 150,150/)
|
749
856
|
end
|
750
857
|
end
|
751
858
|
end
|
859
|
+
|
860
|
+
context 'delay', requires: [:js] do
|
861
|
+
it 'should delay the mouse up' do
|
862
|
+
@session.visit('with_js')
|
863
|
+
@session.find(:css, '#click-test').click(delay: 2)
|
864
|
+
delay = @session.evaluate_script('window.click_delay')
|
865
|
+
expect(delay).to be >= 2
|
866
|
+
end
|
867
|
+
end
|
752
868
|
end
|
753
869
|
|
754
870
|
describe '#double_click', requires: [:js] do
|
@@ -768,7 +884,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
768
884
|
@session.visit('with_js')
|
769
885
|
@session.find(:css, '#click-test').double_click(x: 10, y: 5)
|
770
886
|
link = @session.find(:link, 'has-been-double-clicked')
|
771
|
-
locations = link.text.match(/^Has been double clicked at (?<x>[\d
|
887
|
+
locations = link.text.match(/^Has been double clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
772
888
|
# Resulting click location should be very close to 10, 5 relative to top left corner of the element, but may not be exact due
|
773
889
|
# to integer/float conversions and rounding.
|
774
890
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
@@ -787,7 +903,10 @@ Capybara::SpecHelper.spec 'node' do
|
|
787
903
|
context 'offset', requires: [:js] do
|
788
904
|
before do
|
789
905
|
@session.visit('/offset')
|
790
|
-
|
906
|
+
end
|
907
|
+
|
908
|
+
let :clicker do
|
909
|
+
@session.find(:id, 'clicker')
|
791
910
|
end
|
792
911
|
|
793
912
|
context 'when w3c_click_offset is false' do
|
@@ -796,17 +915,17 @@ Capybara::SpecHelper.spec 'node' do
|
|
796
915
|
end
|
797
916
|
|
798
917
|
it 'should offset from top left of element' do
|
799
|
-
|
918
|
+
clicker.double_click(x: 10, y: 5)
|
800
919
|
expect(@session).to have_text(/clicked at 110,105/)
|
801
920
|
end
|
802
921
|
|
803
922
|
it 'should offset outside the element' do
|
804
|
-
|
923
|
+
clicker.double_click(x: -15, y: -10)
|
805
924
|
expect(@session).to have_text(/clicked at 85,90/)
|
806
925
|
end
|
807
926
|
|
808
927
|
it 'should default to click the middle' do
|
809
|
-
|
928
|
+
clicker.double_click
|
810
929
|
expect(@session).to have_text(/clicked at 150,150/)
|
811
930
|
end
|
812
931
|
end
|
@@ -817,17 +936,17 @@ Capybara::SpecHelper.spec 'node' do
|
|
817
936
|
end
|
818
937
|
|
819
938
|
it 'should offset from center of element' do
|
820
|
-
|
939
|
+
clicker.double_click(x: 10, y: 5)
|
821
940
|
expect(@session).to have_text(/clicked at 160,155/)
|
822
941
|
end
|
823
942
|
|
824
943
|
it 'should offset outside from center of element' do
|
825
|
-
|
944
|
+
clicker.double_click(x: -65, y: -60)
|
826
945
|
expect(@session).to have_text(/clicked at 85,90/)
|
827
946
|
end
|
828
947
|
|
829
948
|
it 'should default to click the middle' do
|
830
|
-
|
949
|
+
clicker.double_click
|
831
950
|
expect(@session).to have_text(/clicked at 150,150/)
|
832
951
|
end
|
833
952
|
end
|
@@ -851,7 +970,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
851
970
|
@session.visit('with_js')
|
852
971
|
@session.find(:css, '#click-test').right_click(x: 10, y: 10)
|
853
972
|
link = @session.find(:link, 'has-been-right-clicked')
|
854
|
-
locations = link.text.match(/^Has been right clicked at (?<x>[\d
|
973
|
+
locations = link.text.match(/^Has been right clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
855
974
|
# Resulting click location should be very close to 10, 10 relative to top left corner of the element, but may not be exact due
|
856
975
|
# to integer/float conversions and rounding
|
857
976
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
@@ -870,7 +989,10 @@ Capybara::SpecHelper.spec 'node' do
|
|
870
989
|
context 'offset', requires: [:js] do
|
871
990
|
before do
|
872
991
|
@session.visit('/offset')
|
873
|
-
|
992
|
+
end
|
993
|
+
|
994
|
+
let :clicker do
|
995
|
+
@session.find(:id, 'clicker')
|
874
996
|
end
|
875
997
|
|
876
998
|
context 'when w3c_click_offset is false' do
|
@@ -879,17 +1001,17 @@ Capybara::SpecHelper.spec 'node' do
|
|
879
1001
|
end
|
880
1002
|
|
881
1003
|
it 'should offset from top left of element' do
|
882
|
-
|
1004
|
+
clicker.right_click(x: 10, y: 5)
|
883
1005
|
expect(@session).to have_text(/clicked at 110,105/)
|
884
1006
|
end
|
885
1007
|
|
886
1008
|
it 'should offset outside the element' do
|
887
|
-
|
1009
|
+
clicker.right_click(x: -15, y: -10)
|
888
1010
|
expect(@session).to have_text(/clicked at 85,90/)
|
889
1011
|
end
|
890
1012
|
|
891
1013
|
it 'should default to click the middle' do
|
892
|
-
|
1014
|
+
clicker.right_click
|
893
1015
|
expect(@session).to have_text(/clicked at 150,150/)
|
894
1016
|
end
|
895
1017
|
end
|
@@ -900,21 +1022,30 @@ Capybara::SpecHelper.spec 'node' do
|
|
900
1022
|
end
|
901
1023
|
|
902
1024
|
it 'should offset from center of element' do
|
903
|
-
|
1025
|
+
clicker.right_click(x: 10, y: 5)
|
904
1026
|
expect(@session).to have_text(/clicked at 160,155/)
|
905
1027
|
end
|
906
1028
|
|
907
1029
|
it 'should offset outside from center of element' do
|
908
|
-
|
1030
|
+
clicker.right_click(x: -65, y: -60)
|
909
1031
|
expect(@session).to have_text(/clicked at 85,90/)
|
910
1032
|
end
|
911
1033
|
|
912
1034
|
it 'should default to click the middle' do
|
913
|
-
|
1035
|
+
clicker.right_click
|
914
1036
|
expect(@session).to have_text(/clicked at 150,150/)
|
915
1037
|
end
|
916
1038
|
end
|
917
1039
|
end
|
1040
|
+
|
1041
|
+
context 'delay', requires: [:js] do
|
1042
|
+
it 'should delay the mouse up' do
|
1043
|
+
@session.visit('with_js')
|
1044
|
+
@session.find(:css, '#click-test').right_click(delay: 2)
|
1045
|
+
delay = @session.evaluate_script('window.right_click_delay')
|
1046
|
+
expect(delay).to be >= 2
|
1047
|
+
end
|
1048
|
+
end
|
918
1049
|
end
|
919
1050
|
|
920
1051
|
describe '#send_keys', requires: [:send_keys] do
|