capybara 3.32.0 → 3.35.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 +99 -15
- data/README.md +9 -4
- data/lib/capybara.rb +18 -8
- data/lib/capybara/config.rb +4 -6
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/helpers.rb +25 -1
- data/lib/capybara/minitest.rb +2 -3
- data/lib/capybara/minitest/spec.rb +14 -11
- data/lib/capybara/node/actions.rb +16 -21
- data/lib/capybara/node/base.rb +6 -6
- data/lib/capybara/node/element.rb +1 -5
- data/lib/capybara/node/finders.rb +7 -6
- data/lib/capybara/node/matchers.rb +12 -12
- data/lib/capybara/node/simple.rb +5 -1
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/current_path_query.rb +14 -4
- data/lib/capybara/queries/selector_query.rb +40 -18
- 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 +7 -1
- data/lib/capybara/rack_test/browser.rb +7 -3
- data/lib/capybara/rack_test/driver.rb +1 -0
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +1 -1
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/drivers.rb +18 -12
- data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
- data/lib/capybara/registrations/servers.rb +3 -2
- data/lib/capybara/result.rb +10 -11
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/rspec/matcher_proxies.rb +1 -1
- data/lib/capybara/rspec/matchers.rb +7 -6
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_text.rb +1 -1
- data/lib/capybara/rspec/matchers/match_style.rb +5 -0
- data/lib/capybara/selector.rb +12 -3
- data/lib/capybara/selector/builders/css_builder.rb +1 -1
- data/lib/capybara/selector/builders/xpath_builder.rb +3 -1
- data/lib/capybara/selector/definition.rb +11 -9
- data/lib/capybara/selector/definition/button.rb +26 -14
- data/lib/capybara/selector/definition/css.rb +1 -1
- data/lib/capybara/selector/definition/datalist_input.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +2 -1
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/label.rb +1 -1
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/select.rb +1 -1
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector/filter_set.rb +2 -2
- data/lib/capybara/selector/selector.rb +9 -1
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
- data/lib/capybara/selenium/driver.rb +51 -7
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +9 -11
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -11
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +3 -3
- data/lib/capybara/selenium/extensions/find.rb +4 -4
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/logger_suppressor.rb +1 -1
- data/lib/capybara/selenium/node.rb +23 -6
- data/lib/capybara/selenium/nodes/chrome_node.rb +23 -5
- data/lib/capybara/selenium/nodes/firefox_node.rb +7 -2
- data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
- data/lib/capybara/selenium/patches/action_pauser.rb +4 -1
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/logs.rb +7 -9
- data/lib/capybara/server/animation_disabler.rb +8 -3
- data/lib/capybara/server/middleware.rb +4 -2
- data/lib/capybara/session.rb +23 -14
- data/lib/capybara/session/config.rb +3 -1
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/test.js +13 -1
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/check_spec.rb +6 -0
- data/lib/capybara/spec/session/click_button_spec.rb +11 -0
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/has_button_spec.rb +51 -0
- data/lib/capybara/spec/session/has_css_spec.rb +2 -1
- data/lib/capybara/spec/session/has_current_path_spec.rb +15 -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/has_text_spec.rb +0 -11
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +29 -9
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +12 -12
- data/lib/capybara/spec/test_app.rb +23 -21
- data/lib/capybara/spec/views/form.erb +28 -1
- data/lib/capybara/spec/views/with_animation.erb +8 -0
- data/lib/capybara/spec/views/with_dragula.erb +3 -1
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +3 -0
- data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +3 -7
- data/spec/basic_node_spec.rb +9 -8
- data/spec/capybara_spec.rb +1 -1
- data/spec/dsl_spec.rb +14 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +3 -2
- data/spec/rack_test_spec.rb +16 -5
- data/spec/result_spec.rb +1 -17
- data/spec/rspec/features_spec.rb +3 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +63 -51
- data/spec/rspec_spec.rb +4 -0
- data/spec/selector_spec.rb +17 -2
- data/spec/selenium_spec_chrome.rb +39 -20
- data/spec/selenium_spec_chrome_remote.rb +5 -1
- data/spec/selenium_spec_firefox.rb +15 -13
- data/spec/server_spec.rb +60 -49
- data/spec/shared_selenium_node.rb +10 -0
- data/spec/shared_selenium_session.rb +98 -7
- data/spec/spec_helper.rb +1 -1
- metadata +50 -15
- data/lib/capybara/spec/session/source_spec.rb +0 -0
data/spec/rspec_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable RSpec/MultipleDescribes
|
4
|
+
|
3
5
|
require 'spec_helper'
|
4
6
|
|
5
7
|
RSpec.describe 'capybara/rspec' do
|
@@ -143,3 +145,5 @@ feature 'Feature DSL' do
|
|
143
145
|
expect(page.body).to include('Another World')
|
144
146
|
end
|
145
147
|
end
|
148
|
+
|
149
|
+
# rubocop:enable RSpec/MultipleDescribes
|
data/spec/selector_spec.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe Capybara do
|
6
|
+
include Capybara::RSpecMatchers
|
6
7
|
describe 'Selectors' do
|
7
8
|
let :string do
|
8
9
|
described_class.string <<-STRING
|
@@ -326,9 +327,23 @@ RSpec.describe Capybara do
|
|
326
327
|
expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
|
327
328
|
end
|
328
329
|
|
329
|
-
it 'accepts Regexp for CSS
|
330
|
+
it 'accepts Regexp for CSS based selectors' do
|
330
331
|
expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
|
331
332
|
end
|
333
|
+
|
334
|
+
it 'accepts Regexp for individual class names for XPath based selectors' do
|
335
|
+
expect(string.find(:custom_xpath_selector, './/div', class: [/random/, 'some'])[:id]).to eq 'random_words'
|
336
|
+
expect(string.find(:custom_xpath_selector, './/div', class: [/om/, /wor/])[:id]).to eq 'random_words'
|
337
|
+
expect { string.find(:custom_xpath_selector, './/div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
|
338
|
+
expect { string.find(:custom_xpath_selector, './/div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'accepts Regexp for individual class names for CSS based selectors' do
|
342
|
+
expect(string.find(:custom_css_selector, 'div', class: [/random/])[:id]).to eq 'random_words'
|
343
|
+
expect(string.find(:custom_css_selector, 'div', class: [/om/, /wor/, 'some'])[:id]).to eq 'random_words'
|
344
|
+
expect { string.find(:custom_css_selector, 'div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
|
345
|
+
expect { string.find(:custom_css_selector, 'div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
|
346
|
+
end
|
332
347
|
end
|
333
348
|
|
334
349
|
context 'with :style option' do
|
@@ -476,7 +491,7 @@ RSpec.describe Capybara do
|
|
476
491
|
end
|
477
492
|
|
478
493
|
describe ':link_or_button selector' do
|
479
|
-
around
|
494
|
+
around do |example|
|
480
495
|
described_class.modify_selector(:link_or_button) do
|
481
496
|
expression_filter(:random) { |xpath, _| xpath } # do nothing filter
|
482
497
|
end
|
@@ -19,39 +19,56 @@ browser_options.add_preference('download.default_directory', Capybara.save_path)
|
|
19
19
|
browser_options.add_preference(:download, default_directory: Capybara.save_path)
|
20
20
|
|
21
21
|
Capybara.register_driver :selenium_chrome do |app|
|
22
|
-
Capybara::Selenium::Driver.
|
22
|
+
version = Capybara::Selenium::Driver.load_selenium
|
23
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
24
|
+
driver_options = { browser: :chrome, timeout: 30 }.tap do |opts|
|
25
|
+
opts[options_key] = browser_options
|
26
|
+
end
|
27
|
+
|
28
|
+
Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
|
23
29
|
# Set download dir for Chrome < 77
|
24
30
|
driver.browser.download_path = Capybara.save_path
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
28
34
|
Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
version = Capybara::Selenium::Driver.load_selenium
|
36
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
37
|
+
chrome_options = { browser: :chrome, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
|
38
|
+
opts[options_key] = browser_options
|
39
|
+
end
|
40
|
+
|
41
|
+
Capybara::Selenium::Driver.new(app, **chrome_options)
|
34
42
|
end
|
35
43
|
|
36
44
|
Capybara.register_driver :selenium_chrome_not_clear_session_storage do |app|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
version = Capybara::Selenium::Driver.load_selenium
|
46
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
47
|
+
chrome_options = { browser: :chrome, clear_session_storage: false }.tap do |opts|
|
48
|
+
opts[options_key] = browser_options
|
49
|
+
end
|
50
|
+
|
51
|
+
Capybara::Selenium::Driver.new(app, **chrome_options)
|
42
52
|
end
|
43
53
|
|
44
54
|
Capybara.register_driver :selenium_chrome_not_clear_local_storage do |app|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
version = Capybara::Selenium::Driver.load_selenium
|
56
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
57
|
+
chrome_options = { browser: :chrome, clear_local_storage: false }.tap do |opts|
|
58
|
+
opts[options_key] = browser_options
|
59
|
+
end
|
60
|
+
Capybara::Selenium::Driver.new(app, **chrome_options)
|
50
61
|
end
|
51
62
|
|
52
63
|
Capybara.register_driver :selenium_driver_subclass_with_chrome do |app|
|
64
|
+
version = Capybara::Selenium::Driver.load_selenium
|
65
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
53
66
|
subclass = Class.new(Capybara::Selenium::Driver)
|
54
|
-
|
67
|
+
chrome_options = { browser: :chrome, timeout: 30 }.tap do |opts|
|
68
|
+
opts[options_key] = browser_options
|
69
|
+
end
|
70
|
+
|
71
|
+
subclass.new(app, **chrome_options)
|
55
72
|
end
|
56
73
|
|
57
74
|
module TestSessions
|
@@ -70,8 +87,6 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybar
|
|
70
87
|
pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
|
71
88
|
when /Capybara::Window#fullscreen should be able to fullscreen the window/
|
72
89
|
skip 'Chromedriver hangs on attempts to fullscreen in headless mode' if ENV['HEADLESS']
|
73
|
-
when /details non-summary descendants should be non-visible/
|
74
|
-
pending 'Chromedriver built-in is_displayed is currently broken' if ENV['W3C'] == 'false'
|
75
90
|
when /node #right_click delay should delay the mouse up/
|
76
91
|
skip "Legacy selenium doesn't support separate right button down/up" if ENV['W3C'] == 'false'
|
77
92
|
end
|
@@ -173,7 +188,7 @@ RSpec.describe 'Capybara::Session with chrome' do
|
|
173
188
|
before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
|
174
189
|
|
175
190
|
it 'does not error getting log types' do
|
176
|
-
skip if Gem::
|
191
|
+
skip if Gem::Requirement.new('< 75.0.3770.90').satisfied_by? chromedriver_version
|
177
192
|
expect do
|
178
193
|
session.driver.browser.manage.logs.available_types
|
179
194
|
end.not_to raise_error
|
@@ -185,4 +200,8 @@ RSpec.describe 'Capybara::Session with chrome' do
|
|
185
200
|
end.not_to raise_error
|
186
201
|
end
|
187
202
|
end
|
203
|
+
|
204
|
+
def chromedriver_version
|
205
|
+
Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
|
206
|
+
end
|
188
207
|
end
|
@@ -81,7 +81,7 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
|
|
81
81
|
before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
|
82
82
|
|
83
83
|
it 'does not error when getting log types' do
|
84
|
-
skip
|
84
|
+
skip unless Gem::Requirement.new('>= 75.0.3770.90').satisfied_by? chromedriver_version
|
85
85
|
expect do
|
86
86
|
session.driver.browser.manage.logs.available_types
|
87
87
|
end.not_to raise_error
|
@@ -93,4 +93,8 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
|
|
93
93
|
end.not_to raise_error
|
94
94
|
end
|
95
95
|
end
|
96
|
+
|
97
|
+
def chromedriver_version
|
98
|
+
Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
|
99
|
+
end
|
96
100
|
end
|
@@ -14,28 +14,30 @@ browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |prof
|
|
14
14
|
profile['browser.download.dir'] = Capybara.save_path
|
15
15
|
profile['browser.download.folderList'] = 2
|
16
16
|
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
|
17
|
+
profile['browser.startup.homepage'] = 'about:blank' # workaround bug in Selenium 4 alpha4-7
|
17
18
|
end
|
18
19
|
|
19
20
|
Capybara.register_driver :selenium_firefox do |app|
|
20
21
|
# ::Selenium::WebDriver.logger.level = "debug"
|
21
|
-
Capybara::Selenium::Driver.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
timeout: 31
|
22
|
+
version = Capybara::Selenium::Driver.load_selenium
|
23
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
24
|
+
driver_options = { browser: :firefox, timeout: 31 }.tap do |opts|
|
25
|
+
opts[options_key] = browser_options
|
26
26
|
# Get a trace level log from geckodriver
|
27
27
|
# :driver_opts => { args: ['-vv'] }
|
28
|
-
|
28
|
+
end
|
29
|
+
|
30
|
+
Capybara::Selenium::Driver.new(app, **driver_options)
|
29
31
|
end
|
30
32
|
|
31
33
|
Capybara.register_driver :selenium_firefox_not_clear_storage do |app|
|
32
|
-
Capybara::Selenium::Driver.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
)
|
34
|
+
version = Capybara::Selenium::Driver.load_selenium
|
35
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
36
|
+
driver_options = { browser: :firefox, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
|
37
|
+
opts[options_key] = browser_options
|
38
|
+
end
|
39
|
+
|
40
|
+
Capybara::Selenium::Driver.new(app, **driver_options)
|
39
41
|
end
|
40
42
|
|
41
43
|
module TestSessions
|
data/spec/server_spec.rb
CHANGED
@@ -75,25 +75,21 @@ RSpec.describe Capybara::Server do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'should handle that getting available ports fails randomly' do
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
begin
|
86
|
-
call_count.zero? ? d_server : m.call(*args)
|
87
|
-
ensure
|
88
|
-
call_count += 1
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
port = described_class.new(Object.new, host: '0.0.0.0').port
|
93
|
-
expect(port).not_to eq(server_port)
|
78
|
+
# Use a port to force a EADDRINUSE error to be generated
|
79
|
+
server = TCPServer.new('0.0.0.0', 0)
|
80
|
+
server_port = server.addr[1]
|
81
|
+
d_server = instance_double('TCPServer', addr: [nil, server_port, nil, nil], close: nil)
|
82
|
+
call_count = 0
|
83
|
+
allow(TCPServer).to receive(:new).and_wrap_original do |m, *args|
|
84
|
+
call_count.zero? ? d_server : m.call(*args)
|
94
85
|
ensure
|
95
|
-
|
86
|
+
call_count += 1
|
96
87
|
end
|
88
|
+
|
89
|
+
port = described_class.new(Object.new, host: '0.0.0.0').port
|
90
|
+
expect(port).not_to eq(server_port)
|
91
|
+
ensure
|
92
|
+
server&.close
|
97
93
|
end
|
98
94
|
|
99
95
|
it 'should return its #base_url' do
|
@@ -103,30 +99,47 @@ RSpec.describe Capybara::Server do
|
|
103
99
|
expect(uri.to_hash).to include(scheme: 'http', host: server.host, port: server.port)
|
104
100
|
end
|
105
101
|
|
106
|
-
it 'should
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
102
|
+
it 'should call #clamp on the puma configuration to ensure that environment is a string' do
|
103
|
+
Capybara.server = :puma
|
104
|
+
app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }
|
105
|
+
require 'puma'
|
106
|
+
allow(Puma::Server).to receive(:new).and_wrap_original do |method, app, events, options|
|
107
|
+
# If #clamp is not called on the puma config then this will be a Proc
|
108
|
+
expect(options.fetch(:environment)).to be_a(String)
|
109
|
+
method.call(app, events, options)
|
110
|
+
end
|
111
|
+
server = described_class.new(app_proc).boot
|
112
|
+
expect(Puma::Server).to have_received(:new).with(
|
113
|
+
anything,
|
114
|
+
anything,
|
115
|
+
satisfy { |opts| opts.final_options[:Port] == server.port }
|
116
|
+
)
|
117
|
+
ensure
|
118
|
+
Capybara.server = :default
|
119
|
+
end
|
113
120
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
121
|
+
it 'should support SSL' do
|
122
|
+
key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')
|
123
|
+
cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')
|
124
|
+
Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
|
125
|
+
app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
|
126
|
+
server = described_class.new(app).boot
|
119
127
|
|
120
|
-
|
121
|
-
|
122
|
-
|
128
|
+
expect do
|
129
|
+
Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }
|
130
|
+
end.to(raise_error do |e|
|
131
|
+
expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true
|
132
|
+
end)
|
123
133
|
|
124
|
-
|
125
|
-
|
126
|
-
expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)
|
127
|
-
ensure
|
128
|
-
Capybara.server = :default
|
134
|
+
res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
|
135
|
+
https.get('/')
|
129
136
|
end
|
137
|
+
|
138
|
+
expect(res.body).to include('Hello SSL Server!')
|
139
|
+
uri = ::Addressable::URI.parse(server.base_url)
|
140
|
+
expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)
|
141
|
+
ensure
|
142
|
+
Capybara.server = :default
|
130
143
|
end
|
131
144
|
|
132
145
|
context 'When Capybara.reuse_server is true' do
|
@@ -224,19 +237,17 @@ RSpec.describe Capybara::Server do
|
|
224
237
|
end
|
225
238
|
|
226
239
|
it 'should raise server errors when the server errors before the timeout' do
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
raise 'kaboom'
|
231
|
-
end
|
232
|
-
Capybara.server = :kaboom
|
233
|
-
|
234
|
-
expect do
|
235
|
-
described_class.new(proc { |e| }).boot
|
236
|
-
end.to raise_error(RuntimeError, 'kaboom')
|
237
|
-
ensure
|
238
|
-
Capybara.server = :default
|
240
|
+
Capybara.register_server :kaboom do
|
241
|
+
sleep 0.1
|
242
|
+
raise 'kaboom'
|
239
243
|
end
|
244
|
+
Capybara.server = :kaboom
|
245
|
+
|
246
|
+
expect do
|
247
|
+
described_class.new(proc { |e| }).boot
|
248
|
+
end.to raise_error(RuntimeError, 'kaboom')
|
249
|
+
ensure
|
250
|
+
Capybara.server = :default
|
240
251
|
end
|
241
252
|
|
242
253
|
it 'should raise an error when there are pending requests' do
|
@@ -35,6 +35,16 @@ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
describe '#set' do
|
39
|
+
it 'respects maxlength when using rapid set' do
|
40
|
+
session.visit('/form')
|
41
|
+
inp = session.find(:css, '#long_length')
|
42
|
+
value = (0...50).map { |i| ((i % 26) + 65).chr }.join
|
43
|
+
inp.set(value, rapid: true)
|
44
|
+
expect(inp.value).to eq value[0...35]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
38
48
|
describe '#visible?' do
|
39
49
|
let(:bridge) do
|
40
50
|
session.driver.browser.send(:bridge)
|
@@ -160,6 +160,15 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
160
160
|
fill_options: { clear: :none })
|
161
161
|
expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnHarry')
|
162
162
|
end
|
163
|
+
|
164
|
+
it 'works with rapid fill' do
|
165
|
+
pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)
|
166
|
+
|
167
|
+
long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join
|
168
|
+
session.visit('/form')
|
169
|
+
session.fill_in('form_first_name', with: long_string, fill_options: { clear: :none })
|
170
|
+
expect(session.find(:fillable_field, 'form_first_name').value).to eq("John#{long_string}")
|
171
|
+
end
|
163
172
|
end
|
164
173
|
|
165
174
|
describe '#fill_in with Date' do
|
@@ -205,6 +214,26 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
205
214
|
end
|
206
215
|
end
|
207
216
|
|
217
|
+
describe '#fill_in with Emoji' do
|
218
|
+
it 'sends emojis' do
|
219
|
+
session.visit('/form')
|
220
|
+
session.fill_in('form_first_name', with: 'a😀cd😴 🛌🏽🇵🇹 e🤾🏽♀️f')
|
221
|
+
expect(session.find(:fillable_field, 'form_first_name').value).to eq('a😀cd😴 🛌🏽🇵🇹 e🤾🏽♀️f')
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe '#send_keys' do
|
226
|
+
it 'defaults to sending keys to the document.activeElement' do
|
227
|
+
session.visit('/form')
|
228
|
+
|
229
|
+
expect(session.evaluate_script('document.activeElement')).to eq(session.find('//body'))
|
230
|
+
|
231
|
+
session.send_keys(:tab)
|
232
|
+
|
233
|
+
expect(session.evaluate_script('document.activeElement')).to eq(session.first(:field))
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
208
237
|
describe '#path' do
|
209
238
|
it 'returns xpath' do
|
210
239
|
# this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver
|
@@ -360,15 +389,64 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
360
389
|
|
361
390
|
it 'should disable CSS animations (set to 0s)' do
|
362
391
|
@animation_session.visit('with_animation')
|
392
|
+
sleep 1
|
363
393
|
@animation_session.click_link('animate me away')
|
364
394
|
expect(@animation_session).to have_no_link('animate me away', wait: 0.5)
|
365
395
|
end
|
366
396
|
|
367
397
|
it 'should disable CSS animations on pseudo elements (set to 0s)' do
|
368
398
|
@animation_session.visit('with_animation')
|
399
|
+
sleep 1
|
369
400
|
@animation_session.find_link('animate me away').right_click
|
370
401
|
expect(@animation_session).to have_content('Animation Ended', wait: 0.1)
|
371
402
|
end
|
403
|
+
|
404
|
+
it 'should scroll the page instantly', requires: [:js] do
|
405
|
+
@animation_session.visit('with_animation')
|
406
|
+
scroll_y = @animation_session.evaluate_script(<<~JS)
|
407
|
+
(function(){
|
408
|
+
window.scrollTo(0,500);
|
409
|
+
return window.scrollY;
|
410
|
+
})()
|
411
|
+
JS
|
412
|
+
expect(scroll_y).to eq 500
|
413
|
+
end
|
414
|
+
|
415
|
+
it 'should scroll the page instantly without jquery animation', requires: [:js] do
|
416
|
+
@animation_session.visit('with_jquery_animation')
|
417
|
+
@animation_session.click_link('scroll top 500')
|
418
|
+
scroll_y = @animation_session.evaluate_script('window.scrollY')
|
419
|
+
expect(scroll_y).to eq 500
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
context 'when set to `false`' do
|
424
|
+
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
425
|
+
skip "Safari doesn't support multiple sessions" if safari?(session)
|
426
|
+
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
|
427
|
+
# it doesn't affect any of these tests because the settings are applied per-session
|
428
|
+
Capybara.disable_animation = false
|
429
|
+
@animation_session = Capybara::Session.new(session.mode, TestApp.new)
|
430
|
+
end
|
431
|
+
|
432
|
+
it 'should scroll the page with a smooth animation', requires: [:js] do
|
433
|
+
@animation_session.visit('with_animation')
|
434
|
+
scroll_y = @animation_session.evaluate_script(<<~JS)
|
435
|
+
(function(){
|
436
|
+
window.scrollTo(0,500);
|
437
|
+
return window.scrollY;
|
438
|
+
})()
|
439
|
+
JS
|
440
|
+
# measured over 0.5 seconds: 0, 75, 282, 478, 500
|
441
|
+
expect(scroll_y).to be < 500
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'should scroll the page with jquery animation', requires: [:js] do
|
445
|
+
@animation_session.visit('with_jquery_animation')
|
446
|
+
@animation_session.click_link('scroll top 500')
|
447
|
+
scroll_y = @animation_session.evaluate_script('window.scrollY')
|
448
|
+
expect(scroll_y).to be < 500
|
449
|
+
end
|
372
450
|
end
|
373
451
|
|
374
452
|
context 'if we pass in css that matches elements' do
|
@@ -382,12 +460,14 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
382
460
|
|
383
461
|
it 'should disable CSS transitions' do
|
384
462
|
@animation_session_with_matching_css.visit('with_animation')
|
463
|
+
sleep 1
|
385
464
|
@animation_session_with_matching_css.click_link('transition me away')
|
386
465
|
expect(@animation_session_with_matching_css).to have_no_link('transition me away', wait: 0.5)
|
387
466
|
end
|
388
467
|
|
389
468
|
it 'should disable CSS animations' do
|
390
469
|
@animation_session_with_matching_css.visit('with_animation')
|
470
|
+
sleep 1
|
391
471
|
@animation_session_with_matching_css.click_link('animate me away')
|
392
472
|
expect(@animation_session_with_matching_css).to have_no_link('animate me away', wait: 0.5)
|
393
473
|
end
|
@@ -404,6 +484,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
404
484
|
|
405
485
|
it 'should not disable CSS transitions' do
|
406
486
|
@animation_session_without_matching_css.visit('with_animation')
|
487
|
+
sleep 1
|
407
488
|
@animation_session_without_matching_css.click_link('transition me away')
|
408
489
|
sleep 0.5 # Wait long enough for click to have been processed
|
409
490
|
expect(@animation_session_without_matching_css).to have_link('transition me away', wait: false)
|
@@ -412,6 +493,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
412
493
|
|
413
494
|
it 'should not disable CSS animations' do
|
414
495
|
@animation_session_without_matching_css.visit('with_animation')
|
496
|
+
sleep 1
|
415
497
|
@animation_session_without_matching_css.click_link('animate me away')
|
416
498
|
sleep 0.5 # Wait long enough for click to have been processed
|
417
499
|
expect(@animation_session_without_matching_css).to have_link('animate me away', wait: false)
|
@@ -425,7 +507,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
425
507
|
it 'can find html5 svg elements' do
|
426
508
|
session.visit('with_html5_svg')
|
427
509
|
expect(session).to have_selector(:element, :svg)
|
428
|
-
expect(session).to have_selector(:element, :rect, visible:
|
510
|
+
expect(session).to have_selector(:element, :rect, visible: :visible)
|
429
511
|
expect(session).to have_selector(:element, :circle)
|
430
512
|
expect(session).to have_selector(:element, :linearGradient, visible: :all)
|
431
513
|
end
|
@@ -441,21 +523,30 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
441
523
|
context 'controlled components' do
|
442
524
|
it 'can set and clear a text field' do
|
443
525
|
skip "This test doesn't support older browsers" if ie?(session)
|
444
|
-
|
445
|
-
# session.all(:css, 'h2#controlled-components ~ p a', text: 'Try it on CodePen')[0].click
|
446
|
-
# copied into local view
|
526
|
+
|
447
527
|
session.visit 'react'
|
448
|
-
|
449
|
-
# session.within_frame(:css, 'iframe.result-iframe:not([src=""])', wait: 10) do
|
528
|
+
|
450
529
|
session.fill_in('Name:', with: 'abc')
|
451
530
|
session.accept_prompt 'A name was submitted: abc' do
|
452
531
|
session.click_button('Submit')
|
453
532
|
end
|
533
|
+
|
454
534
|
session.fill_in('Name:', with: '')
|
455
535
|
session.accept_prompt(/A name was submitted: $/) do
|
456
536
|
session.click_button('Submit')
|
457
537
|
end
|
458
|
-
|
538
|
+
end
|
539
|
+
|
540
|
+
it 'works with rapid fill' do
|
541
|
+
skip "This test doesn't support older browsers" if ie?(session)
|
542
|
+
|
543
|
+
session.visit 'react'
|
544
|
+
long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join
|
545
|
+
|
546
|
+
session.fill_in('Name:', with: long_string)
|
547
|
+
session.accept_prompt "A name was submitted: #{long_string}" do
|
548
|
+
session.click_button('Submit')
|
549
|
+
end
|
459
550
|
end
|
460
551
|
end
|
461
552
|
end
|