capybara 3.17.0 → 3.18.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e077e28912ed7973882a0394db7eb44c493b0546175f81ef6f15c8ad1ee564c1
4
- data.tar.gz: 6efae1078877ffe1578dc28d83f6d8df338dc01a162214c5b3aa3bd625c6a426
3
+ metadata.gz: 3cb32760328428839877de78f879a68af52098b0d1540c1d0de102acce58bc4b
4
+ data.tar.gz: b2c40ed521b21b43b4a44e1fe91f38b704e6c85e04829673fcc4493ff8fd217a
5
5
  SHA512:
6
- metadata.gz: 48d7420e5621c0dafbff830bfa56aba6ccf1d171d9efd0081f30f95f0cc538fa655d6fd5bef5525d13da573f51993f443f89b20af9b2241e4b9194b6ca3d2ae1
7
- data.tar.gz: e7470806d56a47cbb6a2b12690816cc0cb569d26032ccae32ad2d832f356d59235f156651a8422ba70259021f9e47a81ad43f4d3e97612891e7e98c6eb1c857e
6
+ metadata.gz: 69163470d9db2ce8831cad207bbc14aa286181357ac650b909f266fde4e50e2400a851f1451fb0091d54f859f8e270cfe267afbfc8d76b74b6e46f4a2cca21b9
7
+ data.tar.gz: 48b79d23c6c3c87e9bdcbfd2128a15b475b001699b3b15b79f208772d2dfbc8444f442267ece4d331be25b7489f6c39c869c4edcc017f4d03629d79b09dbbe57
data/History.md CHANGED
@@ -1,3 +1,14 @@
1
+ # Version 3.18.0
2
+ Release date: 2019-04-22
3
+
4
+ ### Added
5
+
6
+ * XPath Selector query optimized to make use of Regexp :text option in initial element find
7
+
8
+ ### Fixed
9
+
10
+ * Workaround issue where Chrome/chromedriver 74 can return the wrong error type when a click is intercepted
11
+
1
12
  # Version 3.17.0
2
13
  Release date: 2019-04-18
