capybara 3.33.0 → 3.35.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +83 -15
  3. data/README.md +0 -2
  4. data/lib/capybara.rb +1 -1
  5. data/lib/capybara/config.rb +4 -6
  6. data/lib/capybara/driver/base.rb +4 -0
  7. data/lib/capybara/helpers.rb +25 -1
  8. data/lib/capybara/minitest.rb +2 -2
  9. data/lib/capybara/minitest/spec.rb +14 -11
  10. data/lib/capybara/node/actions.rb +1 -2
  11. data/lib/capybara/node/base.rb +6 -6
  12. data/lib/capybara/node/element.rb +1 -5
  13. data/lib/capybara/node/finders.rb +7 -6
  14. data/lib/capybara/node/matchers.rb +8 -6
  15. data/lib/capybara/node/simple.rb +5 -1
  16. data/lib/capybara/queries/ancestor_query.rb +1 -1
  17. data/lib/capybara/queries/current_path_query.rb +14 -4
  18. data/lib/capybara/queries/selector_query.rb +32 -17
  19. data/lib/capybara/queries/sibling_query.rb +1 -1
  20. data/lib/capybara/queries/text_query.rb +2 -2
  21. data/lib/capybara/rack_test/browser.rb +7 -3
  22. data/lib/capybara/rack_test/driver.rb +1 -0
  23. data/lib/capybara/rack_test/form.rb +1 -1
  24. data/lib/capybara/rack_test/node.rb +1 -1
  25. data/lib/capybara/registration_container.rb +3 -3
  26. data/lib/capybara/registrations/drivers.rb +18 -12
  27. data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
  28. data/lib/capybara/registrations/servers.rb +2 -1
  29. data/lib/capybara/result.rb +6 -10
  30. data/lib/capybara/rspec.rb +2 -0
  31. data/lib/capybara/rspec/matcher_proxies.rb +1 -1
  32. data/lib/capybara/rspec/matchers.rb +7 -6
  33. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  34. data/lib/capybara/rspec/matchers/match_style.rb +5 -0
  35. data/lib/capybara/selector.rb +2 -2
  36. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  37. data/lib/capybara/selector/builders/xpath_builder.rb +3 -1
  38. data/lib/capybara/selector/definition.rb +6 -5
  39. data/lib/capybara/selector/definition/button.rb +26 -15
  40. data/lib/capybara/selector/definition/css.rb +1 -1
  41. data/lib/capybara/selector/definition/datalist_input.rb +1 -1
  42. data/lib/capybara/selector/definition/element.rb +2 -1
  43. data/lib/capybara/selector/definition/label.rb +1 -1
  44. data/lib/capybara/selector/definition/select.rb +1 -1
  45. data/lib/capybara/selector/definition/table_row.rb +2 -2
  46. data/lib/capybara/selector/filter_set.rb +2 -2
  47. data/lib/capybara/selector/selector.rb +5 -1
  48. data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
  49. data/lib/capybara/selenium/driver.rb +47 -5
  50. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +3 -3
  51. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +3 -3
  52. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  53. data/lib/capybara/selenium/extensions/find.rb +4 -4
  54. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  55. data/lib/capybara/selenium/logger_suppressor.rb +8 -2
  56. data/lib/capybara/selenium/node.rb +6 -3
  57. data/lib/capybara/selenium/nodes/chrome_node.rb +23 -5
  58. data/lib/capybara/selenium/nodes/firefox_node.rb +6 -1
  59. data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
  60. data/lib/capybara/selenium/patches/atoms.rb +4 -4
  61. data/lib/capybara/selenium/patches/logs.rb +4 -4
  62. data/lib/capybara/server/animation_disabler.rb +8 -3
  63. data/lib/capybara/server/middleware.rb +4 -2
  64. data/lib/capybara/session.rb +20 -11
  65. data/lib/capybara/session/matchers.rb +11 -11
  66. data/lib/capybara/spec/public/test.js +6 -1
  67. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  68. data/lib/capybara/spec/session/check_spec.rb +6 -0
  69. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  70. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  71. data/lib/capybara/spec/session/has_button_spec.rb +35 -0
  72. data/lib/capybara/spec/session/has_css_spec.rb +2 -1
  73. data/lib/capybara/spec/session/has_current_path_spec.rb +13 -0
  74. data/lib/capybara/spec/session/has_text_spec.rb +0 -11
  75. data/lib/capybara/spec/session/html_spec.rb +1 -1
  76. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  77. data/lib/capybara/spec/session/node_spec.rb +23 -3
  78. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  79. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  80. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  81. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  82. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  83. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  84. data/lib/capybara/spec/spec_helper.rb +11 -12
  85. data/lib/capybara/spec/test_app.rb +9 -3
  86. data/lib/capybara/spec/views/form.erb +23 -1
  87. data/lib/capybara/spec/views/with_animation.erb +8 -0
  88. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  89. data/lib/capybara/spec/views/with_js.erb +2 -0
  90. data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
  91. data/lib/capybara/version.rb +1 -1
  92. data/lib/capybara/window.rb +3 -7
  93. data/spec/basic_node_spec.rb +9 -8
  94. data/spec/dsl_spec.rb +1 -1
  95. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  96. data/spec/minitest_spec.rb +2 -1
  97. data/spec/rack_test_spec.rb +15 -5
  98. data/spec/rspec/features_spec.rb +3 -1
  99. data/spec/rspec/scenarios_spec.rb +4 -0
  100. data/spec/rspec/shared_spec_matchers.rb +2 -2
  101. data/spec/rspec_spec.rb +4 -0
  102. data/spec/selector_spec.rb +16 -1
  103. data/spec/selenium_spec_chrome.rb +39 -18
  104. data/spec/selenium_spec_chrome_remote.rb +5 -1
  105. data/spec/selenium_spec_firefox.rb +15 -13
  106. data/spec/server_spec.rb +19 -0
  107. data/spec/shared_selenium_session.rb +74 -1
  108. metadata +47 -13
  109. data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -100,7 +100,7 @@ module Capybara
