capybara 3.29.0 → 3.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +40 -1
  3. data/README.md +1 -1
  4. data/lib/capybara/config.rb +7 -3
  5. data/lib/capybara/dsl.rb +10 -2
  6. data/lib/capybara/helpers.rb +3 -1
  7. data/lib/capybara/minitest.rb +18 -4
  8. data/lib/capybara/node/actions.rb +23 -19
  9. data/lib/capybara/node/document.rb +2 -2
  10. data/lib/capybara/node/document_matchers.rb +3 -3
  11. data/lib/capybara/node/element.rb +21 -16
  12. data/lib/capybara/node/finders.rb +17 -11
  13. data/lib/capybara/node/matchers.rb +60 -45
  14. data/lib/capybara/node/simple.rb +4 -2
  15. data/lib/capybara/queries/ancestor_query.rb +1 -1
  16. data/lib/capybara/queries/base_query.rb +2 -1
  17. data/lib/capybara/queries/selector_query.rb +17 -4
  18. data/lib/capybara/queries/sibling_query.rb +1 -1
  19. data/lib/capybara/rack_test/browser.rb +4 -1
  20. data/lib/capybara/rack_test/driver.rb +1 -1
  21. data/lib/capybara/rack_test/form.rb +1 -1
  22. data/lib/capybara/rack_test/node.rb +34 -9
  23. data/lib/capybara/result.rb +24 -4
  24. data/lib/capybara/rspec/matchers.rb +27 -27
  25. data/lib/capybara/rspec/matchers/base.rb +12 -6
  26. data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
  27. data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
  28. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  29. data/lib/capybara/rspec/matchers/have_selector.rb +15 -7
  30. data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
  31. data/lib/capybara/rspec/matchers/have_text.rb +2 -2
  32. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  33. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  34. data/lib/capybara/rspec/matchers/match_style.rb +2 -2
  35. data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
  36. data/lib/capybara/selector.rb +24 -16
  37. data/lib/capybara/selector/css.rb +1 -1
  38. data/lib/capybara/selector/definition.rb +2 -2
  39. data/lib/capybara/selector/definition/button.rb +7 -2
  40. data/lib/capybara/selector/definition/checkbox.rb +2 -2
  41. data/lib/capybara/selector/definition/css.rb +3 -1
  42. data/lib/capybara/selector/definition/datalist_input.rb +1 -1
  43. data/lib/capybara/selector/definition/datalist_option.rb +1 -1
  44. data/lib/capybara/selector/definition/element.rb +1 -1
  45. data/lib/capybara/selector/definition/field.rb +1 -1
  46. data/lib/capybara/selector/definition/file_field.rb +1 -1
  47. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  48. data/lib/capybara/selector/definition/label.rb +4 -2
  49. data/lib/capybara/selector/definition/radio_button.rb +2 -2
  50. data/lib/capybara/selector/definition/select.rb +32 -13
  51. data/lib/capybara/selector/definition/table.rb +5 -2
  52. data/lib/capybara/selector/filter_set.rb +11 -9
  53. data/lib/capybara/selector/filters/base.rb +6 -1
  54. data/lib/capybara/selector/filters/locator_filter.rb +1 -1
  55. data/lib/capybara/selector/selector.rb +4 -2
  56. data/lib/capybara/selenium/driver.rb +19 -11
  57. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  58. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
  59. data/lib/capybara/selenium/extensions/html5_drag.rb +30 -13
  60. data/lib/capybara/selenium/node.rb +29 -10
  61. data/lib/capybara/selenium/nodes/chrome_node.rb +11 -5
  62. data/lib/capybara/selenium/nodes/edge_node.rb +4 -2
  63. data/lib/capybara/selenium/nodes/firefox_node.rb +2 -2
  64. data/lib/capybara/server.rb +15 -3
  65. data/lib/capybara/server/checker.rb +1 -1
  66. data/lib/capybara/server/middleware.rb +20 -10
  67. data/lib/capybara/session.rb +40 -23
  68. data/lib/capybara/session/config.rb +6 -2
  69. data/lib/capybara/session/matchers.rb +6 -6
  70. data/lib/capybara/spec/public/test.js +51 -6
  71. data/lib/capybara/spec/session/all_spec.rb +60 -5
  72. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  73. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  74. data/lib/capybara/spec/session/click_button_spec.rb +5 -0
  75. data/lib/capybara/spec/session/fill_in_spec.rb +20 -0
  76. data/lib/capybara/spec/session/find_spec.rb +20 -0
  77. data/lib/capybara/spec/session/has_css_spec.rb +3 -3
  78. data/lib/capybara/spec/session/has_select_spec.rb +28 -0
  79. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  80. data/lib/capybara/spec/session/has_text_spec.rb +35 -0
  81. data/lib/capybara/spec/session/node_spec.rb +106 -2
  82. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  83. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  84. data/lib/capybara/spec/session/selectors_spec.rb +15 -2
  85. data/lib/capybara/spec/views/form.erb +11 -1
  86. data/lib/capybara/version.rb +1 -1
  87. data/spec/dsl_spec.rb +2 -2
  88. data/spec/minitest_spec_spec.rb +46 -46
  89. data/spec/rack_test_spec.rb +0 -1
  90. data/spec/regexp_dissassembler_spec.rb +45 -37
  91. data/spec/result_spec.rb +7 -3
  92. data/spec/rspec/features_spec.rb +1 -0
  93. data/spec/rspec/shared_spec_matchers.rb +3 -3
  94. data/spec/rspec_spec.rb +4 -4
  95. data/spec/selenium_spec_chrome.rb +5 -4
  96. data/spec/selenium_spec_firefox.rb +7 -2
  97. data/spec/server_spec.rb +42 -0
  98. data/spec/session_spec.rb +1 -1
  99. data/spec/shared_selenium_node.rb +3 -3
  100. data/spec/shared_selenium_session.rb +8 -7
  101. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f11a887ca6aed51d064d9c8eb797e0db4605a3d013082a11f4f4b1013b27bef