3
14
 
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
7
7
  [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=capybara&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
8
8
 
9
- **Note** You are viewing the README for the 3.17.x version of Capybara.
9
+ **Note** You are viewing the README for the 3.18.x version of Capybara.
10
10
 
11
11
 
12
12
  Capybara helps you test web applications by simulating how a real user would
@@ -22,7 +22,7 @@ module Capybara
22
22
  @actual_path = options[:url] ? uri&.to_s : uri&.request_uri
23
23
 
24
24
  if @expected_path.is_a? Regexp
25
- @actual_path.to_s.match(@expected_path)
25
+ @actual_path.to_s.match?(@expected_path)
26
26
  else
27
27
  ::Addressable::URI.parse(@expected_path) == ::Addressable::URI.parse(@actual_path)
28
28
  end
@@ -148,12 +148,22 @@ module Capybara
148
148
  end
149
149
 
150
150
  def xpath_text_conditions
151
- (options[:text] || options[:exact_text]).split.map { |txt| XPath.contains(txt) }.reduce(&:&)
151
+ text = (options[:text] || options[:exact_text])
152
+ case text
153
+ when String
154
+ text.split.map { |txt| XPath.contains(txt) }.reduce(&:&)
155
+ when Regexp
156
+ condition = XPath.current
157
+ condition = condition.uppercase if text.casefold?
158
+ Selector::RegexpDisassembler.new(text).alternated_substrings.map do |strs|
159
+ strs.flat_map(&:split).map { |str| condition.contains(str) }.reduce(:&)
160
+ end.reduce(:|)
161
+ end
152
162
  end
153
163
 
154
164
  def try_text_match_in_expression?
155
165
  first_try? &&
156
- (options[:text] || options[:exact_text]).is_a?(String) &&
166
+ (options[:text] || options[:exact_text]) &&
157
167
  @resolved_node&.respond_to?(:session) &&
158
168
  @resolved_node.session.driver.wait?
159
169
  end
@@ -436,7 +446,7 @@ module Capybara
436
446
  def matches_text_regexp?(node, regexp)
437
447
  text_visible = visible
438
448
  text_visible = :all if text_visible == :hidden
439
- !!node.text(text_visible, normalize_ws: normalize_ws).match(regexp)
449
+ node.text(text_visible, normalize_ws: normalize_ws).match?(regexp)
440
450
  end
441
451
 
442
452
  def default_visibility
@@ -13,7 +13,7 @@ module Capybara
13
13
  end
14
14
 
15
15
  def resolves_for?(node)
16
- (@actual_title = node.title).match(@search_regexp)
16
+ (@actual_title = node.title).match?(@search_regexp)
17
17
  end
18
18
 
19
19
  def failure_message
@@ -120,7 +120,7 @@ Capybara.add_selector(:link, locator_type: [String, Symbol]) do
120
120
 
121
121
  node_filter(:href) do |node, href|
122
122
  # If not a Regexp it's been handled in the main XPath
123
- (href.is_a?(Regexp) ? node[:href].match(href) : true).tap do |res|
123
+ (href.is_a?(Regexp) ? node[:href].match?(href) : true).tap do |res|
124
124
  add_error "Expected href to match #{href.inspect} but it was #{node[:href].inspect}" unless res
125
125
  end
126
126
  end
@@ -38,6 +38,13 @@ module Capybara::Selenium::Driver::ChromeDriver
38
38
 
39
39
  private
40
40
 
41
+ def clear_storage
42
+ # Chrome errors if attempt to clear storage on about:blank
43
+ # In W3C mode it crashes chromedriver
44
+ url = current_url
45
+ super unless url.nil? || url.start_with?('about:')
46
+ end
47
+
41
48
  def delete_all_cookies
42
49
  execute_cdp('Network.clearBrowserCookies')
43
50
  rescue *cdp_unsupported_errors
@@ -26,6 +26,15 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
26
26
  html5_drag_to(element)
27
27
  end
28
28
 
29
+ def click(*)
30
+ super
31
+ rescue ::Selenium::WebDriver::Error::WebDriverError => e
32
+ # chromedriver 74 (at least on mac) raises the wrong error for this
33
+ raise ::Selenium::WebDriver::Error::ElementClickInterceptedError, e.message if e.message.match?(/element click intercepted/)
34
+
35
+ raise
36
+ end
37
+
29
38
  private
30
39
 
31
40
  def file_errors
@@ -40,10 +40,12 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
40
40
  end
41
41
 
42
42
  def disabled?
43
- return true if super || (self[:disabled] == 'true')
43
+ return true if super
44
44
 
45
45
  # workaround for safaridriver reporting elements as enabled when they are nested in disabling elements
46
46
  if %w[option optgroup].include? tag_name
47
+ return true if self[:disabled] == 'true'
48
+
47
49
  find_xpath('parent::*[self::optgroup or self::select]')[0].disabled?
48
50
  else
49
51
  !find_xpath(DISABLED_BY_FIELDSET_XPATH).empty?
@@ -37,7 +37,9 @@ Capybara::SpecHelper.spec '#assert_current_path' do
37
37
  end
38
38
 
39
39
  it 'should not cause an exception when current_url is nil' do
40
- allow_any_instance_of(Capybara::Session).to receive(:current_url).and_return(nil)
40
+ allow(@session).to receive(:current_url).and_return(nil)
41
+ allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page
42
+
41
43
  expect { @session.assert_current_path(nil) }.not_to raise_error
42
44
  end
43
45
  end
@@ -65,7 +67,8 @@ Capybara::SpecHelper.spec '#assert_no_current_path?' do
65
67
  end
66
68
 
67
69
  it 'should not cause an exception when current_url is nil' do
68
- allow_any_instance_of(Capybara::Session).to receive(:current_url).and_return(nil)
70
+ allow(@session).to receive(:current_url).and_return(nil)
71
+ allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page
69
72
 
70
73
  expect { @session.assert_no_current_path('/with_html') }.not_to raise_error
71
74
  end
@@ -107,8 +107,8 @@ Capybara::SpecHelper.spec '#find' do
107
107
  end
108
108
 
109
109
  it 'should warn if passed a non-valid locator type' do
110
- expect_any_instance_of(Kernel).to receive(:warn).with(/must respond to to_xpath or be an instance of String/)
111
- expect { @session.find(:xpath, 123) }.to raise_error Exception # The exact error is not yet well defined
110
+ expect { @session.find(:xpath, 123) }.to raise_error(Exception) # The exact error is not yet well defined
111
+ .and output(/must respond to to_xpath or be an instance of String/).to_stderr
112
112
  end
113
113
  end
114
114
 
@@ -263,9 +263,8 @@ Capybara::SpecHelper.spec '#find' do
263
263
  end
264
264
 
265
265
  it 'warns when the option has no effect' do
266
- expect_any_instance_of(Kernel).to receive(:warn)
267
- .with('The :exact option only has an effect on queries using the XPath#is method. Using it with the query "#test_field" has no effect.')
268
- @session.find(:css, '#test_field', exact: true)
266
+ expect { @session.find(:css, '#test_field', exact: true) }.to \
267
+ output(/^The :exact option only has an effect on queries using the XPath#is method. Using it with the query "#test_field" has no effect/).to_stderr
269
268
  end
270
269
  end
271
270
 
@@ -81,7 +81,8 @@ Capybara::SpecHelper.spec '#has_current_path?' do
81
81
  end
82
82
 
83
83
  it 'should not raise an exception if the current_url is nil' do
84
- allow_any_instance_of(Capybara::Session).to receive(:current_url).and_return(nil)
84
+ allow(@session).to receive(:current_url).and_return(nil)
85
+ allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page
85
86
 
86
87
  # Without ignore_query option
87
88
  expect do
@@ -121,7 +122,8 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
121
122
  end
122
123
 
123
124
  it 'should not raise an exception if the current_url is nil' do
124
- allow_any_instance_of(Capybara::Session).to receive(:current_url).and_return(nil)
125
+ allow(@session).to receive(:current_url).and_return(nil)
126
+ allow(@session.page).to receive(:current_url).and_return(nil) if @session.respond_to? :page
125
127
 
126
128
  # Without ignore_query option
127
129
  expect do
@@ -24,8 +24,8 @@ Capybara::SpecHelper.spec '#matches_style?', requires: [:css] do
24
24
  end
25
25
 
26
26
  it 'deprecated has_style?' do
27
- expect_any_instance_of(Kernel).to receive(:warn).once
28
- have_style(display: /^bl/)
27
+ expect { have_style(display: /^bl/) }.to \
28
+ output(/have_style is deprecated/).to_stderr
29
29
 
30
30
  el = @session.find(:css, '#first')
31
31
  allow(el).to receive(:warn).and_return(nil)
@@ -143,8 +143,8 @@ Capybara::SpecHelper.spec '#select' do
143
143
  end
144
144
 
145
145
  it 'should warn' do
146
- expect_any_instance_of(Capybara::Node::Element).to receive(:warn).once
147
- @session.select('Other', from: 'form_title')
146
+ expect { @session.select('Other', from: 'form_title') }.to \
147
+ output(/^Attempt to select disabled option: Other/).to_stderr
148
148
  end
149
149
  end
150
150
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Capybara
4
- VERSION = '3.17.0'
4
+ VERSION = '3.18.0'
5
5
  end
@@ -80,11 +80,11 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
80
80
 
81
81
  describe '#fill_in' do
82
82
  it 'should warn that :fill_options are not supported' do
83
- allow_any_instance_of(Capybara::RackTest::Node).to receive(:warn)
84
83
  session.visit '/with_html'
85
- field = session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true }
84
+
85
+ expect { session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true } }.to \
86
+ output(/^Options passed to Node#set but the RackTest driver doesn't support any - ignoring/).to_stderr
86
87
  expect(session).to have_field('test_field', with: 'not_monkey')
87
- expect(field.base).to have_received(:warn).with("Options passed to Node#set but the RackTest driver doesn't support any - ignoring")
88
88
  end
89
89
  end
90
90
 
@@ -85,25 +85,6 @@ RSpec.describe Capybara::Result do
85
85
  expect(result.size).to eq 1
86
86
  end
87
87
 
88
- it 'should catch invalid element errors during filtering' do
89
- allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
90
- allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(
91
- instance_double('Capybara::Session', driver: instance_double('Capybara::Driver::Base', invalid_element_errors: [StandardError], wait?: false))
92
- )
93
- result = string.all('//li', text: 'Alpha')
94
- expect(result.size).to eq 0
95
- end
96
-
97
- it 'should return non-invalid element errors during filtering' do
98
- allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
99
- allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(
100
- instance_double('Capybara::Session', driver: instance_double('Capybara::Driver::Base', invalid_element_errors: [ArgumentError], wait?: false))
101
- )
102
- expect do
103
- string.all('//li', text: 'Alpha').to_a
104
- end.to raise_error(StandardError)
105
- end
106
-
107
88
  # Not a great test but it indirectly tests what is needed
108
89
  it 'should evaluate filters lazily for idx' do
109
90
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
@@ -7,6 +7,8 @@ require 'rspec/shared_spec_matchers'
7
7
 
8
8
  CHROME_DRIVER = :selenium_chrome
9
9
 
10
+ Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV['CI'] && ENV['W3C']
11
+
10
12
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
11
13
  browser_options.headless! if ENV['HEADLESS']
12
14
  browser_options.add_option(:w3c, !!ENV['W3C'])
@@ -31,7 +33,7 @@ end
31
33
 
32
34
  skipped_tests = %i[response_headers status_code trigger]
33
35
 
34
- $stdout.puts `#{Selenium::WebDriver::Chrome.driver_path} --version` if ENV['CI']
36
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Chrome) if ENV['CI']
35
37
 
