capybara 3.32.0 → 3.33.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 +38 -1
- data/README.md +10 -3
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/minitest.rb +2 -3
- data/lib/capybara/node/actions.rb +16 -20
- data/lib/capybara/node/matchers.rb +4 -6
- data/lib/capybara/queries/selector_query.rb +8 -1
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +6 -0
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/servers.rb +1 -1
- data/lib/capybara/result.rb +4 -1
- data/lib/capybara/rspec/matchers/have_text.rb +1 -1
- data/lib/capybara/selector/definition/button.rb +1 -0
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/definition.rb +5 -4
- data/lib/capybara/selector/selector.rb +4 -0
- data/lib/capybara/selector.rb +10 -1
- data/lib/capybara/selenium/driver.rb +6 -4
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +7 -9
- 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/node.rb +17 -3
- data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
- data/lib/capybara/selenium/patches/action_pauser.rb +4 -1
- data/lib/capybara/selenium/patches/logs.rb +3 -5
- data/lib/capybara/session/config.rb +3 -1
- data/lib/capybara/session.rb +3 -3
- data/lib/capybara/spec/public/test.js +7 -0
- data/lib/capybara/spec/session/click_button_spec.rb +11 -0
- data/lib/capybara/spec/session/has_button_spec.rb +16 -0
- 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 +4 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
- data/lib/capybara/spec/session/node_spec.rb +6 -6
- data/lib/capybara/spec/spec_helper.rb +1 -0
- data/lib/capybara/spec/test_app.rb +14 -18
- data/lib/capybara/spec/views/form.erb +6 -1
- data/lib/capybara/spec/views/with_dragula.erb +3 -1
- data/lib/capybara/spec/views/with_js.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara.rb +17 -7
- data/spec/capybara_spec.rb +1 -1
- data/spec/dsl_spec.rb +14 -1
- data/spec/minitest_spec.rb +1 -1
- data/spec/rack_test_spec.rb +1 -0
- data/spec/result_spec.rb +1 -17
- data/spec/rspec/shared_spec_matchers.rb +65 -53
- data/spec/selector_spec.rb +1 -1
- data/spec/selenium_spec_chrome.rb +0 -2
- data/spec/server_spec.rb +41 -49
- data/spec/shared_selenium_node.rb +10 -0
- data/spec/shared_selenium_session.rb +25 -7
- data/spec/spec_helper.rb +1 -1
- metadata +4 -3
|
@@ -42,7 +42,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
|
42
42
|
|
|
43
43
|
def send_keys(*args)
|
|
44
44
|
# https://github.com/mozilla/geckodriver/issues/846
|
|
45
|
-
return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?
|
|
45
|
+
return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)
|
|
46
46
|
|
|
47
47
|
native.click
|
|
48
48
|
_send_keys(args).perform
|
|
@@ -20,4 +20,7 @@ module ActionPauser
|
|
|
20
20
|
private_constant :Pauser
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
::Selenium::WebDriver::
|
|
23
|
+
if defined?(::Selenium::WebDriver::VERSION) && (::Selenium::WebDriver::VERSION.to_f < 4) &&
|
|
24
|
+
defined?(::Selenium::WebDriver::ActionBuilder)
|
|
25
|
+
::Selenium::WebDriver::ActionBuilder.prepend(ActionPauser)
|
|
26
|
+
end
|
|
@@ -33,11 +33,9 @@ module Capybara
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
Array(data).map do |l|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
next
|
|
40
|
-
end
|
|
36
|
+
::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
|
|
37
|
+
rescue KeyError
|
|
38
|
+
next
|
|
41
39
|
end
|
|
42
40
|
rescue ::Selenium::WebDriver::Error::UnknownCommandError
|
|
43
41
|
raise NotImplementedError, LOG_MSG
|
|
@@ -8,7 +8,7 @@ module Capybara
|
|
|
8
8
|
automatic_reload match exact exact_text raise_server_errors visible_text_only
|
|
9
9
|
automatic_label_click enable_aria_label save_path asset_host default_host app_host
|
|
10
10
|
server_host server_port server_errors default_set_options disable_animation test_id
|
|
11
|
-
predicates_wait default_normalize_ws w3c_click_offset].freeze
|
|
11
|
+
predicates_wait default_normalize_ws w3c_click_offset enable_aria_role].freeze
|
|
12
12
|
|
|
13
13
|
attr_accessor(*OPTIONS)
|
|
14
14
|
|
|
@@ -37,6 +37,8 @@ module Capybara
|
|
|
37
37
|
# See {Capybara.configure}
|
|
38
38
|
# @!method enable_aria_label
|
|
39
39
|
# See {Capybara.configure}
|
|
40
|
+
# @!method enable_aria_role
|
|
41
|
+
# See {Capybara.configure}
|
|
40
42
|
# @!method save_path
|
|
41
43
|
# See {Capybara.configure}
|
|
42
44
|
# @!method asset_host
|
data/lib/capybara/session.rb
CHANGED
|
@@ -97,8 +97,8 @@ module Capybara
|
|
|
97
97
|
|
|
98
98
|
def driver
|
|
99
99
|
@driver ||= begin
|
|
100
|
-
unless Capybara.drivers
|
|
101
|
-
other_drivers = Capybara.drivers.
|
|
100
|
+
unless Capybara.drivers[mode]
|
|
101
|
+
other_drivers = Capybara.drivers.names.map(&:inspect)
|
|
102
102
|
raise Capybara::DriverNotFoundError, "no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}"
|
|
103
103
|
end
|
|
104
104
|
driver = Capybara.drivers[mode].call(app)
|
|
@@ -192,7 +192,7 @@ module Capybara
|
|
|
192
192
|
# @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
|
|
193
193
|
#
|
|
194
194
|
def html
|
|
195
|
-
driver.html
|
|
195
|
+
driver.html || ''
|
|
196
196
|
end
|
|
197
197
|
alias_method :body, :html
|
|
198
198
|
alias_method :source, :html
|
|
@@ -108,6 +108,13 @@ $(function() {
|
|
|
108
108
|
}, 4000);
|
|
109
109
|
return false;
|
|
110
110
|
});
|
|
111
|
+
$('#aria-button').click(function() {
|
|
112
|
+
var span = $(this);
|
|
113
|
+
setTimeout(function() {
|
|
114
|
+
$(span).after('<span role="button">ARIA button has been clicked</span>')
|
|
115
|
+
}, 1000);
|
|
116
|
+
return false;
|
|
117
|
+
});
|
|
111
118
|
$('#waiter').change(function() {
|
|
112
119
|
activeRequests = 1;
|
|
113
120
|
setTimeout(function() {
|
|
@@ -193,6 +193,17 @@ Capybara::SpecHelper.spec '#click_button' do
|
|
|
193
193
|
end
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
+
context 'when Capybara.enable_aria_role = true' do
|
|
197
|
+
it 'should click on a button role', requires: [:js] do
|
|
198
|
+
Capybara.enable_aria_role = true
|
|
199
|
+
@session.using_wait_time(1.5) do
|
|
200
|
+
@session.visit('/with_js')
|
|
201
|
+
@session.click_button('ARIA button')
|
|
202
|
+
expect(@session).to have_button('ARIA button has been clicked')
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
196
207
|
context 'with fields associated with the form using the form attribute', requires: [:form_attribute] do
|
|
197
208
|
let(:results) { extract_results(@session) }
|
|
198
209
|
|
|
@@ -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
|
|
@@ -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,7 @@ 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
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
@@ -158,7 +158,7 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
it 'should be true even when the options are invisible, if the select itself is invisible' do
|
|
161
|
-
expect(@session).to have_select('Icecream', visible:
|
|
161
|
+
expect(@session).to have_select('Icecream', visible: :hidden, with_options: %w[Vanilla Strawberry])
|
|
162
162
|
end
|
|
163
163
|
end
|
|
164
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
|
|
@@ -271,12 +271,12 @@ Capybara::SpecHelper.spec 'node' do
|
|
|
271
271
|
|
|
272
272
|
it 'works when details is toggled open and closed' do
|
|
273
273
|
@session.find(:css, '#closed_details > summary').click
|
|
274
|
-
expect(@session).to have_css('#closed_details *', visible:
|
|
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
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
|
|
@@ -758,7 +758,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
|
758
758
|
@session.visit('with_js')
|
|
759
759
|
@session.find(:css, '#click-test').click(x: 5, y: 5)
|
|
760
760
|
link = @session.find(:link, 'has-been-clicked')
|
|
761
|
-
locations = link.text.match(/^Has been clicked at (?<x>[\d
|
|
761
|
+
locations = link.text.match(/^Has been clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
|
|
762
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
|
|
763
763
|
# integer/float conversions and rounding.
|
|
764
764
|
expect(locations[:x].to_f).to be_within(1).of(5)
|
|
@@ -884,7 +884,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
|
884
884
|
@session.visit('with_js')
|
|
885
885
|
@session.find(:css, '#click-test').double_click(x: 10, y: 5)
|
|
886
886
|
link = @session.find(:link, 'has-been-double-clicked')
|
|
887
|
-
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.-]+)$/)
|
|
888
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
|
|
889
889
|
# to integer/float conversions and rounding.
|
|
890
890
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
|
@@ -970,7 +970,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
|
970
970
|
@session.visit('with_js')
|
|
971
971
|
@session.find(:css, '#click-test').right_click(x: 10, y: 10)
|
|
972
972
|
link = @session.find(:link, 'has-been-right-clicked')
|
|
973
|
-
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.-]+)$/)
|
|
974
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
|
|
975
975
|
# to integer/float conversions and rounding
|
|
976
976
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
|
@@ -188,28 +188,24 @@ class TestApp < Sinatra::Base
|
|
|
188
188
|
end
|
|
189
189
|
|
|
190
190
|
post '/upload' do
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
'No file uploaded'
|
|
198
|
-
end
|
|
191
|
+
buffer = []
|
|
192
|
+
buffer << "Content-type: #{params.dig(:form, :document, :type)}"
|
|
193
|
+
buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
|
|
194
|
+
buffer.join(' | ')
|
|
195
|
+
rescue StandardError
|
|
196
|
+
'No file uploaded'
|
|
199
197
|
end
|
|
200
198
|
|
|
201
199
|
post '/upload_multiple' do
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
buffer << "File content: #{doc[:tempfile].read}"
|
|
208
|
-
end
|
|
209
|
-
buffer.join(' | ')
|
|
210
|
-
rescue StandardError
|
|
211
|
-
'No files uploaded'
|
|
200
|
+
docs = params.dig(:form, :multiple_documents)
|
|
201
|
+
buffer = [docs.size.to_s]
|
|
202
|
+
docs.each do |doc|
|
|
203
|
+
buffer << "Content-type: #{doc[:type]}"
|
|
204
|
+
buffer << "File content: #{doc[:tempfile].read}"
|
|
212
205
|
end
|
|
206
|
+
buffer.join(' | ')
|
|
207
|
+
rescue StandardError
|
|
208
|
+
'No files uploaded'
|
|
213
209
|
end
|
|
214
210
|
|
|
215
211
|
get '/apple-touch-icon-precomposed.png' do
|
|
@@ -140,7 +140,11 @@
|
|
|
140
140
|
|
|
141
141
|
<p>
|
|
142
142
|
<label for="form_zipcode">Zipcode</label>
|
|
143
|
-
<input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" />
|
|
143
|
+
<input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" pattern="[0-9]{5,9}" />
|
|
144
|
+
</p>
|
|
145
|
+
|
|
146
|
+
<p>
|
|
147
|
+
<input maxlength="35" id="long_length" />
|
|
144
148
|
</p>
|
|
145
149
|
|
|
146
150
|
<p>
|
|
@@ -453,6 +457,7 @@ New line after and before textarea tag
|
|
|
453
457
|
<button id="no_type">No Type!</button>
|
|
454
458
|
<button><img alt="A horse eating hay"/></button>
|
|
455
459
|
<input type="button" disabled="disabled" value="Disabled button"/>
|
|
460
|
+
<span role="button">ARIA button</span>
|
|
456
461
|
</p>
|
|
457
462
|
|
|
458
463
|
<p>
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
</div>
|
|
16
16
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.js" type="text/javascript"></script>
|
|
17
17
|
<script>
|
|
18
|
-
|
|
18
|
+
let container = document.getElementById("sortable");
|
|
19
|
+
dragula([container]);
|
|
20
|
+
container.className = "ready"
|
|
19
21
|
</script>
|
|
20
22
|
</body>
|
|
21
23
|
</html>
|
data/lib/capybara/version.rb
CHANGED
data/lib/capybara.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'nokogiri'
|
|
|
5
5
|
require 'xpath'
|
|
6
6
|
require 'forwardable'
|
|
7
7
|
require 'capybara/config'
|
|
8
|
+
require 'capybara/registration_container'
|
|
8
9
|
|
|
9
10
|
module Capybara
|
|
10
11
|
class CapybaraError < StandardError; end
|
|
@@ -81,6 +82,7 @@ module Capybara
|
|
|
81
82
|
# - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
|
|
82
83
|
# - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
|
|
83
84
|
# - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
|
|
85
|
+
# - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).
|
|
84
86
|
# - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions
|
|
85
87
|
# written using the `XPath#is` method.
|
|
86
88
|
# - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.
|
|
@@ -93,6 +95,7 @@ module Capybara
|
|
|
93
95
|
# - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},
|
|
94
96
|
# {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
|
|
95
97
|
# - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
|
|
98
|
+
# - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
|
|
96
99
|
# - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
|
|
97
100
|
# and {configure raise_server_errors} is `true`.
|
|
98
101
|
# - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
|
|
@@ -124,7 +127,7 @@ module Capybara
|
|
|
124
127
|
# @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
|
|
125
128
|
#
|
|
126
129
|
def register_driver(name, &block)
|
|
127
|
-
drivers
|
|
130
|
+
drivers.send(:register, name, block)
|
|
128
131
|
end
|
|
129
132
|
|
|
130
133
|
##
|
|
@@ -143,7 +146,7 @@ module Capybara
|
|
|
143
146
|
# @yieldparam host The host/ip to bind to
|
|
144
147
|
#
|
|
145
148
|
def register_server(name, &block)
|
|
146
|
-
servers
|
|
149
|
+
servers.send(:register, name.to_sym, block)
|
|
147
150
|
end
|
|
148
151
|
|
|
149
152
|
##
|
|
@@ -197,11 +200,11 @@ module Capybara
|
|
|
197
200
|
end
|
|
198
201
|
|
|
199
202
|
def drivers
|
|
200
|
-
@drivers ||=
|
|
203
|
+
@drivers ||= RegistrationContainer.new
|
|
201
204
|
end
|
|
202
205
|
|
|
203
206
|
def servers
|
|
204
|
-
@servers ||=
|
|
207
|
+
@servers ||= RegistrationContainer.new
|
|
205
208
|
end
|
|
206
209
|
|
|
207
210
|
# Wraps the given string, which should contain an HTML document or fragment
|
|
@@ -349,7 +352,8 @@ module Capybara
|
|
|
349
352
|
#
|
|
350
353
|
# Yield a block using a specific session name or {Capybara::Session} instance.
|
|
351
354
|
#
|
|
352
|
-
def using_session(name_or_session)
|
|
355
|
+
def using_session(name_or_session, &block)
|
|
356
|
+
previous_session = current_session
|
|
353
357
|
previous_session_info = {
|
|
354
358
|
specified_session: specified_session,
|
|
355
359
|
session_name: session_name,
|
|
@@ -362,7 +366,12 @@ module Capybara
|
|
|
362
366
|
else
|
|
363
367
|
self.session_name = name_or_session
|
|
364
368
|
end
|
|
365
|
-
|
|
369
|
+
|
|
370
|
+
if block.arity.zero?
|
|
371
|
+
yield
|
|
372
|
+
else
|
|
373
|
+
yield current_session, previous_session
|
|
374
|
+
end
|
|
366
375
|
ensure
|
|
367
376
|
self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
|
|
368
377
|
self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
|
|
@@ -394,7 +403,7 @@ module Capybara
|
|
|
394
403
|
template.inner_html = ''
|
|
395
404
|
end
|
|
396
405
|
document.xpath('//textarea').each do |textarea|
|
|
397
|
-
textarea['_capybara_raw_value'] = textarea.content.
|
|
406
|
+
textarea['_capybara_raw_value'] = textarea.content.delete_prefix("\n")
|
|
398
407
|
end
|
|
399
408
|
end
|
|
400
409
|
end
|
|
@@ -501,6 +510,7 @@ Capybara.configure do |config|
|
|
|
501
510
|
config.visible_text_only = false
|
|
502
511
|
config.automatic_label_click = false
|
|
503
512
|
config.enable_aria_label = false
|
|
513
|
+
config.enable_aria_role = false
|
|
504
514
|
config.reuse_server = true
|
|
505
515
|
config.default_set_options = {}
|
|
506
516
|
config.test_id = nil
|
data/spec/capybara_spec.rb
CHANGED
data/spec/dsl_spec.rb
CHANGED
|
@@ -8,7 +8,7 @@ class TestClass
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
|
|
11
|
-
js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial
|
|
11
|
+
js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation
|
|
12
12
|
] do |example|
|
|
13
13
|
case example.metadata[:full_description]
|
|
14
14
|
when /has_css\? should support case insensitive :class and :id options/
|
|
@@ -19,6 +19,10 @@ Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
RSpec.describe Capybara::DSL do
|
|
22
|
+
before do
|
|
23
|
+
Capybara.use_default_driver
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
after do
|
|
23
27
|
Capybara.session_name = nil
|
|
24
28
|
Capybara.default_driver = nil
|
|
@@ -238,6 +242,15 @@ RSpec.describe Capybara::DSL do
|
|
|
238
242
|
end
|
|
239
243
|
expect(Capybara.current_session).to eq(original_session)
|
|
240
244
|
end
|
|
245
|
+
|
|
246
|
+
it 'should pass the new session if block accepts' do
|
|
247
|
+
original_session = Capybara.current_session
|
|
248
|
+
Capybara.using_session(:administrator) do |admin_session, prev_session|
|
|
249
|
+
expect(admin_session).to be(Capybara.current_session)
|
|
250
|
+
expect(prev_session).to be(original_session)
|
|
251
|
+
expect(prev_session).not_to be(admin_session)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
241
254
|
end
|
|
242
255
|
|
|
243
256
|
describe '#session_name' do
|
data/spec/minitest_spec.rb
CHANGED
data/spec/rack_test_spec.rb
CHANGED
data/spec/result_spec.rb
CHANGED
|
@@ -190,23 +190,7 @@ RSpec.describe Capybara::Result do
|
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
-
context 'lazy select' do
|
|
194
|
-
it 'is compatible' do
|
|
195
|
-
# This test will let us know when JRuby fixes lazy select so we can re-enable it in Result
|
|
196
|
-
pending 'JRuby < 9.2.8.0 has an issue with lazy enumberator evaluation' if jruby_lazy_enumerator_workaround?
|
|
197
|
-
eval_count = 0
|
|
198
|
-
enum = %w[Text1 Text2 Text3].lazy.select do
|
|
199
|
-
eval_count += 1
|
|
200
|
-
true
|
|
201
|
-
end
|
|
202
|
-
expect(eval_count).to eq 0
|
|
203
|
-
enum.next
|
|
204
|
-
sleep 1
|
|
205
|
-
expect(eval_count).to eq 1
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
193
|
def jruby_lazy_enumerator_workaround?
|
|
210
|
-
|
|
194
|
+
RUBY_PLATFORM == 'java'
|
|
211
195
|
end
|
|
212
196
|
end
|