4
- data.tar.gz: 714e834fdb1c2f0e692f547a1d032113dd888d6905eddecc60f05503720bcd8e
3
+ metadata.gz: dd31d35629d475d7fdaba1d6e415599d995a08f27b28fa619a3a4449b61b91d8
4
+ data.tar.gz: 27c812629e2d99e8f4c62fa7961df9b499c5346b1c61092faf487f592356033d
5
5
  SHA512:
6
- metadata.gz: 82c37d1b9c8d1c7f9d858f8d7aebebfc2ecee4c5e35d35f9a3c949d978e4e97d48f78b9d5f93079e209fc779ab31e5707ecce8ac0d2a4ce8108fc3be2437e1bc
7
- data.tar.gz: '06886b335dd0ef5f93f59a09026877bc460e6430b2d2f1902cd31a3179b1bd52b9418a1b43ab558dcf18e92b198506023c3549a065949bb33f881538ec9e018d'
6
+ metadata.gz: 946e3f2de0137ddaa6e3a2febba2c87244997737c54a10024133de110ca41b8aeddcb66e0437bef5d826e9fe21d4c42701674c3864bd578d24c30c7b1f90e2a9
7
+ data.tar.gz: f9409de3e2e0ea44e0bb6b6f77cce7e0e8f5a4d95c43fb62af2eb63d11e755d6a8c00b9b9b4d2bbe2729538d0d1038e92468e0a7994d1578b50e05b5227b87f4
data/History.md CHANGED
@@ -1,5 +1,44 @@
1
+ # Version 3.31.0
2
+ Release date: 2020-01-26
3
+
4
+ ### Added
5
+
6
+ * Support setting range inputs with the selenium driver [Andrew White]
7
+ * Support setting range inputs with the rack driver
8
+ * Support drop modifier keys in drag & drop [Elliot Crosby-McCullough]
9
+ * `enabled_options` and `disabled options` filters for select selector
10
+ * Support beginless ranges
11
+ * Optionally allow `all` results to be reloaded when stable - Beta feature - may be removed in
12
+ future version if problems occur
13
+
14
+ ### Fixed
15
+
16
+ * Fix Ruby 2.7 deprecation notices around keyword arguments. I have tried to do this without
17
+ any breaking changes, but due to the nature of the 2.7 changes and some selector types accepting
18
+ Hashes as locators there are a lot of edge cases. If you find any broken cases please report
19
+ them and I'll see if they're fixable.
20
+ * Clicking on details/summary element behavior in rack_test driver_
21
+
22
+ # Version 3.30.0
23
+ Release date: 2019-12-24
24
+
25
+ ### Added
26
+
27
+ * Display pending requests when they don't complete in time [Juan Carlos Medina]
28
+ * :order option in selector queries - set to :reverse to for reverse document order results
29
+ * Support regexp for :name and :placeholder options in selectors that import filters from
30
+ _field filter set
31
+
32
+ ### Fixed
33
+
34
+ * Issue around automatic port assignment - Issue #2245
35
+ * Label selector when label has no id - Issue #2260
36
+ * Preserve clientX/clientY in Selenium HTML5 drag emulation [Nicolò G.]
37
+ * table selector using :with_cols option if last specified column matched but others didn't - Issue #2287
38
+ * Some tests updated for Ruby 2.7 behavior change around keyword args
39
+
1
40
  # Version 3.29.0