36
38
  Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests do |example|
37
39
  case example.metadata[:full_description]
@@ -16,7 +16,7 @@ end
16
16
 
17
17
  skipped_tests = %i[response_headers status_code trigger modals]
18
18
 
19
- $stdout.puts `#{Selenium::WebDriver::Edge.driver_path} --version` if ENV['CI']
19
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Edge) if ENV['CI']
20
20
 
21
21
  Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_skip: skipped_tests do |example|
22
22
  case example.metadata[:description]
@@ -43,7 +43,7 @@ end
43
43
 
44
44
  skipped_tests = %i[response_headers status_code trigger]
45
45
 
46
- $stdout.puts `#{Selenium::WebDriver::Firefox.driver_path} --version` if ENV['CI']
46
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Firefox) if ENV['CI']
47
47
 
48
48
  Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capybara_skip: skipped_tests do |example|
49
49
  case example.metadata[:full_description]
@@ -5,7 +5,13 @@ require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
6
  require 'rspec/shared_spec_matchers'
7
7
 
8
- ::Selenium::WebDriver::IE.driver_path = 'C:\Tools\WebDriver\IEDriverServer.exe' if ENV['CI']
8
+ if ENV['CI']
9
+ if ::Selenium::WebDriver::Service.respond_to? :driver_path=
10
+ ::Selenium::WebDriver::IE::Service
11
+ else
12
+ ::Selenium::WebDriver::IE
13
+ end.driver_path = 'C:\Tools\WebDriver\IEDriverServer.exe'
14
+ end
9
15
 
