capybara 3.29.0 → 3.31.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/History.md +40 -1
- data/README.md +1 -1
- data/lib/capybara/config.rb +7 -3
- data/lib/capybara/dsl.rb +10 -2
- data/lib/capybara/helpers.rb +3 -1
- data/lib/capybara/minitest.rb +18 -4
- data/lib/capybara/node/actions.rb +23 -19
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +21 -16
- data/lib/capybara/node/finders.rb +17 -11
- data/lib/capybara/node/matchers.rb +60 -45
- 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 +17 -4
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +4 -1
- 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/result.rb +24 -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 +2 -2
- 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 +24 -16
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition.rb +2 -2
- data/lib/capybara/selector/definition/button.rb +7 -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 +1 -1
- data/lib/capybara/selector/definition/label.rb +4 -2
- 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 +5 -2
- 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 +4 -2
- data/lib/capybara/selenium/driver.rb +19 -11
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
- 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 +29 -10
- data/lib/capybara/selenium/nodes/chrome_node.rb +11 -5
- data/lib/capybara/selenium/nodes/edge_node.rb +4 -2
- data/lib/capybara/selenium/nodes/firefox_node.rb +2 -2
- 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 +40 -23
- data/lib/capybara/session/config.rb +6 -2
- data/lib/capybara/session/matchers.rb +6 -6
- data/lib/capybara/spec/public/test.js +51 -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 +5 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +20 -0
- data/lib/capybara/spec/session/find_spec.rb +20 -0
- data/lib/capybara/spec/session/has_css_spec.rb +3 -3
- data/lib/capybara/spec/session/has_select_spec.rb +28 -0
- 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 +106 -2
- 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/views/form.erb +11 -1
- data/lib/capybara/version.rb +1 -1
- data/spec/dsl_spec.rb +2 -2
- data/spec/minitest_spec_spec.rb +46 -46
- data/spec/rack_test_spec.rb +0 -1
- data/spec/regexp_dissassembler_spec.rb +45 -37
- data/spec/result_spec.rb +7 -3
- data/spec/rspec/features_spec.rb +1 -0
- data/spec/rspec/shared_spec_matchers.rb +3 -3
- data/spec/rspec_spec.rb +4 -4
- data/spec/selenium_spec_chrome.rb +5 -4
- data/spec/selenium_spec_firefox.rb +7 -2
- data/spec/server_spec.rb +42 -0
- data/spec/session_spec.rb +1 -1
- data/spec/shared_selenium_node.rb +3 -3
- data/spec/shared_selenium_session.rb +8 -7
- metadata +3 -3
@@ -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
|
@@ -117,6 +117,34 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
117
117
|
end
|
118
118
|
end
|
119
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])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
120
148
|
context 'with partial options' do
|
121
149
|
it 'should be true if a field with the given partial options is on the page' do
|
122
150
|
expect(@session).to have_select('Region', with_options: %w[Norway Sweden])
|
@@ -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,11 +270,11 @@ 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
|
273
|
+
@session.find(:css, '#closed_details > summary').click
|
274
274
|
expect(@session).to have_css('#closed_details *', visible: true, 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
279
|
expect(@session).to have_no_css(descendants_css, visible: true)
|
280
280
|
.and(have_css(descendants_css, visible: :hidden, count: 3))
|
@@ -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
|
|
@@ -15,7 +15,7 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
|
|
15
15
|
@session.save_and_open_screenshot
|
16
16
|
|
17
17
|
expect(@session.driver).to have_received(:save_screenshot)
|
18
|
-
.with(expected_file_regex,
|
18
|
+
.with(expected_file_regex, any_args)
|
19
19
|
expect(Launchy).to have_received(:open).with(expected_file_regex)
|
20
20
|
end
|
21
21
|
|
@@ -27,7 +27,7 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
|
|
27
27
|
@session.save_and_open_screenshot(custom_path)
|
28
28
|
|
29
29
|
expect(@session.driver).to have_received(:save_screenshot)
|
30
|
-
.with(/#{custom_path}$/,
|
30
|
+
.with(/#{custom_path}$/, any_args)
|
31
31
|
expect(Launchy).to have_received(:open).with(/#{custom_path}$/)
|
32
32
|
end
|
33
33
|
|
@@ -19,7 +19,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
|
|
19
19
|
@session.save_screenshot
|
20
20
|
|
21
21
|
regexp = Regexp.new(File.join(Dir.pwd, 'capybara-\d+\.png'))
|
22
|
-
expect(@session.driver).to have_received(:save_screenshot).with(regexp,
|
22
|
+
expect(@session.driver).to have_received(:save_screenshot).with(regexp, any_args)
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'allows to specify another path' do
|
@@ -28,7 +28,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
|
|
28
28
|
custom_path = 'screenshots/1.png'
|
29
29
|
@session.save_screenshot(custom_path)
|
30
30
|
|
31
|
-
expect(@session.driver).to have_received(:save_screenshot).with(/#{custom_path}$/,
|
31
|
+
expect(@session.driver).to have_received(:save_screenshot).with(/#{custom_path}$/, any_args)
|
32
32
|
end
|
33
33
|
|
34
34
|
context 'with Capybara.save_path' do
|
@@ -39,7 +39,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
|
|
39
39
|
@session.save_screenshot
|
40
40
|
|
41
41
|
regexp = Regexp.new(File.join(alternative_path, 'capybara-\d+\.png'))
|
42
|
-
expect(@session.driver).to have_received(:save_screenshot).with(regexp,
|
42
|
+
expect(@session.driver).to have_received(:save_screenshot).with(regexp, any_args)
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'relative paths are relative to save_path' do
|
@@ -49,7 +49,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
|
|
49
49
|
custom_path = 'screenshots/2.png'
|
50
50
|
@session.save_screenshot(custom_path)
|
51
51
|
|
52
|
-
expect(@session.driver).to have_received(:save_screenshot).with(File.expand_path(custom_path, alternative_path),
|
52
|
+
expect(@session.driver).to have_received(:save_screenshot).with(File.expand_path(custom_path, alternative_path), any_args)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -31,6 +31,11 @@ Capybara::SpecHelper.spec Capybara::Selector do
|
|
31
31
|
expect(@session.find(:label, for: input).text).to eq 'Nested Label'
|
32
32
|
end
|
33
33
|
|
34
|
+
it 'finds a label from nested input using :for filter with element when no id on label' do
|
35
|
+
input = @session.find(:css, '#wrapper_label').find(:css, 'input')
|
36
|
+
expect(@session.find(:label, for: input).text).to eq 'Wrapper Label'
|
37
|
+
end
|
38
|
+
|
34
39
|
it 'finds the label for an non-nested element when using :for filter' do
|
35
40
|
select = @session.find(:id, 'form_other_title')
|
36
41
|
expect(@session.find(:label, for: select)['for']).to eq 'form_other_title'
|
@@ -62,14 +67,22 @@ Capybara::SpecHelper.spec Capybara::Selector do
|
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
65
|
-
it 'can find specifically by name' do
|
70
|
+
it 'can find specifically by name string' do
|
66
71
|
expect(@session.find(:field, name: 'form[other_title]')['id']).to eq 'form_other_title'
|
67
72
|
end
|
68
73
|
|
69
|
-
it 'can find specifically by
|
74
|
+
it 'can find specifically by name regex' do
|
75
|
+
expect(@session.find(:field, name: /form\[other_.*\]/)['id']).to eq 'form_other_title'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'can find specifically by placeholder string' do
|
70
79
|
expect(@session.find(:field, placeholder: 'FirstName')['id']).to eq 'form_first_name'
|
71
80
|
end
|
72
81
|
|
82
|
+
it 'can find specifically by placeholder regex' do
|
83
|
+
expect(@session.find(:field, placeholder: /FirstN.*/)['id']).to eq 'form_first_name'
|
84
|
+
end
|
85
|
+
|
73
86
|
it 'can find by type' do
|
74
87
|
expect(@session.find(:field, 'Confusion', type: 'checkbox')['id']).to eq 'confusion_checkbox'
|
75
88
|
expect(@session.find(:field, 'Confusion', type: 'text')['id']).to eq 'confusion_text'
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<option>Miss</option>
|
12
12
|
<option disabled="disabled">Other</option>
|
13
13
|
</select>
|
14
|
-
|
14
|
+
</p>
|
15
15
|
|
16
16
|
<p>
|
17
17
|
<label for="customer_name">Customer Name
|
@@ -62,6 +62,11 @@
|
|
62
62
|
<input type="text" name="form[name]" value="John Smith" id="form_name"/>
|
63
63
|
</p>
|
64
64
|
|
65
|
+
<p>
|
66
|
+
<label for="form_age">Age</label>
|
67
|
+
<input type="range" name="form[age]" value="18" min="13" max="100" step="0.5" id="form_age"/>
|
68
|
+
</p>
|
69
|
+
|
65
70
|
<p>
|
66
71
|
<label for="form_schmooo">Schmooo</label>
|
67
72
|
<input type="schmooo" name="form[schmooo]" value="This is Schmooo!" id="form_schmooo"/>
|
@@ -474,6 +479,11 @@ New line after and before textarea tag
|
|
474
479
|
<input type="text" name="nested_label" id="nested_label"/>
|
475
480
|
</label>
|
476
481
|
|
482
|
+
<label id="wrapper_label">
|
483
|
+
Wrapper Label
|
484
|
+
<input type="checkbox"/>
|
485
|
+
</label>
|
486
|
+
|
477
487
|
<form id="form1" action="/form" method="post">
|
478
488
|
<input type="text" name="form[which_form]" value="form1" id="form_which_form"/>
|
479
489
|
<input type="text" name="form[for_form2]" value="for_form2" form="form2"/>
|
data/lib/capybara/version.rb
CHANGED
data/spec/dsl_spec.rb
CHANGED
@@ -92,7 +92,7 @@ RSpec.describe Capybara::DSL do
|
|
92
92
|
driver_before_block = Capybara.current_driver
|
93
93
|
begin
|
94
94
|
Capybara.using_driver(:selenium) { raise 'ohnoes!' }
|
95
|
-
rescue Exception # rubocop:disable Lint/RescueException,Lint/
|
95
|
+
rescue Exception # rubocop:disable Lint/RescueException,Lint/SuppressedException
|
96
96
|
end
|
97
97
|
expect(Capybara.current_driver).to eq(driver_before_block)
|
98
98
|
end
|
@@ -208,7 +208,7 @@ RSpec.describe Capybara::DSL do
|
|
208
208
|
Capybara.using_session(:raise) do
|
209
209
|
raise
|
210
210
|
end
|
211
|
-
rescue Exception # rubocop:disable Lint/RescueException,Lint/
|
211
|
+
rescue Exception # rubocop:disable Lint/RescueException,Lint/SuppressedException
|
212
212
|
end
|
213
213
|
expect(Capybara.session_name).to eq(:default)
|
214
214
|
end
|
data/spec/minitest_spec_spec.rb
CHANGED
@@ -17,125 +17,125 @@ class MinitestSpecTest < Minitest::Spec
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'supports text expectations' do
|
20
|
-
page.must_have_text('Form', minimum: 1)
|
21
|
-
page.wont_have_text('Not a form')
|
20
|
+
_(page).must_have_text('Form', minimum: 1)
|
21
|
+
_(page).wont_have_text('Not a form')
|
22
22
|
form = find(:css, 'form', text: 'Title')
|
23
|
-
form.must_have_text('Customer Email')
|
24
|
-
form.wont_have_text('Some other email')
|
23
|
+
_(form).must_have_text('Customer Email')
|
24
|
+
_(form).wont_have_text('Some other email')
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'supports current_path expectations' do
|
28
|
-
page.must_have_current_path('/form')
|
29
|
-
page.wont_have_current_path('/form2')
|
28
|
+
_(page).must_have_current_path('/form')
|
29
|
+
_(page).wont_have_current_path('/form2')
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'supports title expectations' do
|
33
33
|
visit('/with_title')
|
34
|
-
page.must_have_title('Test Title')
|
35
|
-
page.wont_have_title('Not the title')
|
34
|
+
_(page).must_have_title('Test Title')
|
35
|
+
_(page).wont_have_title('Not the title')
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'supports xpath expectations' do
|
39
|
-
page.must_have_xpath('.//input[@id="customer_email"]')
|
40
|
-
page.wont_have_xpath('.//select[@id="not_form_title"]')
|
41
|
-
page.wont_have_xpath('.//input[@id="customer_email"]') { |el| el[:id] == 'not_customer_email' }
|
39
|
+
_(page).must_have_xpath('.//input[@id="customer_email"]')
|
40
|
+
_(page).wont_have_xpath('.//select[@id="not_form_title"]')
|
41
|
+
_(page).wont_have_xpath('.//input[@id="customer_email"]') { |el| el[:id] == 'not_customer_email' }
|
42
42
|
select = find(:select, 'form_title')
|
43
|
-
select.must_have_xpath('.//option[@class="title"]')
|
44
|
-
select.must_have_xpath('.//option', count: 1) { |option| option[:class] != 'title' && !option.disabled? }
|
45
|
-
select.wont_have_xpath('.//input[@id="customer_email"]')
|
43
|
+
_(select).must_have_xpath('.//option[@class="title"]')
|
44
|
+
_(select).must_have_xpath('.//option', count: 1) { |option| option[:class] != 'title' && !option.disabled? }
|
45
|
+
_(select).wont_have_xpath('.//input[@id="customer_email"]')
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'support css expectations' do
|
49
|
-
page.must_have_css('input#customer_email')
|
50
|
-
page.wont_have_css('select#not_form_title')
|
49
|
+
_(page).must_have_css('input#customer_email')
|
50
|
+
_(page).wont_have_css('select#not_form_title')
|
51
51
|
el = find(:select, 'form_title')
|
52
|
-
el.must_have_css('option.title')
|
53
|
-
el.wont_have_css('input#customer_email')
|
52
|
+
_(el).must_have_css('option.title')
|
53
|
+
_(el).wont_have_css('input#customer_email')
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'supports link expectations' do
|
57
57
|
visit('/with_html')
|
58
|
-
page.must_have_link('A link')
|
59
|
-
page.wont_have_link('Not on page')
|
58
|
+
_(page).must_have_link('A link')
|
59
|
+
_(page).wont_have_link('Not on page')
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'supports button expectations' do
|
63
|
-
page.must_have_button('fresh_btn')
|
64
|
-
page.wont_have_button('not_btn')
|
63
|
+
_(page).must_have_button('fresh_btn')
|
64
|
+
_(page).wont_have_button('not_btn')
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'supports field expectations' do
|
68
|
-
page.must_have_field('customer_email')
|
69
|
-
page.wont_have_field('not_on_the_form')
|
68
|
+
_(page).must_have_field('customer_email')
|
69
|
+
_(page).wont_have_field('not_on_the_form')
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'supports select expectations' do
|
73
|
-
page.must_have_select('form_title')
|
74
|
-
page.wont_have_select('not_form_title')
|
73
|
+
_(page).must_have_select('form_title')
|
74
|
+
_(page).wont_have_select('not_form_title')
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'supports checked_field expectations' do
|
78
|
-
page.must_have_checked_field('form_pets_dog')
|
79
|
-
page.wont_have_checked_field('form_pets_cat')
|
78
|
+
_(page).must_have_checked_field('form_pets_dog')
|
79
|
+
_(page).wont_have_checked_field('form_pets_cat')
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'supports unchecked_field expectations' do
|
83
|
-
page.must_have_unchecked_field('form_pets_cat')
|
84
|
-
page.wont_have_unchecked_field('form_pets_dog')
|
83
|
+
_(page).must_have_unchecked_field('form_pets_cat')
|
84
|
+
_(page).wont_have_unchecked_field('form_pets_dog')
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'supports table expectations' do
|
88
88
|
visit('/tables')
|
89
|
-
page.must_have_table('agent_table')
|
90
|
-
page.wont_have_table('not_on_form')
|
89
|
+
_(page).must_have_table('agent_table')
|
90
|
+
_(page).wont_have_table('not_on_form')
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'supports all_of_selectors expectations' do
|
94
|
-
page.must_have_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')
|
94
|
+
_(page).must_have_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'supports none_of_selectors expectations' do
|
98
|
-
page.must_have_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')
|
98
|
+
_(page).must_have_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')
|
99
99
|
end
|
100
100
|
|
101
101
|
it 'supports any_of_selectors expectations' do
|
102
|
-
page.must_have_any_of_selectors(:css, 'select#form_other_title', 'input#not_on_page')
|
102
|
+
_(page).must_have_any_of_selectors(:css, 'select#form_other_title', 'input#not_on_page')
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'supports match_selector expectations' do
|
106
|
-
find(:field, 'customer_email').must_match_selector(:field, 'customer_email')
|
107
|
-
find(:select, 'form_title').wont_match_selector(:field, 'customer_email')
|
106
|
+
_(find(:field, 'customer_email')).must_match_selector(:field, 'customer_email')
|
107
|
+
_(find(:select, 'form_title')).wont_match_selector(:field, 'customer_email')
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'supports match_css expectations' do
|
111
|
-
find(:select, 'form_title').must_match_css('select#form_title')
|
112
|
-
find(:select, 'form_title').wont_match_css('select#form_other_title')
|
111
|
+
_(find(:select, 'form_title')).must_match_css('select#form_title')
|
112
|
+
_(find(:select, 'form_title')).wont_match_css('select#form_other_title')
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'supports match_xpath expectations' do
|
116
|
-
find(:select, 'form_title').must_match_xpath('.//select[@id="form_title"]')
|
117
|
-
find(:select, 'form_title').wont_match_xpath('.//select[@id="not_on_page"]')
|
116
|
+
_(find(:select, 'form_title')).must_match_xpath('.//select[@id="form_title"]')
|
117
|
+
_(find(:select, 'form_title')).wont_match_xpath('.//select[@id="not_on_page"]')
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'handles failures' do
|
121
|
-
page.must_have_select('non_existing_form_title')
|
121
|
+
_(page).must_have_select('non_existing_form_title')
|
122
122
|
end
|
123
123
|
|
124
124
|
it 'supports style expectations' do
|
125
125
|
skip "Rack test doesn't support style" if Capybara.current_driver == :rack_test
|
126
126
|
visit('/with_html')
|
127
|
-
find(:css, '#second').must_have_style('display' => 'inline') # deprecated
|
128
|
-
find(:css, '#second').must_match_style('display' => 'inline')
|
127
|
+
_(find(:css, '#second')).must_have_style('display' => 'inline') # deprecated
|
128
|
+
_(find(:css, '#second')).must_match_style('display' => 'inline')
|
129
129
|
end
|
130
130
|
|
131
131
|
it 'supports ancestor expectations' do
|
132
132
|
option = find(:option, 'Finnish')
|
133
|
-
option.must_have_ancestor(:css, '#form_locale')
|
133
|
+
_(option).must_have_ancestor(:css, '#form_locale')
|
134
134
|
end
|
135
135
|
|
136
136
|
it 'supports sibling expectations' do
|
137
137
|
option = find(:css, '#form_title').find(:option, 'Mrs')
|
138
|
-
option.must_have_sibling(:option, 'Mr')
|
138
|
+
_(option).must_have_sibling(:option, 'Mr')
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|