2
- Release date: Unreleased
41
+ Release date: 2019-09-02
3
42
 
4
43
  ### Added
5
44
 
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![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)
8
8
  [![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)
9
9
 
10
- **Note** You are viewing the README for the 3.29.x version of Capybara.
10
+ **Note** You are viewing the README for the 3.31.x stable branch of Capybara.
11
11
 
12
12
  Capybara helps you test web applications by simulating how a real user would
13
13
  interact with your app. It is agnostic about the driver running your tests and
@@ -27,7 +27,9 @@ module Capybara
27
27
  attr_writer :reuse_server
28
28
 
29
29
  def threadsafe=(bool)
30
- raise 'Threadsafe setting cannot be changed once a session is created' if (bool != threadsafe) && Session.instance_created?
30
+ if (bool != threadsafe) && Session.instance_created?
31
+ raise 'Threadsafe setting cannot be changed once a session is created'
32
+ end
31
33
 
32
34
  @threadsafe = bool
33
35
  end
@@ -59,7 +61,7 @@ module Capybara
59
61
  @server = if name.respond_to? :call
60
62
  name
61
63
  elsif options
62
- proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, options) }
64
+ proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, **options) }
63
65
  else
64
66
  Capybara.servers[name.to_sym]
65
67
  end
@@ -83,7 +85,9 @@ module Capybara
83
85
 
84
86
  def deprecate(method, alternate_method, once = false)
85
87
  @deprecation_notified ||= {}
86
- warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once && @deprecation_notified[method]
88
+ unless once && @deprecation_notified[method]
89
+ warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead"
90
+ end
87
91
  @deprecation_notified[method] = true
88
92
  end
89
93
  end
@@ -47,8 +47,16 @@ module Capybara
47
47
  end
48
48
 
49
49
  Session::DSL_METHODS.each do |method|
50
- define_method method do |*args, &block|
51
- page.send method, *args, &block
50
+ if RUBY_VERSION >= '2.7'
51
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
52
+ def #{method}(...)
53
+ page.method("#{method}").call(...)
54
+ end
55
+ METHOD
56
+ else
57
+ define_method method do |*args, &block|
58
+ page.send method, *args, &block
59
+ end
52
60
  end
53
61
  end
54
62
  end
@@ -87,7 +87,9 @@ module Capybara
87
87
  end
88
88
 
89
89
  def expired?
90
- raise Capybara::FrozenInTime, 'Time appears to be frozen. Capybara does not work with libraries which freeze time, consider using time travelling instead' if stalled?
90
+ if stalled?
91
+ raise Capybara::FrozenInTime, 'Time appears to be frozen. Capybara does not work with libraries which freeze time, consider using time travelling instead'
92
+ end
91
93
 
92
94
  current - @start >= @expire_in