10
16
  def selenium_host
11
17
  ENV.fetch('SELENIUM_HOST', '192.168.56.102')
@@ -58,7 +64,7 @@ TestSessions::SeleniumIE.current_window.resize_to(800, 500)
58
64
 
59
65
  skipped_tests = %i[response_headers status_code trigger modals hover form_attribute windows]
60
66
 
61
- $stdout.puts `#{Selenium::WebDriver::IE.driver_path} --version` if ENV['CI']
67
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::IE) if ENV['CI']
62
68
 
63
69
  TestSessions::SeleniumIE.current_window.resize_to(1600, 1200)
64
70
 
@@ -7,7 +7,11 @@ require 'rspec/shared_spec_matchers'
7
7
 
8
8
  SAFARI_DRIVER = :selenium_safari
9
9
 
10
- ::Selenium::WebDriver::Safari.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
10
+ if ::Selenium::WebDriver::Service.respond_to? :driver_path=
11
+ ::Selenium::WebDriver::Safari::Service
12
+ else
13
+ ::Selenium::WebDriver::Safari
14
+ end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
11
15
 
12
16
  browser_options = ::Selenium::WebDriver::Safari::Options.new
13
17
  # browser_options.headless! if ENV['HEADLESS']
@@ -33,7 +37,7 @@ end
33
37
 
