capybara 3.39.2 → 3.40.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 +22 -0
- data/README.md +173 -29
- data/lib/capybara/helpers.rb +1 -1
- data/lib/capybara/minitest/spec.rb +16 -4
- data/lib/capybara/minitest.rb +14 -1
- data/lib/capybara/node/matchers.rb +25 -0
- data/lib/capybara/node/whitespace_normalizer.rb +5 -5
- data/lib/capybara/queries/selector_query.rb +2 -1
- data/lib/capybara/rack_test/browser.rb +3 -2
- data/lib/capybara/rack_test/node.rb +5 -12
- data/lib/capybara/registration_container.rb +2 -2
- data/lib/capybara/registrations/drivers.rb +1 -1
- data/lib/capybara/registrations/servers.rb +8 -7
- data/lib/capybara/result.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +4 -12
- data/lib/capybara/rspec/matchers.rb +7 -2
- data/lib/capybara/selector/css.rb +5 -5
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector.rb +251 -0
- data/lib/capybara/selenium/driver.rb +11 -51
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -6
- data/lib/capybara/selenium/node.rb +4 -31
- data/lib/capybara/selenium/nodes/chrome_node.rb +3 -19
- data/lib/capybara/selenium/nodes/edge_node.rb +0 -16
- data/lib/capybara/server/animation_disabler.rb +1 -1
- data/lib/capybara/server.rb +1 -1
- data/lib/capybara/session.rb +3 -2
- data/lib/capybara/spec/session/all_spec.rb +1 -1
- data/lib/capybara/spec/session/click_link_spec.rb +1 -1
- data/lib/capybara/spec/session/find_spec.rb +8 -0
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_table_spec.rb +13 -2
- data/lib/capybara/spec/session/node_spec.rb +6 -0
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +2 -2
- data/lib/capybara/spec/test_app.rb +1 -1
- data/lib/capybara/spec/views/form.erb +5 -0
- data/lib/capybara/spec/views/with_html.erb +2 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara.rb +7 -6
- data/spec/minitest_spec.rb +8 -1
- data/spec/result_spec.rb +9 -0
- data/spec/rspec/shared_spec_matchers.rb +26 -2
- data/spec/rspec_spec.rb +1 -1
- data/spec/sauce_spec_chrome.rb +1 -1
- data/spec/selector_spec.rb +1 -1
- data/spec/selenium_spec_chrome.rb +7 -5
- data/spec/selenium_spec_chrome_remote.rb +0 -5
- data/spec/selenium_spec_edge.rb +11 -4
- data/spec/selenium_spec_firefox.rb +4 -3
- data/spec/selenium_spec_firefox_remote.rb +2 -3
- data/spec/server_spec.rb +12 -0
- data/spec/shared_selenium_session.rb +0 -2
- data/spec/spec_helper.rb +2 -2
- metadata +25 -32
- data/lib/capybara/selenium/logger_suppressor.rb +0 -44
- data/lib/capybara/selenium/patches/action_pauser.rb +0 -26
@@ -24,12 +24,6 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
24
24
|
JS
|
25
25
|
end
|
26
26
|
super
|
27
|
-
rescue *file_errors => e
|
28
|
-
if e.message.match?(/File not found : .+\n.+/m)
|
29
|
-
raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
|
30
|
-
end
|
31
|
-
|
32
|
-
raise
|
33
27
|
end
|
34
28
|
|
35
29
|
def drop(*args)
|
@@ -94,7 +88,7 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
94
88
|
private
|
95
89
|
|
96
90
|
def perform_legacy_drag(element, drop_modifiers)
|
97
|
-
return super if chromedriver_fixed_actions_key_state? ||
|
91
|
+
return super if chromedriver_fixed_actions_key_state? || element.obscured?
|
98
92
|
|
99
93
|
raise ArgumentError, 'Modifier keys are not supported while dragging in this version of Chrome.' unless drop_modifiers.empty?
|
100
94
|
|
@@ -104,19 +98,9 @@ private
|
|
104
98
|
browser_action.click_and_hold(native).move_to(element.native).release.perform
|
105
99
|
end
|
106
100
|
|
107
|
-
def file_errors
|
108
|
-
@file_errors = ::Selenium::WebDriver.logger.suppress_deprecations do
|
109
|
-
if defined? ::Selenium::WebDriver::Error::ExpectedError # Selenium < 4
|
110
|
-
[::Selenium::WebDriver::Error::ExpectedError]
|
111
|
-
else
|
112
|
-
[]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
101
|
def browser_version(to_float: true)
|
118
102
|
caps = capabilities
|
119
|
-
ver =
|
103
|
+
ver = caps[:browser_version] || caps[:version]
|
120
104
|
ver = ver.to_f if to_float
|
121
105
|
ver
|
122
106
|
end
|
@@ -135,7 +119,7 @@ private
|
|
135
119
|
|
136
120
|
def native_displayed?
|
137
121
|
(driver.options[:native_displayed] != false) &&
|
138
|
-
|
122
|
+
chromedriver_supports_displayed_endpoint? &&
|
139
123
|
(!ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS'])
|
140
124
|
end
|
141
125
|
end
|
@@ -24,12 +24,6 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
|
|
24
24
|
JS
|
25
25
|
end
|
26
26
|
super
|
27
|
-
rescue *file_errors => e
|
28
|
-
if e.message.match?(/File not found : .+\n.+/m)
|
29
|
-
raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
|
30
|
-
end
|
31
|
-
|
32
|
-
raise
|
33
27
|
end
|
34
28
|
|
35
29
|
def drop(*args)
|
@@ -97,16 +91,6 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
|
|
97
91
|
|
98
92
|
private
|
99
93
|
|
100
|
-
def file_errors
|
101
|
-
@file_errors = ::Selenium::WebDriver.logger.suppress_deprecations do
|
102
|
-
if defined? ::Selenium::WebDriver::Error::ExpectedError # Selenium < 4
|
103
|
-
[::Selenium::WebDriver::Error::ExpectedError]
|
104
|
-
else
|
105
|
-
[]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
94
|
def browser_version
|
111
95
|
@browser_version ||= begin
|
112
96
|
caps = driver.browser.capabilities
|
data/lib/capybara/server.rb
CHANGED
@@ -55,7 +55,7 @@ module Capybara
|
|
55
55
|
|
56
56
|
res = @checker.request { |http| http.get('/__identify__') }
|
57
57
|
|
58
|
-
|
58
|
+
res.body == app.object_id.to_s if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
|
59
59
|
rescue SystemCallError, Net::ReadTimeout, OpenSSL::SSL::SSLError
|
60
60
|
false
|
61
61
|
end
|
data/lib/capybara/session.rb
CHANGED
@@ -45,6 +45,7 @@ module Capybara
|
|
45
45
|
fill_in find find_all find_button find_by_id find_field find_link
|
46
46
|
has_content? has_text? has_css? has_no_content? has_no_text?
|
47
47
|
has_no_css? has_no_xpath? has_xpath? select uncheck
|
48
|
+
has_element? has_no_element?
|
48
49
|
has_link? has_no_link? has_button? has_no_button? has_field?
|
49
50
|
has_no_field? has_checked_field? has_unchecked_field?
|
50
51
|
has_no_table? has_table? unselect has_select? has_no_select?
|
@@ -309,8 +310,8 @@ module Capybara
|
|
309
310
|
# @!method send_keys
|
310
311
|
# @see Capybara::Node::Element#send_keys
|
311
312
|
#
|
312
|
-
def send_keys(
|
313
|
-
driver.send_keys(
|
313
|
+
def send_keys(...)
|
314
|
+
driver.send_keys(...)
|
314
315
|
end
|
315
316
|
|
316
317
|
##
|
@@ -129,7 +129,7 @@ Capybara::SpecHelper.spec '#all' do
|
|
129
129
|
end
|
130
130
|
|
131
131
|
context 'with per session config', requires: [:psc] do
|
132
|
-
it 'should use the sessions ignore_hidden_elements', psc
|
132
|
+
it 'should use the sessions ignore_hidden_elements', :psc do
|
133
133
|
Capybara.ignore_hidden_elements = true
|
134
134
|
@session.config.ignore_hidden_elements = false
|
135
135
|
expect(Capybara.ignore_hidden_elements).to be(true)
|
@@ -105,7 +105,7 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
105
105
|
|
106
106
|
it "should raise an error if no link's href matched the pattern" do
|
107
107
|
expect { @session.click_link('labore', href: /invalid_pattern/) }.to raise_error(Capybara::ElementNotFound, %r{with href matching /invalid_pattern/})
|
108
|
-
expect { @session.click_link('labore', href: /.+d+/) }.to raise_error(Capybara::ElementNotFound, /#{Regexp.quote
|
108
|
+
expect { @session.click_link('labore', href: /.+d+/) }.to raise_error(Capybara::ElementNotFound, /#{Regexp.quote 'with href matching /.+d+/'}/)
|
109
109
|
end
|
110
110
|
|
111
111
|
context 'href: nil' do
|
@@ -233,6 +233,14 @@ Capybara::SpecHelper.spec '#find' do
|
|
233
233
|
end.to raise_error(Capybara::ElementNotFound, 'Unable to find xpath "//div[@id=\\"nosuchthing\\"]"')
|
234
234
|
end
|
235
235
|
|
236
|
+
context 'without locator' do
|
237
|
+
it 'should not output `nil` in the ElementNotFound message if nothing was found' do
|
238
|
+
expect do
|
239
|
+
@session.find(:label, text: 'no such thing').to be_nil
|
240
|
+
end.to raise_error(Capybara::ElementNotFound, 'Unable to find label')
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
236
244
|
it 'should accept an XPath instance' do
|
237
245
|
@session.visit('/form')
|
238
246
|
@xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Capybara::SpecHelper.spec '#has_element?' do
|
4
|
+
before do
|
5
|
+
@session.visit('/with_html')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should be true if the given element is on the page' do
|
9
|
+
expect(@session).to have_element('a', id: 'foo')
|
10
|
+
expect(@session).to have_element('a', text: 'A link', href: '/with_simple_html')
|
11
|
+
expect(@session).to have_element('a', text: :'A link', href: :'/with_simple_html')
|
12
|
+
expect(@session).to have_element('a', text: 'A link', href: %r{/with_simple_html})
|
13
|
+
expect(@session).to have_element('a', text: 'labore', target: '_self')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should be false if the given element is not on the page' do
|
17
|
+
expect(@session).not_to have_element('a', text: 'monkey')
|
18
|
+
expect(@session).not_to have_element('a', text: 'A link', href: '/nonexistent-href')
|
19
|
+
expect(@session).not_to have_element('a', text: 'A link', href: /nonexistent/)
|
20
|
+
expect(@session).not_to have_element('a', text: 'labore', target: '_blank')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should notify if an invalid locator is specified' do
|
24
|
+
allow(Capybara::Helpers).to receive(:warn).and_return(nil)
|
25
|
+
@session.has_element?(@session)
|
26
|
+
expect(Capybara::Helpers).to have_received(:warn).with(/Called from: .+/)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Capybara::SpecHelper.spec '#has_no_element?' do
|
31
|
+
before do
|
32
|
+
@session.visit('/with_html')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should be false if the given element is on the page' do
|
36
|
+
expect(@session).not_to have_no_element('a', id: 'foo')
|
37
|
+
expect(@session).not_to have_no_element('a', text: 'A link', href: '/with_simple_html')
|
38
|
+
expect(@session).not_to have_no_element('a', text: 'labore', target: '_self')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should be true if the given element is not on the page' do
|
42
|
+
expect(@session).to have_no_element('a', text: 'monkey')
|
43
|
+
expect(@session).to have_no_element('a', text: 'A link', href: '/nonexistent-href')
|
44
|
+
expect(@session).to have_no_element('a', text: 'A link', href: %r{/nonexistent-href})
|
45
|
+
expect(@session).to have_no_element('a', text: 'labore', target: '_blank')
|
46
|
+
end
|
47
|
+
end
|
@@ -19,12 +19,17 @@ Capybara::SpecHelper.spec '#has_table?' do
|
|
19
19
|
])
|
20
20
|
end
|
21
21
|
|
22
|
-
it 'should accept rows with partial column header
|
22
|
+
it 'should accept rows with partial column header hashes' do
|
23
23
|
expect(@session).to have_table('Horizontal Headers', with_rows:
|
24
24
|
[
|
25
25
|
{ 'First Name' => 'Thomas' },
|
26
26
|
{ 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }
|
27
27
|
])
|
28
|
+
|
29
|
+
expect(@session).not_to have_table('Horizontal Headers', with_rows:
|
30
|
+
[
|
31
|
+
{ 'Unmatched Header' => 'Thomas' }
|
32
|
+
])
|
28
33
|
end
|
29
34
|
|
30
35
|
it 'should accept rows with array of cell values' do
|
@@ -103,6 +108,11 @@ Capybara::SpecHelper.spec '#has_table?' do
|
|
103
108
|
{ 'First Name' => 'Danilo', 'Last Name' => 'Walpole', 'City' => 'Johnsonville' },
|
104
109
|
{ 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }
|
105
110
|
])
|
111
|
+
|
112
|
+
expect(@session).not_to have_table('Vertical Headers', with_cols:
|
113
|
+
[
|
114
|
+
{ 'Unmatched Header' => 'Thomas' }
|
115
|
+
])
|
106
116
|
end
|
107
117
|
|
108
118
|
it 'should be false if the table is not on the page' do
|
@@ -113,10 +123,11 @@ Capybara::SpecHelper.spec '#has_table?' do
|
|
113
123
|
expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, 'First Name' => 'Thomas', 'Last Name' => 'Walpole')
|
114
124
|
expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, 'Last Name' => 'Walpole')
|
115
125
|
expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, 'First Name' => 'Walpole')
|
126
|
+
expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, 'Unmatched Header' => 'Thomas')
|
116
127
|
end
|
117
128
|
|
118
129
|
it 'should find row by cell values' do
|
119
|
-
expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, %w[Thomas Walpole])
|
130
|
+
expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, %w[Thomas Walpole Oceanside])
|
120
131
|
expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, %w[Walpole Thomas])
|
121
132
|
expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, %w[Other])
|
122
133
|
end
|
@@ -163,6 +163,12 @@ Capybara::SpecHelper.spec 'node' do
|
|
163
163
|
@session.find(:css, '#single_input').set("my entry\n")
|
164
164
|
expect(extract_results(@session)['single_input']).to eq('my entry')
|
165
165
|
end
|
166
|
+
|
167
|
+
it 'should not submit single text input forms if ended with \n and has multiple values' do
|
168
|
+
@session.visit('/form')
|
169
|
+
@session.find(:css, '#two_input_1').set("my entry\n")
|
170
|
+
expect(@session.find(:css, '#two_input_1').value).to eq("my entry\n").or(eq 'my entry')
|
171
|
+
end
|
166
172
|
end
|
167
173
|
|
168
174
|
describe '#tag_name' do
|
@@ -34,6 +34,6 @@ Capybara::SpecHelper.spec '#to_capybara_node' do
|
|
34
34
|
end.to raise_error(/^expected to find css "#second" within #<Capybara::Node::Element/)
|
35
35
|
expect do
|
36
36
|
expect(para).to have_link(href: %r{/without_simple_html})
|
37
|
-
end.to raise_error(%r{^expected to find link
|
37
|
+
end.to raise_error(%r{^expected to find link with href matching /\\/without_simple_html/ within #<Capybara::Node::Element})
|
38
38
|
end
|
39
39
|
end
|
@@ -72,7 +72,7 @@ module Capybara
|
|
72
72
|
session.reset_session!
|
73
73
|
end
|
74
74
|
|
75
|
-
before :each, psc
|
75
|
+
before :each, :psc do
|
76
76
|
SpecHelper.reset_threadsafe(bool: true, session: session)
|
77
77
|
end
|
78
78
|
|
@@ -138,4 +138,4 @@ module Capybara
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
Dir["#{File.dirname(__FILE__)}/session/**/*.rb"].
|
141
|
+
Dir["#{File.dirname(__FILE__)}/session/**/*.rb"].each { |file| require_relative file }
|
@@ -699,6 +699,11 @@ New line after and before textarea tag
|
|
699
699
|
<input type="text" name="form[single_input]" id="single_input"/>
|
700
700
|
</form>
|
701
701
|
|
702
|
+
<form id="two_input_form" action="/form" method="post">
|
703
|
+
<input type="text" name="form[two_input_1]" id="two_input_1"/>
|
704
|
+
<input type="text" name="form[two_input_2]" id="two_input_2"/>
|
705
|
+
</form>
|
706
|
+
|
702
707
|
<label>Confusion
|
703
708
|
<input type="checkbox" id="confusion_checkbox" class="confusion-checkbox confusion"/>
|
704
709
|
</label>
|
data/lib/capybara/version.rb
CHANGED
data/lib/capybara.rb
CHANGED
@@ -260,7 +260,7 @@ module Capybara
|
|
260
260
|
#
|
261
261
|
def current_driver
|
262
262
|
if threadsafe
|
263
|
-
Thread.current
|
263
|
+
Thread.current.thread_variable_get :capybara_current_driver
|
264
264
|
else
|
265
265
|
@current_driver
|
266
266
|
end || default_driver
|
@@ -269,7 +269,7 @@ module Capybara
|
|
269
269
|
|
270
270
|
def current_driver=(name)
|
271
271
|
if threadsafe
|
272
|
-
Thread.current
|
272
|
+
Thread.current.thread_variable_set :capybara_current_driver, name
|
273
273
|
else
|
274
274
|
@current_driver = name
|
275
275
|
end
|
@@ -336,7 +336,8 @@ module Capybara
|
|
336
336
|
#
|
337
337
|
def session_name
|
338
338
|
if threadsafe
|
339
|
-
Thread.current
|
339
|
+
Thread.current.thread_variable_get(:capybara_session_name) ||
|
340
|
+
Thread.current.thread_variable_set(:capybara_session_name, :default)
|
340
341
|
else
|
341
342
|
@session_name ||= :default
|
342
343
|
end
|
@@ -344,7 +345,7 @@ module Capybara
|
|
344
345
|
|
345
346
|
def session_name=(name)
|
346
347
|
if threadsafe
|
347
|
-
Thread.current
|
348
|
+
Thread.current.thread_variable_set :capybara_session_name, name
|
348
349
|
else
|
349
350
|
@session_name = name
|
350
351
|
end
|
@@ -424,7 +425,7 @@ module Capybara
|
|
424
425
|
|
425
426
|
def specified_session
|
426
427
|
if threadsafe
|
427
|
-
Thread.current
|
428
|
+
Thread.current.thread_variable_get :capybara_specified_session
|
428
429
|
else
|
429
430
|
@specified_session ||= nil
|
430
431
|
end
|
@@ -432,7 +433,7 @@ module Capybara
|
|
432
433
|
|
433
434
|
def specified_session=(session)
|
434
435
|
if threadsafe
|
435
|
-
Thread.current
|
436
|
+
Thread.current.thread_variable_set :capybara_specified_session, session
|
436
437
|
else
|
437
438
|
@specified_session = session
|
438
439
|
end
|
data/spec/minitest_spec.rb
CHANGED
@@ -60,6 +60,13 @@ class MinitestTest < Minitest::Test
|
|
60
60
|
refute_selector(:css, 'select#not_form_title')
|
61
61
|
end
|
62
62
|
|
63
|
+
def test_assert_element
|
64
|
+
visit('/with_html')
|
65
|
+
assert_element('a', text: 'A link')
|
66
|
+
assert_element(count: 1) { |el| el.text == 'A link' }
|
67
|
+
assert_no_element(text: 'Not on page')
|
68
|
+
end
|
69
|
+
|
63
70
|
def test_assert_link
|
64
71
|
visit('/with_html')
|
65
72
|
assert_link('A link')
|
@@ -163,6 +170,6 @@ RSpec.describe 'capybara/minitest' do
|
|
163
170
|
reporter.start
|
164
171
|
MinitestTest.run reporter, {}
|
165
172
|
reporter.report
|
166
|
-
expect(output.string).to include('
|
173
|
+
expect(output.string).to include('23 runs, 56 assertions, 0 failures, 0 errors, 1 skips')
|
167
174
|
end
|
168
175
|
end
|
data/spec/result_spec.rb
CHANGED
@@ -30,6 +30,15 @@ RSpec.describe Capybara::Result do
|
|
30
30
|
result.last.text == 'Delta'
|
31
31
|
end
|
32
32
|
|
33
|
+
it 'splats into multiple assignment' do
|
34
|
+
first, *rest, last = result
|
35
|
+
|
36
|
+
expect(first).to have_text 'Alpha'
|
37
|
+
expect(rest.first).to have_text 'Beta'
|
38
|
+
expect(rest.last).to have_text 'Gamma'
|
39
|
+
expect(last).to have_text 'Delta'
|
40
|
+
end
|
41
|
+
|
33
42
|
it 'can supports values_at method' do
|
34
43
|
expect(result.values_at(0, 2).map(&:text)).to eq(%w[Alpha Gamma])
|
35
44
|
end
|
@@ -503,6 +503,30 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
503
503
|
end
|
504
504
|
end
|
505
505
|
|
506
|
+
describe 'have_element matcher' do
|
507
|
+
let(:html) { '<img src="/img.jpg" alt="a JPEG"><img src="/img.png" alt="a PNG">' }
|
508
|
+
|
509
|
+
it 'gives proper description' do
|
510
|
+
expect(have_element('img').description).to eq('have visible element "img"')
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'passes if there is such a element' do
|
514
|
+
expect(html).to have_element('img', src: '/img.jpg')
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'fails if there is no such element' do
|
518
|
+
expect do
|
519
|
+
expect(html).to have_element('photo')
|
520
|
+
end.to raise_error(/expected to find element "photo"/)
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'supports compounding' do
|
524
|
+
expect(html).to have_element('img', alt: 'a JPEG').and have_element('img', src: '/img.png')
|
525
|
+
expect(html).to have_element('photo').or have_element('img', src: '/img.jpg')
|
526
|
+
expect(html).to have_no_element('photo').and have_element('img', alt: 'a PNG')
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
506
530
|
describe 'have_link matcher' do
|
507
531
|
let(:html) { '<a href="#">Just a link</a><a href="#">Another link</a>' }
|
508
532
|
|
@@ -840,10 +864,10 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
840
864
|
end
|
841
865
|
|
842
866
|
it 'gives proper description when :visible option passed' do
|
843
|
-
expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"') # rubocop:disable
|
867
|
+
expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"') # rubocop:disable Capybara/VisibilityMatcher
|
844
868
|
expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
|
845
869
|
expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
|
846
|
-
expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"') # rubocop:disable
|
870
|
+
expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"') # rubocop:disable Capybara/VisibilityMatcher
|
847
871
|
end
|
848
872
|
|
849
873
|
it 'passes if there is such a table' do
|
data/spec/rspec_spec.rb
CHANGED
@@ -37,7 +37,7 @@ RSpec.describe 'capybara/rspec' do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
it 'switches to the javascript driver when giving it as metadata', js
|
40
|
+
it 'switches to the javascript driver when giving it as metadata', :js do
|
41
41
|
expect(Capybara.current_driver).to eq(Capybara.javascript_driver)
|
42
42
|
end
|
43
43
|
|
data/spec/sauce_spec_chrome.rb
CHANGED
data/spec/selector_spec.rb
CHANGED
@@ -117,7 +117,7 @@ RSpec.describe Capybara do
|
|
117
117
|
css { |_sel| 'input[type="hidden"]' }
|
118
118
|
end
|
119
119
|
|
120
|
-
expect(string).to have_no_css('input[type="hidden"]') # rubocop:disable
|
120
|
+
expect(string).to have_no_css('input[type="hidden"]') # rubocop:disable Capybara/SpecificMatcher
|
121
121
|
expect(string).to have_selector(:hidden_field)
|
122
122
|
end
|
123
123
|
end
|
@@ -10,8 +10,13 @@ CHROME_DRIVER = :selenium_chrome
|
|
10
10
|
|
11
11
|
Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV.fetch('CI', nil) && ENV.fetch('CHROME_BETA', nil)
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
Selenium::WebDriver.logger.ignore(:selenium_manager)
|
14
|
+
|
15
|
+
browser_options = if ENV['HEADLESS']
|
16
|
+
Selenium::WebDriver::Options.chrome(args: ['--headless=new'])
|
17
|
+
else
|
18
|
+
Selenium::WebDriver::Options.chrome
|
19
|
+
end
|
15
20
|
|
16
21
|
# Chromedriver 77 requires setting this for headless mode on linux
|
17
22
|
# Different versions of Chrome/selenium-webdriver require setting differently - jus set them all
|
@@ -83,12 +88,9 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybar
|
|
83
88
|
case example.metadata[:full_description]
|
84
89
|
when /#click_link can download a file$/
|
85
90
|
skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
|
86
|
-
when /Capybara::Session selenium_chrome Capybara::Window#maximize/
|
87
|
-
pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
|
88
91
|
when /Capybara::Session selenium_chrome node #shadow_root should get visible text/
|
89
92
|
pending "Selenium doesn't currently support getting visible text for shadow root elements"
|
90
93
|
when /Capybara::Session selenium_chrome node #shadow_root/
|
91
|
-
skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
|
92
94
|
skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)
|
93
95
|
end
|
94
96
|
end
|
@@ -57,14 +57,9 @@ skipped_tests = %i[response_headers status_code trigger download]
|
|
57
57
|
|
58
58
|
Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
|
59
59
|
case example.metadata[:full_description]
|
60
|
-
when 'Capybara::Session selenium_chrome_remote #attach_file with multipart form should not break when using HTML5 multiple file input uploading multiple files',
|
61
|
-
'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once for each set of files uploaded',
|
62
|
-
'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
|
63
|
-
pending "Selenium with Remote Chrome doesn't support multiple file upload" unless selenium_gte?(3.14)
|
64
60
|
when /Capybara::Session selenium_chrome_remote node #shadow_root should get visible text/
|
65
61
|
pending "Selenium doesn't currently support getting visible text for shadow root elements"
|
66
62
|
when /Capybara::Session selenium_chrome_remote node #shadow_root/
|
67
|
-
skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
|
68
63
|
skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)
|
69
64
|
end
|
70
65
|
end
|
data/spec/selenium_spec_edge.rb
CHANGED
@@ -10,6 +10,8 @@ require 'rspec/shared_spec_matchers'
|
|
10
10
|
# Selenium::WebDriver::Edge::Service.driver_path = '/usr/local/bin/msedgedriver'
|
11
11
|
# end
|
12
12
|
|
13
|
+
Selenium::WebDriver.logger.ignore(:selenium_manager)
|
14
|
+
|
13
15
|
if Selenium::WebDriver::Platform.mac?
|
14
16
|
Selenium::WebDriver::Edge.path = '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'
|
15
17
|
end
|
@@ -17,8 +19,15 @@ end
|
|
17
19
|
Capybara.register_driver :selenium_edge do |app|
|
18
20
|
# ::Selenium::WebDriver.logger.level = "debug"
|
19
21
|
# If we don't create an options object the path set above won't be used
|
20
|
-
|
21
|
-
browser_options
|
22
|
+
|
23
|
+
# browser_options = Selenium::WebDriver::Edge::Options.new
|
24
|
+
# browser_options.add_argument('--headless') if ENV['HEADLESS']
|
25
|
+
|
26
|
+
browser_options = if ENV['HEADLESS']
|
27
|
+
Selenium::WebDriver::Options.edge(args: ['--headless=new'])
|
28
|
+
else
|
29
|
+
Selenium::WebDriver::Options.edge
|
30
|
+
end
|
22
31
|
|
23
32
|
Capybara::Selenium::Driver.new(app, browser: :edge, options: browser_options).tap do |driver|
|
24
33
|
driver.browser
|
@@ -40,8 +49,6 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_
|
|
40
49
|
pending "Edge doesn't allow clicking on file inputs"
|
41
50
|
when /Capybara::Session selenium node #shadow_root should get visible text/
|
42
51
|
pending "Selenium doesn't currently support getting visible text for shadow root elements"
|
43
|
-
when /Capybara::Session selenium Capybara::Window#maximize/
|
44
|
-
pending "Edge headless doesn't support maximize" if ENV['HEADLESS']
|
45
52
|
end
|
46
53
|
end
|
47
54
|
|
@@ -6,8 +6,10 @@ require 'shared_selenium_session'
|
|
6
6
|
require 'shared_selenium_node'
|
7
7
|
require 'rspec/shared_spec_matchers'
|
8
8
|
|
9
|
+
Selenium::WebDriver.logger.ignore(:selenium_manager)
|
10
|
+
|
9
11
|
browser_options = Selenium::WebDriver::Firefox::Options.new
|
10
|
-
browser_options.headless
|
12
|
+
browser_options.add_argument '-headless' if ENV['HEADLESS']
|
11
13
|
# browser_options.add_option("log", {"level": "trace"})
|
12
14
|
|
13
15
|
browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |profile|
|
@@ -78,13 +80,12 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capyba
|
|
78
80
|
'Capybara::Session selenium node #shadow_root should use convenience methods once moved to a descendant of the shadow root',
|
79
81
|
'Capybara::Session selenium node #shadow_root should produce error messages when failing',
|
80
82
|
'Capybara::Session with firefox with selenium driver #evaluate_script returns a shadow root'
|
81
|
-
pending "Firefox doesn't yet have full W3C shadow root support"
|
83
|
+
pending "Firefox doesn't yet have full W3C shadow root support" if firefox_lt?(113, @session)
|
82
84
|
when 'Capybara::Session selenium #fill_in should handle carriage returns with line feeds in a textarea correctly'
|
83
85
|
pending 'Not sure what firefox is doing here'
|
84
86
|
when /Capybara::Session selenium node #shadow_root should get visible text/
|
85
87
|
pending "Selenium doesn't currently support getting visible text for shadow root elements"
|
86
88
|
when /Capybara::Session selenium node #shadow_root/
|
87
|
-
skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
|
88
89
|
skip 'Not supported with this geckodriver version' if geckodriver_lt?('0.31.0', @session)
|
89
90
|
when /Capybara::Session selenium node #set should submit single text input forms if ended with \\n/
|
90
91
|
pending 'Firefox/geckodriver doesn\'t submit with values ending in \n'
|
@@ -71,14 +71,13 @@ Capybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVE
|
|
71
71
|
'Capybara::Session selenium_firefox_remote node #shadow_root should click on elements',
|
72
72
|
'Capybara::Session selenium_firefox_remote node #shadow_root should use convenience methods once moved to a descendant of the shadow root',
|
73
73
|
'Capybara::Session selenium_firefox_remote node #shadow_root should produce error messages when failing',
|
74
|
-
'Capybara::Session with firefox with selenium driver #evaluate_script returns a shadow root'
|
74
|
+
'Capybara::Session with remote firefox with selenium driver #evaluate_script returns a shadow root'
|
75
75
|
pending "Firefox doesn't yet have full W3C shadow root support"
|
76
76
|
when /Capybara::Session selenium_firefox_remote node #shadow_root should get visible text/
|
77
77
|
pending "Selenium doesn't currently support getting visible text for shadow root elements"
|
78
78
|
when /Capybara::Session selenium_firefox_remote node #shadow_root/
|
79
|
-
skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
|
80
79
|
skip 'Not supported with this geckodriver version' if geckodriver_lt?('0.31.0', @session)
|
81
|
-
when /Capybara::Session
|
80
|
+
when /Capybara::Session selenium node #set should submit single text input forms if ended with \\n/
|
82
81
|
pending 'Firefox/geckodriver doesn\'t submit with values ending in \n'
|
83
82
|
end
|
84
83
|
end
|