100
100
  # @param [Boolean] check_ancestors Whether to inherit visibility from ancestors
101
101
  # @return [Boolean] Whether the element is visible
102
102
  #
103
- def visible?(check_ancestors = true)
103
+ def visible?(check_ancestors = true) # rubocop:disable Style/OptionalBooleanParameter
104
104
  return false if (tag_name == 'input') && (native[:type] == 'hidden')
105
105
  return false if tag_name == 'template'
106
106
 
@@ -148,6 +148,10 @@ module Capybara
148
148
  native.has_attribute?('multiple')
149
149
  end
150
150
 
151
+ def readonly?
152
+ native.has_attribute?('readonly')
153
+ end
154
+
151
155
  def synchronize(_seconds = nil)
152
156
  yield # simple nodes don't need to wait
153
157
  end
@@ -16,7 +16,7 @@ module Capybara
16
16
  end
17
17
  end
18
18
 
19
- def description(applied = false)
19
+ def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter
20
20
  child_query = @child_node&.instance_variable_get(:@query)
21
21
  desc = super
22
22
  desc += " that is an ancestor of #{child_query.description}" if child_query
@@ -6,26 +6,30 @@ module Capybara
6
6
  # @api private
7
7
  module Queries
8
8
  class CurrentPathQuery < BaseQuery
9
- def initialize(expected_path, **options)
9
+ def initialize(expected_path, **options, &optional_filter_block)
10
10
  super(options)
11
11
  @expected_path = expected_path
12
12
  @options = {
13
13
  url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path || '').hostname.nil?,
14
14
  ignore_query: false
15
15
  }.merge(options)
16
+ @filter_block = optional_filter_block
16
17
  assert_valid_keys
17
18
  end
18
19
 
19
20
  def resolves_for?(session)
20
21
  uri = ::Addressable::URI.parse(session.current_url)
21
- uri&.query = nil if options[:ignore_query]
22
- @actual_path = options[:url] ? uri&.to_s : uri&.request_uri
22
+ @actual_path = (options[:ignore_query] ? uri&.omit(:query) : uri).yield_self do |u|
23
+ options[:url] ? u&.to_s : u&.request_uri
24
+ end
23
25
 
24
- if @expected_path.is_a? Regexp
26
+ res = if @expected_path.is_a? Regexp
25
27
  @actual_path.to_s.match?(@expected_path)
26
28
  else
27
29
  ::Addressable::URI.parse(@expected_path) == ::Addressable::URI.parse(@actual_path)
28
30
  end
31
+
32
+ res && matches_filter_block?(uri)
29
33
  end