34
38
  skipped_tests = %i[response_headers status_code trigger windows drag]
35
39
 
36
- $stdout.puts `#{Selenium::WebDriver::Safari.driver_path} --version` if ENV['CI']
40
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Safari) if ENV['CI']
37
41
 
38
42
  Capybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybara_skip: skipped_tests do |example|
39
43
  case example.metadata[:full_description]
@@ -52,11 +52,24 @@ module Capybara
52
52
  def remote?(session)
53
53
  session.driver.browser.is_a? ::Selenium::WebDriver::Remote::Driver
54
54
  end
55
+
56
+ def self.log_selenium_driver_version(mod)
57
+ mod = mod::Service if ::Selenium::WebDriver::Service.respond_to? :driver_path
58
+ path = mod.driver_path
59
+ path = path.call if path.respond_to? :call
60
+ $stdout.puts `#{path} --version`
61
+ end
55
62
  end
56
63
  end
57
64
 
58
65
  RSpec.configure do |config|
59
66
  Capybara::SpecHelper.configure(config)
67
+ config.expect_with :rspec do |expectations|
68
+ expectations.syntax = :expect
69
+ end
70
+ config.mock_with :rspec do |mocks|
71
+ mocks.verify_partial_doubles = true
72
+ end
60
73
  config.filter_run_including focus_: true unless ENV['CI']
61
74
  config.run_all_when_everything_filtered = true
62
75
  config.after(:suite) { SeleniumStatistics.print_results }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.17.0
4
+ version: 3.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Walpole
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain:
12
12
  - gem-public_cert.pem
13
- date: 2019-04-18 00:00:00.000000000 Z
13
+ date: 2019-04-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: addressable
@@ -334,6 +334,20 @@ dependencies:
334
334
  - - ">="
335
335
  - !ruby/object:Gem::Version
336
336
  version: 1.4.0
337
+ - !ruby/object:Gem::Dependency
338
+ name: webdrivers
339
+ requirement: !ruby/object:Gem::Requirement
340
+ requirements:
341
+ - - ">="
342
+ - !ruby/object:Gem::Version
343
+ version: 3.6.0
344
+ type: :development
345
+ prerelease: false
346
+ version_requirements: !ruby/object:Gem::Requirement
347
+ requirements:
348
+ - - ">="
349
+ - !ruby/object:Gem::Version
350
+ version: 3.6.0
337
351
  - !ruby/object:Gem::Dependency
338
352
  name: yard
339
353
  requirement: !ruby/object:Gem::Requirement