93
95
  end
@@ -52,6 +52,7 @@ module Capybara
52
52
  raise ::Minitest::Assertion, e.message
53
53
  end
54
54
  ASSERTION
55
+ ruby2_keywords "assert_#{assertion_name}" if respond_to?(:ruby2_keywords)
55
56
  end
56
57
 
57
58
  alias_method :refute_title, :assert_no_title
@@ -109,6 +110,7 @@ module Capybara
109
110
  raise ::Minitest::Assertion, e.message
110
111
  end
111
112
  ASSERTION
113
+ ruby2_keywords "assert_#{assertion_name}" if respond_to?(:ruby2_keywords)
112
114
  end
113
115
 
114
116
  alias_method :refute_selector, :assert_no_selector
@@ -120,14 +122,16 @@ module Capybara
120
122
  define_method "assert_#{selector_type}" do |*args, &optional_filter_block|
121
123
  subject, args = determine_subject(args)
122
124
  locator, options = extract_locator(args)
123
- assert_selector(subject, selector_type.to_sym, locator, options, &optional_filter_block)
125
+ assert_selector(subject, selector_type.to_sym, locator, **options, &optional_filter_block)
124
126
  end
127
+ ruby2_keywords "assert_#{selector_type}" if respond_to?(:ruby2_keywords)
125
128
 
126
129
  define_method "assert_no_#{selector_type}" do |*args, &optional_filter_block|
127
130
  subject, args = determine_subject(args)
128
131
  locator, options = extract_locator(args)
129
- assert_no_selector(subject, selector_type.to_sym, locator, options, &optional_filter_block)
132
+ assert_no_selector(subject, selector_type.to_sym, locator, **options, &optional_filter_block)
130
133
  end
134
+ ruby2_keywords "assert_no_#{selector_type}" if respond_to?(:ruby2_keywords)
131
135
  alias_method "refute_#{selector_type}", "assert_no_#{selector_type}"
132
136
  end
133
137
 
@@ -135,14 +139,22 @@ module Capybara
135
139
  define_method "assert_#{field_type}_field" do |*args, &optional_filter_block|
136
140
  subject, args = determine_subject(args)
137
141
  locator, options = extract_locator(args)
138
- assert_selector(subject, :field, locator, options.merge(field_type.to_sym => true), &optional_filter_block)
142
+ assert_selector(subject, :field, locator, **options.merge(field_type.to_sym => true), &optional_filter_block)
139
143
  end
144
+ ruby2_keywords "assert_#{field_type}_field" if respond_to?(:ruby2_keywords)
140
145
 
141
146
  define_method "assert_no_#{field_type}_field" do |*args, &optional_filter_block|
142
147
  subject, args = determine_subject(args)
143
148
  locator, options = extract_locator(args)
144
- assert_no_selector(subject, :field, locator, options.merge(field_type.to_sym => true), &optional_filter_block)
149
+ assert_no_selector(
150
+ subject,
151
+ :field,
152
+ locator,
153
+ **options.merge(field_type.to_sym => true),
154
+ &optional_filter_block
155
+ )
145
156
  end
157
+ ruby2_keywords "assert_no_#{field_type}_field" if respond_to?(:ruby2_keywords)
146
158
  alias_method "refute_#{field_type}_field", "assert_no_#{field_type}_field"
147
159
  end
148
160
 
@@ -151,11 +163,13 @@ module Capybara
151
163
  subject, args = determine_subject(args)
152
164
  assert_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)
153
165
  end
166
+ ruby2_keywords "assert_matches_#{selector_type}" if respond_to?(:ruby2_keywords)
154
167
 
155
168
  define_method "assert_not_matches_#{selector_type}" do |*args, &optional_filter_block|
156
169
  subject, args = determine_subject(args)
157
170
  assert_not_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)
158
171
  end
172
+ ruby2_keywords "assert_not_matches_#{selector_type}" if respond_to?(:ruby2_keywords)
159
173
  alias_method "refute_matches_#{selector_type}", "assert_not_matches_#{selector_type}"
160
174
  end
161
175
 