30
34
 
31
35
  def failure_message
@@ -38,6 +42,12 @@ module Capybara
38
42
 
39
43
  private
40
44
 
45
+ def matches_filter_block?(url)
46
+ return true unless @filter_block
47
+
48
+ @filter_block.call(url)
49
+ end
50
+
41
51
  def failure_message_helper(negated = '')
42
52
  verb = @expected_path.is_a?(Regexp) ? 'match' : 'equal'
43
53
  "expected #{@actual_path.inspect}#{negated} to #{verb} #{@expected_path.inspect}"
@@ -55,7 +55,7 @@ module Capybara
55
55
  def name; selector.name; end
56
56
  def label; selector.label || selector.name; end
57
57
 
58
- def description(only_applied = false)
58
+ def description(only_applied = false) # rubocop:disable Style/OptionalBooleanParameter
59
59
  desc = +''
60
60
  show_for = show_for_stage(only_applied)
61
61
 
@@ -95,11 +95,9 @@ module Capybara
95
95
  desc << ' that also matches the custom filter block' if @filter_block && show_for[:node]
96
96
 
97
97
  desc << " within #{@resolved_node.inspect}" if describe_within?
98
- if locator.is_a?(String) && locator.start_with?('#', './/', '//')
99
- unless selector.raw_locator?
100
- desc << "\nNote: It appears you may be passing a CSS selector or XPath expression rather than a locator. " \
101
- "Please see the documentation for acceptable locator values.\n\n"
102
- end
98
+ if locator.is_a?(String) && locator.start_with?('#', './/', '//') && !selector.raw_locator?
99
+ desc << "\nNote: It appears you may be passing a CSS selector or XPath expression rather than a locator. " \
100
+ "Please see the documentation for acceptable locator values.\n\n"
103
101
  end
104
102
  desc
105
103
  end
@@ -239,17 +237,18 @@ module Capybara
239
237
  hints[:styles] = options[:style] if use_default_style_filter?
240
238
  hints[:position] = true if use_spatial_filter?
241
239
 
242
- if selector_format == :css
243
- if node.method(:find_css).arity != 1
244
- node.find_css(css, **hints)
245
- else
240
+ case selector_format
241
+ when :css
242
+ if node.method(:find_css).arity == 1
246
243
  node.find_css(css)
247
- end
248
- elsif selector_format == :xpath
249
- if node.method(:find_xpath).arity != 1
250
- node.find_xpath(xpath(exact), **hints)
251
244
  else
245
+ node.find_css(css, **hints)
246
+ end
247
+ when :xpath
248
+ if node.method(:find_xpath).arity == 1
252
249
  node.find_xpath(xpath(exact))
250
+ else
251
+ node.find_xpath(xpath(exact), **hints)
253
252
  end
254
253
  else
255
254
  raise ArgumentError, "Unknown format: #{selector_format}"
@@ -483,9 +482,25 @@ module Capybara
483
482
  end
484
483
 
485
484
  def matches_class_filter?(node)
486
- return true unless use_default_class_filter? && options[:class].is_a?(Regexp)
485
+ return true unless use_default_class_filter? && need_to_process_classes?
486
+
487
+ if options[:class].is_a? Regexp
488
+ options[:class].match? node[:class]
489
+ else
490
+ classes = (node[:class] || '').split
491
+ options[:class].select { |c| c.is_a? Regexp }.all? do |r|
492
+ classes.any? { |cls| r.match? cls }
493
+ end
494
+ end
495
+ end
487
496
 
488
- options[:class].match? node[:class]
497
+ def need_to_process_classes?
498
+ case options[:class]
499
+ when Regexp then true
500
+ when Array then options[:class].any?(Regexp)
501
+ else
502
+ false
503
+ end
489
504
  end
490
505
 
491
506
  def matches_style_filter?(node)
@@ -652,7 +667,7 @@ module Capybara
652
667
 
653
668
  d = u.dot w
654
669
  e = v.dot w
655
- cap_d = (a * c) - (b * b)
670
+ cap_d = (a * c) - (b**2)
656
671
  sD = tD = cap_d
657
672
 
658
673
  # compute the line parameters of the two closest points
@@ -15,7 +15,7 @@ module Capybara
15
15
  end
16
16
  end
17
17
 
18
- def description(applied = false)
18
+ def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter
19
19
  desc = super