@@ -23,7 +23,7 @@ module Capybara
23
23
  # @return [Capybara::Node::Element] The element clicked
24
24
  #
25
25
  def click_link_or_button(locator = nil, **options)
26
- find(:link_or_button, locator, options).click
26
+ find(:link_or_button, locator, **options).click
27
27
  end
28
28
  alias_method :click_on, :click_link_or_button
29
29
 
@@ -39,7 +39,7 @@ module Capybara
39
39
  #
40
40
  # @return [Capybara::Node::Element] The element clicked
41
41
  def click_link(locator = nil, **options)
42
- find(:link, locator, options).click
42
+ find(:link, locator, **options).click
43
43
  end
44
44
 
45
45
  ##
@@ -55,7 +55,7 @@ module Capybara
55
55
  # @param [Hash] options See {Capybara::Node::Finders#find_button}
56
56
  # @return [Capybara::Node::Element] The element clicked
57
57
  def click_button(locator = nil, **options)
58
- find(:button, locator, options).click
58
+ find(:button, locator, **options).click
59
59
  end
60
60
 
61
61
  ##
@@ -88,7 +88,7 @@ module Capybara
88
88
  def fill_in(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)
89
89
  find_options[:with] = currently_with if currently_with
90
90
  find_options[:allow_self] = true if locator.nil?
91
- find(:fillable_field, locator, find_options).set(with, fill_options)
91
+ find(:fillable_field, locator, **find_options).set(with, **fill_options)
92
92
  end
93
93
 
94
94
  # @!macro label_click
@@ -119,7 +119,7 @@ module Capybara
119
119
  #
120
120
  # @return [Capybara::Node::Element] The element chosen or the label clicked
121
121
  def choose(locator = nil, **options)
122
- _check_with_label(:radio_button, true, locator, options)
122
+ _check_with_label(:radio_button, true, locator, **options)
123
123
  end
124
124
 
125
125
  ##
@@ -147,7 +147,7 @@ module Capybara
147
147
  #
148
148
  # @return [Capybara::Node::Element] The element checked or the label clicked
149
149
  def check(locator = nil, **options)
150
- _check_with_label(:checkbox, true, locator, options)
150
+ _check_with_label(:checkbox, true, locator, **options)
151
151
  end
152
152
 
153
153
  ##
@@ -175,7 +175,7 @@ module Capybara
175
175
  #
176
176
  # @return [Capybara::Node::Element] The element unchecked or the label clicked
177
177
  def uncheck(locator = nil, **options)
178
- _check_with_label(:checkbox, false, locator, options)
178
+ _check_with_label(:checkbox, false, locator, **options)
179
179
  end
180
180
 
181
181
  ##
@@ -205,7 +205,7 @@ module Capybara
205
205
  if el.respond_to?(:tag_name) && (el.tag_name == 'input')
206
206
  select_datalist_option(el, value)
207
207
  else
208
- el.find(:option, value, options).select_option
208
+ el.find(:option, value, **options).select_option
209
209
  end
210
210
  end
211
211
 
@@ -229,8 +229,8 @@ module Capybara
229
229
  def unselect(value = nil, from: nil, **options)
230
230
  raise ArgumentError, 'The :from option does not take an element' if from.is_a? Capybara::Node::Element
231
231
 
232
- scope = from ? find(:select, from, options) : self
233
- scope.find(:option, value, options).unselect_option
232
+ scope = from ? find(:select, from, **options) : self
233
+ scope.find(:option, value, **options).unselect_option
234
234
  end
235
235
 
236
236
  ##
@@ -276,7 +276,9 @@ module Capybara
276
276
  # @yield Block whose actions will trigger the system file chooser to be shown
277
277
  # @return [Capybara::Node::Element] The file field element
278
278
  def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments
279
- raise ArgumentError, '``#attach_file` does not support passing both a locator and a block' if locator && block_given?
279
+ if locator && block_given?
280
+ raise ArgumentError, '``#attach_file` does not support passing both a locator and a block'
281
+ end
280
282
 
281
283
  Array(paths).each do |path|
282
284
  raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