20
20
  sibling_query = @sibling_node&.instance_variable_get(:@query)
21
21
  desc += " that is a sibling of #{sibling_query.description}" if sibling_query
@@ -6,7 +6,7 @@ module Capybara
6
6
  class TextQuery < BaseQuery
7
7
  def initialize(type = nil, expected_text, session_options:, **options) # rubocop:disable Style/OptionalArguments
8
8
  @type = type.nil? ? default_type : type
9
- raise ArgumentError, '${@type} is not a valid type for a text query' unless valid_types.include?(@type)
9
+ raise ArgumentError, "#{@type} is not a valid type for a text query" unless valid_types.include?(@type)
10
10
 
11
11
  @options = options
12
12
  super(@options)
@@ -14,7 +14,7 @@ module Capybara
14
14
 
15
15
  if expected_text.nil? && !exact?
16
16
  warn 'Checking for expected text of nil is confusing and/or pointless since it will always match. '\
17
- 'Please specify a string or regexp instead.'
17
+ "Please specify a string or regexp instead. #{Capybara::Helpers.filter_backtrace(caller)}"
18
18
  end
19
19
 
20
20
  @expected_text = expected_text.is_a?(Regexp) ? expected_text : expected_text.to_s
@@ -8,6 +8,7 @@ class Capybara::RackTest::Browser
8
8
 
9
9
  def initialize(driver)
10
10
  @driver = driver
11
+ @current_fragment = nil
11
12
  end
12
13
 
13
14
  def app
@@ -31,7 +32,7 @@ class Capybara::RackTest::Browser
31
32
  def submit(method, path, attributes)
32
33
  path = request_path if path.nil? || path.empty?
33
34
  uri = build_uri(path)
34
- uri.query = '' if method&.to_s&.downcase == 'get'
35
+ uri.query = '' if method.to_s.casecmp('get').zero?
35
36
  process_and_follow_redirects(method, uri.to_s, attributes, 'HTTP_REFERER' => current_url)
36
37
  end
37
38
 
@@ -42,6 +43,7 @@ class Capybara::RackTest::Browser
42
43
  end
43
44
 
44
45
  def process_and_follow_redirects(method, path, attributes = {}, env = {})
46
+ @current_fragment = build_uri(path).fragment
45
47
  process(method, path, attributes, env)
46
48
 
47
49
  return unless driver.follow_redirects?
@@ -65,7 +67,7 @@ class Capybara::RackTest::Browser
65
67
  method = method.downcase
66
68
  new_uri = build_uri(path)
67
69
  @current_scheme, @current_host, @current_port = new_uri.select(:scheme, :host, :port)
68
-
70
+ @current_fragment = new_uri.fragment || @current_fragment
69
71
  reset_cache!
70
72
  send(method, new_uri.to_s, attributes, env.merge(options[:headers] || {}))
71
73
  end
@@ -83,7 +85,9 @@ class Capybara::RackTest::Browser
83
85
  end
84
86
 
85
87
  def current_url
86
- last_request.url
88
+ uri = build_uri(last_request.url)
89
+ uri.fragment = @current_fragment if @current_fragment
90
+ uri.to_s
87
91
  rescue Rack::Test::Error
88
92
  ''
89
93
  end
@@ -17,6 +17,7 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
17
17
  def initialize(app, **options)
18
18
  raise ArgumentError, 'rack-test requires a rack application, but none was given' unless app
19
19
 
20
+ super()
20
21
  @app = app
21
22
  @options = DEFAULT_OPTIONS.merge(options)
22
23
  end
@@ -6,7 +6,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
6
6
  # That check should be based solely on the form element's 'enctype' attribute value,
7
7
  # which should probably be provided to Rack::Test in its non-GET request methods.
8
8
  class NilUploadedFile < Rack::Test::UploadedFile
9
- def initialize
9
+ def initialize # rubocop:disable Lint/MissingSuper
10
10
  @empty_file = Tempfile.new('nil_uploaded_file')
11
11
  @empty_file.close
12
12
  end
@@ -15,7 +15,7 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
15
15
  end
16
16
 
17
17
  def visible_text
18
- displayed_text.gsub(/\ +/, ' ')
18
+ displayed_text.squeeze(' ')
19
19
  .gsub(/[\ \n]*\n[\ \n]*/, "\n")