@@ -295,10 +297,10 @@ module Capybara
295
297
  end
296
298
  # Allow user to update the CSS style of the file input since they are so often hidden on a page
297
299
  if make_visible
298
- ff = file_field || find(:file_field, locator, options.merge(visible: :all))
300
+ ff = file_field || find(:file_field, locator, **options.merge(visible: :all))
299
301
  while_visible(ff, make_visible) { |el| el.set(paths) }
300
302
  else
301
- (file_field || find(:file_field, locator, options)).set(paths)
303
+ (file_field || find(:file_field, locator, **options)).set(paths)
302
304
  end
303
305
  end
304
306
 
@@ -307,12 +309,12 @@ module Capybara
307
309
  def find_select_or_datalist_input(from, options)
308
310
  synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
309
311
  begin
310
- find(:select, from, options)
312
+ find(:select, from, **options)
311
313
  rescue Capybara::ElementNotFound => select_error # rubocop:disable Naming/RescuedExceptionsVariableName
312
314
  raise if %i[selected with_selected multiple].any? { |option| options.key?(option) }
313
315
 
314
316
  begin
315
- find(:datalist_input, from, options)
317
+ find(:datalist_input, from, **options)
316
318
  rescue Capybara::ElementNotFound => dlinput_error # rubocop:disable Naming/RescuedExceptionsVariableName
317
319
  raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
318
320
  end
@@ -338,7 +340,9 @@ module Capybara
338
340
  visible_css = { opacity: 1, display: 'block', visibility: 'visible', width: 'auto', height: 'auto' }
339
341
  end
340
342
  _update_style(element, visible_css)
341
- raise ExpectationNotMet, 'The style changes in :make_visible did not make the file input visible' unless element.visible?
343
+ unless element.visible?
344
+ raise ExpectationNotMet, 'The style changes in :make_visible did not make the file input visible'
345
+ end
342
346
 
343
347
  begin
344
348
  yield element
@@ -355,7 +359,7 @@ module Capybara
355
359
 
356
360
  def _reset_style(element)
357
361
  element.execute_script(RESET_STYLE_SCRIPT)
358
- rescue StandardError # rubocop:disable Lint/HandleExceptions swallow extra errors
362
+ rescue StandardError # rubocop:disable Lint/SuppressedException swallow extra errors
359
363
  end
360
364
 
361
365
  def _check_with_label(selector, checked, locator,
@@ -364,13 +368,13 @@ module Capybara
364
368
 
365
369
  synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
366
370
  begin
367
- el = find(selector, locator, options)
371
+ el = find(selector, locator, **options)
368
372
  el.set(checked)
369
373
  rescue StandardError => e
370
374
  raise unless allow_label_click && catch_error?(e)
371
375
 
372
376
  begin
373
- el ||= find(selector, locator, options.merge(visible: :all))
377
+ el ||= find(selector, locator, **options.merge(visible: :all))
374
378
  el.session.find(:label, for: el, visible: true).click unless el.checked? == checked
375
379
  rescue StandardError # swallow extra errors - raise original
376
380
  raise e
@@ -40,8 +40,8 @@ module Capybara
40
40
  find(:xpath, '/html').evaluate_script(*args)
41
41
  end
42
42
 
43
- def scroll_to(*args)
44
- find(:xpath, '//body').scroll_to(*args)
43
+ def scroll_to(*args, **options)
44
+ find(:xpath, '//body').scroll_to(*args, **options)
45
45
  end
46
46
  end
47
47
  end
@@ -42,7 +42,7 @@ module Capybara
42
42
  # @return [Boolean]
43
43
  #
44
44
  def has_title?(title, **options)
45
- make_predicate(options) { assert_title(title, options) }
45
+ make_predicate(options) { assert_title(title, **options) }
46
46
  end
47
47
 
48
48
  ##
@@ -52,13 +52,13 @@ module Capybara
52
52
  # @return [Boolean]
53
53
  #
54
54
  def has_no_title?(title, **options)
55
- make_predicate(options) { assert_no_title(title, options) }
55
+ make_predicate(options) { assert_no_title(title, **options) }
56
56
  end
57
57
 
58
58
  private
59
59
 
60
60
  def _verify_title(title, options)
61
- query = Capybara::Queries::TitleQuery.new(title, options)
61
+ query = Capybara::Queries::TitleQuery.new(title, **options)
62
62
  synchronize(query.wait) { yield(query) }
63
63
  true
64
64
  end
@@ -27,9 +27,11 @@ module Capybara
27
27
  @query_scope = query_scope
28
28
  @query = query
29
29
  @allow_reload = false
30
+ @query_idx = nil
30
31
  end
31
32
 
32
- def allow_reload!
33
+ def allow_reload!(idx = nil)
34
+ @query_idx = idx
33
35
  @allow_reload = true
34
36
  end
35
37
 
@@ -113,10 +115,12 @@ module Capybara
113
115
  #
114
116
  # @return [Capybara::Node::Element] The element
115
117
  def set(value, **options)
116
- raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}" if ENV['CAPYBARA_THOROUGH'] && readonly?
118
+ if ENV['CAPYBARA_THOROUGH'] && readonly?
119
+ raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}"
120
+ end
117
121
 
118
122
  options = session_options.default_set_options.to_h.merge(options)
119
- synchronize { base.set(value, options) }
123
+ synchronize { base.set(value, **options) }
120
124
  self
121
125
  end
122
126
 
@@ -163,8 +167,8 @@ module Capybara
163
167
  # offset will be from the element center, otherwise it will be from the top left corner of the element
164
168
  # @return [Capybara::Node::Element] The element
165
169
  def click(*keys, **options)
166
- perform_click_action(keys, options) do |k, opts|
167
- base.click(k, opts)
170
+ perform_click_action(keys, **options) do |k, opts|
171
+ base.click(k, **opts)
168
172
  end
169
173
  end
170
174
 
@@ -176,8 +180,8 @@ module Capybara
176
180
  # @macro click_modifiers
177
181
  # @return [Capybara::Node::Element] The element
178
182
  def right_click(*keys, **options)
179
- perform_click_action(keys, options) do |k, opts|
180
- base.right_click(k, opts)
183
+ perform_click_action(keys, **options) do |k, opts|
184
+ base.right_click(k, **opts)
181
185
  end
182
186
  end
183
187
 
@@ -189,8 +193,8 @@ module Capybara
189
193
  # @macro click_modifiers
190
194
  # @return [Capybara::Node::Element] The element
191
195
  def double_click(*keys, **options)
192
- perform_click_action(keys, options) do |k, opts|
193
- base.double_click(k, opts)
196
+ perform_click_action(keys, **options) do |k, opts|
197
+ base.double_click(k, **opts)
194
198
  end
195
199
  end
196
200
 
@@ -405,6 +409,8 @@ module Capybara
405
409
  # @option options [Boolean] :html5 When using Chrome/Firefox with Selenium enables to force the use of HTML5
406
410
  # (true) or legacy (false) dragging. If not specified the driver will attempt to
407
411
  # detect the correct method to use.
412
+ # @option options [Array<Symbol>,Symbol] :drop_modifiers Modifier keys which should be held while the dragged element is dropped.
413
+ #
408
414
  #
409
415
  # @return [Capybara::Node::Element] The dragged element
410
416
  def drag_to(node, **options)
@@ -543,14 +549,13 @@ module Capybara
543
549
 
544
550
  # @api private
545
551
  def reload
546
- if @allow_reload
547
- begin
548
- reloaded = @query.resolve_for(query_scope.reload)&.first
552
+ return self unless @allow_reload
549
553
 
550
- @base = reloaded.base if reloaded
551
- rescue StandardError => e
552
- raise e unless catch_error?(e)
553
- end
554
+ begin
555
+ reloaded = @query.resolve_for(query_scope.reload)[@query_idx.to_i]
556
+ @base = reloaded.base if reloaded
557
+ rescue StandardError => e
558
+ raise e unless catch_error?(e)
554
559
  end
555
560
  self
556
561
  end