20
20
  .gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
21
21
  .gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
@@ -12,13 +12,13 @@ module Capybara
12
12
  end
13
13
 
14
14
  def []=(name, value)
15
- warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'
15
+ Capybara::Helpers.warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'
16
16
  @registered[name] = value
17
17
  end
18
18
 
19
19
  def method_missing(method_name, *args, **options, &block)
20
20
  if @registered.respond_to?(method_name)
21
- warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
21
+ Capybara::Helpers.warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
22
22
  # RUBY 2.6 will send an empty hash rather than nothing with **options so fix that
23
23
  return @registered.public_send(method_name, *args, &block) if options.empty?
24
24
 
@@ -27,7 +27,7 @@ module Capybara
27
27
  super
28
28
  end
29
29
 
30
- def respond_to_missing?(method_name, include_private = false)
30
+ def respond_to_missing?(method_name, include_all)
31
31
  @registered.respond_to?(method_name) || super
32
32
  end
33
33
 
@@ -9,28 +9,34 @@ Capybara.register_driver :selenium do |app|
9
9
  end
10
10
 
11
11
  Capybara.register_driver :selenium_headless do |app|
12
- Capybara::Selenium::Driver.load_selenium
13
- browser_options = ::Selenium::WebDriver::Firefox::Options.new
14
- browser_options.args << '-headless'
15
- Capybara::Selenium::Driver.new(app, browser: :firefox, options: browser_options)
12
+ version = Capybara::Selenium::Driver.load_selenium
13
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
14
+ browser_options = ::Selenium::WebDriver::Firefox::Options.new.tap do |opts|
15
+ opts.add_argument '-headless'
16
+ end
17
+ Capybara::Selenium::Driver.new(app, **Hash[:browser => :firefox, options_key => browser_options])
16
18
  end
17
19
 
18
20
  Capybara.register_driver :selenium_chrome do |app|
19
- Capybara::Selenium::Driver.load_selenium
21
+ version = Capybara::Selenium::Driver.load_selenium
22
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
20
23
  browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
21
24
  # Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
22
- opts.args << '--disable-site-isolation-trials'
25
+ opts.add_argument('--disable-site-isolation-trials')
23
26
  end
24
- Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
27
+
28
+ Capybara::Selenium::Driver.new(app, **Hash[:browser => :chrome, options_key => browser_options])
25
29
  end
26
30
 
27
31
  Capybara.register_driver :selenium_chrome_headless do |app|
28
- Capybara::Selenium::Driver.load_selenium
32
+ version = Capybara::Selenium::Driver.load_selenium
33
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
29
34
  browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
30
- opts.args << '--headless'
31
- opts.args << '--disable-gpu' if Gem.win_platform?
35
+ opts.add_argument('--headless')
36
+ opts.add_argument('--disable-gpu') if Gem.win_platform?
32
37
  # Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
33
- opts.args << '--disable-site-isolation-trials'
38
+ opts.add_argument('--disable-site-isolation-trials')
34
39
  end
35
- Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
40
+
41
+ Capybara::Selenium::Driver.new(app, **Hash[:browser => :chrome, options_key => browser_options])
36
42
  end
@@ -4,12 +4,14 @@ module Puma
4
4
  module MiniSSL
5
5
  class Socket
6
6
  def read_nonblock(size, *_)
7
+ wait_states = %i[wait_readable wait_writable]
8
+
7
9
  loop do
8
10
  output = engine_read_all
9
11
  return output if output
10
12
 
11
13
  data = @socket.read_nonblock(size, exception: false)
12
- raise IO::EAGAINWaitReadable if %i[wait_readable wait_writable].include? data
14
+ raise IO::EAGAINWaitReadable if wait_states.include? data
13
15
  return nil if data.nil?
14
16
 
15
17
  @engine.inject(data)
@@ -28,10 +28,11 @@ Capybara.register_server :puma do |app, port, host, **options|
28
28
  options = default_options.merge(options)
29
29
 
30
30
  conf = Rack::Handler::Puma.config(app, options)
31
+ conf.clamp
31
32
  events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
32
33
 
33
34
  puma_ver = Gem::Version.new(Puma::Const::PUMA_VERSION)
34
- require_relative 'patches/puma_ssl' if (Gem::Version.new('4.0.0')...Gem::Version.new('4.1.0')).cover? puma_ver
35
+ require_relative 'patches/puma_ssl' if Gem::Requirement.new('>=4.0.0', '< 4.1.0').satisfied_by?(puma_ver)
35
36
 
36
37
  events.log 'Capybara starting Puma...'
37
38
  events.log "* Version #{Puma::Const::PUMA_VERSION} , codename: #{Puma::Const::CODE_NAME}"
@@ -39,7 +39,7 @@ module Capybara
39
39
  alias index find_index
40
40
 
41
41
  def each(&block)
42
- return enum_for(:each) unless block_given?
42
+ return enum_for(:each) unless block
43
43
 
44
44
  @result_cache.each(&block)
45
45
  loop do
@@ -54,10 +54,10 @@ module Capybara
54
54
  idx, length = args
55
55
  max_idx = case idx
56
56
  when Integer
57
- if !idx.negative?
58
- length.nil? ? idx : idx + length - 1
59
- else
57
+ if idx.negative?
60
58
  nil
59
+ else
60
+ length.nil? ? idx : idx + length - 1
61
61
  end
62
62
  when Range
63
63
  # idx.max is broken with beginless ranges
@@ -91,13 +91,9 @@ module Capybara
91
91
  return load_up_to(count + 1) <=> count
92
92
  end
93
93
 
94
- if min && (min = Integer(min))
95
- return -1 if load_up_to(min) < min
96
- end
94
+ return -1 if min && (min = Integer(min)) && (load_up_to(min) < min)
97
95
 
98
- if max && (max = Integer(max))
99
- return 1 if load_up_to(max + 1) > max
100
- end
96
+ return 1 if max && (max = Integer(max)) && (load_up_to(max + 1) > max)
101
97
 
102
98
  if between
103
99
  min, max = (between.begin && between.min) || 1, between.end
@@ -9,6 +9,8 @@ require 'capybara/rspec/matcher_proxies'
9
9
  RSpec.configure do |config|
10
10
  config.include Capybara::DSL, type: :feature
11
11
  config.include Capybara::RSpecMatchers, type: :feature
12
+ config.include Capybara::DSL, type: :system
13
+ config.include Capybara::RSpecMatchers, type: :system
12
14
  config.include Capybara::RSpecMatchers, type: :view
13
15
 
14
16
  # The before and after blocks must run instantaneously, because Capybara
@@ -11,7 +11,7 @@ module Capybara
11
11
  end
12
12
 
13
13
  def within(*args, **kwargs, &block)
14
- if block_given?
14
+ if block
15
15
  within_element(*args, **kwargs, &block)
16
16
  else
17
17
  be_within(*args)
@@ -94,7 +94,7 @@ module Capybara
94
94
  # @see Capybara::Node::Matchers#has_button?
95
95
 
96
96
  # @!method have_field(locator = nil, **options, &optional_filter_block)
97
- # RSpec matcher for links.
97
+ # RSpec matcher for form fields.
98
98
  #
99
99
  # @see Capybara::Node::Matchers#has_field?
100
100
 
@@ -139,22 +139,23 @@ module Capybara
139
139
  # RSpec matcher for the current path.
140
140
  #
141
141
  # @see Capybara::SessionMatchers#assert_current_path
142
- def have_current_path(path, **options)
143
- Matchers::HaveCurrentPath.new(path, **options)
142
+ def have_current_path(path, **options, &optional_filter_block)
143
+ Matchers::HaveCurrentPath.new(path, **options, &optional_filter_block)
144
144
  end
145
145
 
146
146
  # RSpec matcher for element style.
147
147
  #
148
148
  # @see Capybara::Node::Matchers#matches_style?
149
- def match_style(styles, **options)
149
+ def match_style(styles = nil, **options)
150
+ styles, options = options, {} if styles.nil?
150
151
  Matchers::MatchStyle.new(styles, **options)
151
152
  end
152
153
 
153
154
  ##
154
155
  # @deprecated
155
156
  #
156
- def have_style(styles, **options)
157
- warn 'DEPRECATED: have_style is deprecated, please use match_style'
157
+ def have_style(styles = nil, **options)
158
+ Capybara::Helpers.warn "DEPRECATED: have_style is deprecated, please use match_style : #{Capybara::Helpers.filter_backtrace(caller)}"
158
159
  match_style(styles, **options)
159
160
  end
160
161