capybara 2.18.0 → 3.0.0.rc1

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.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +26 -1
  3. data/README.md +12 -12
  4. data/lib/capybara.rb +13 -25
  5. data/lib/capybara/config.rb +11 -57
  6. data/lib/capybara/cucumber.rb +2 -3
  7. data/lib/capybara/driver/base.rb +5 -16
  8. data/lib/capybara/driver/node.rb +5 -4
  9. data/lib/capybara/dsl.rb +1 -0
  10. data/lib/capybara/helpers.rb +16 -28
  11. data/lib/capybara/minitest.rb +139 -138
  12. data/lib/capybara/minitest/spec.rb +15 -14
  13. data/lib/capybara/node/actions.rb +59 -81
  14. data/lib/capybara/node/base.rb +11 -18
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +8 -8
  17. data/lib/capybara/node/element.rb +30 -40
  18. data/lib/capybara/node/finders.rb +62 -70
  19. data/lib/capybara/node/matchers.rb +48 -71
  20. data/lib/capybara/node/simple.rb +11 -17
  21. data/lib/capybara/queries/ancestor_query.rb +4 -6
  22. data/lib/capybara/queries/base_query.rb +18 -17
  23. data/lib/capybara/queries/current_path_query.rb +8 -24
  24. data/lib/capybara/queries/match_query.rb +3 -7
  25. data/lib/capybara/queries/selector_query.rb +92 -95
  26. data/lib/capybara/queries/sibling_query.rb +4 -4
  27. data/lib/capybara/queries/text_query.rb +37 -34
  28. data/lib/capybara/queries/title_query.rb +8 -11
  29. data/lib/capybara/rack_test/browser.rb +15 -18
  30. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  31. data/lib/capybara/rack_test/driver.rb +6 -10
  32. data/lib/capybara/rack_test/form.rb +50 -40
  33. data/lib/capybara/rack_test/node.rb +70 -56
  34. data/lib/capybara/rails.rb +2 -6
  35. data/lib/capybara/result.rb +22 -22
  36. data/lib/capybara/rspec.rb +5 -10
  37. data/lib/capybara/rspec/compound.rb +5 -10
  38. data/lib/capybara/rspec/features.rb +17 -48
  39. data/lib/capybara/rspec/matcher_proxies.rb +31 -15
  40. data/lib/capybara/rspec/matchers.rb +70 -60
  41. data/lib/capybara/selector.rb +129 -117
  42. data/lib/capybara/selector/css.rb +6 -11
  43. data/lib/capybara/selector/filter.rb +1 -17
  44. data/lib/capybara/selector/filter_set.rb +17 -14
  45. data/lib/capybara/selector/filters/base.rb +7 -6
  46. data/lib/capybara/selector/filters/expression_filter.rb +6 -23
  47. data/lib/capybara/selector/filters/node_filter.rb +2 -12
  48. data/lib/capybara/selector/selector.rb +27 -33
  49. data/lib/capybara/selenium/driver.rb +113 -127
  50. data/lib/capybara/selenium/node.rb +148 -113
  51. data/lib/capybara/server.rb +3 -2
  52. data/lib/capybara/session.rb +137 -223
  53. data/lib/capybara/session/config.rb +47 -67
  54. data/lib/capybara/session/matchers.rb +8 -7
  55. data/lib/capybara/spec/public/test.js +26 -4
  56. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
  57. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
  58. data/lib/capybara/spec/session/accept_prompt_spec.rb +1 -0
  59. data/lib/capybara/spec/session/all_spec.rb +31 -18
  60. data/lib/capybara/spec/session/ancestor_spec.rb +2 -4
  61. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
  62. data/lib/capybara/spec/session/assert_current_path.rb +12 -11
  63. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  64. data/lib/capybara/spec/session/assert_text.rb +18 -17
  65. data/lib/capybara/spec/session/assert_title.rb +1 -0
  66. data/lib/capybara/spec/session/attach_file_spec.rb +14 -13
  67. data/lib/capybara/spec/session/body_spec.rb +1 -0
  68. data/lib/capybara/spec/session/check_spec.rb +7 -6
  69. data/lib/capybara/spec/session/choose_spec.rb +5 -4
  70. data/lib/capybara/spec/session/click_button_spec.rb +20 -28
  71. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
  72. data/lib/capybara/spec/session/click_link_spec.rb +8 -7
  73. data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
  74. data/lib/capybara/spec/session/current_url_spec.rb +7 -6
  75. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
  76. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
  77. data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
  78. data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
  79. data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
  80. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +3 -2
  81. data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
  82. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  83. data/lib/capybara/spec/session/fill_in_spec.rb +6 -5
  84. data/lib/capybara/spec/session/find_button_spec.rb +4 -3
  85. data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
  86. data/lib/capybara/spec/session/find_field_spec.rb +8 -14
  87. data/lib/capybara/spec/session/find_link_spec.rb +6 -5
  88. data/lib/capybara/spec/session/find_spec.rb +37 -31
  89. data/lib/capybara/spec/session/first_spec.rb +60 -33
  90. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  91. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  92. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  93. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  94. data/lib/capybara/spec/session/has_all_selectors_spec.rb +15 -15
  95. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  96. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  97. data/lib/capybara/spec/session/has_current_path_spec.rb +12 -28
  98. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  99. data/lib/capybara/spec/session/has_link_spec.rb +1 -0
  100. data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
  101. data/lib/capybara/spec/session/has_select_spec.rb +30 -29
  102. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  103. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  104. data/lib/capybara/spec/session/has_text_spec.rb +6 -5
  105. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  106. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  107. data/lib/capybara/spec/session/headers.rb +2 -1
  108. data/lib/capybara/spec/session/html_spec.rb +1 -0
  109. data/lib/capybara/spec/session/node_spec.rb +91 -56
  110. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  111. data/lib/capybara/spec/session/refresh_spec.rb +4 -2
  112. data/lib/capybara/spec/session/reset_session_spec.rb +1 -0
  113. data/lib/capybara/spec/session/response_code.rb +1 -0
  114. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  115. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  116. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  117. data/lib/capybara/spec/session/save_screenshot_spec.rb +1 -1
  118. data/lib/capybara/spec/session/select_spec.rb +20 -20
  119. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  120. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  121. data/lib/capybara/spec/session/text_spec.rb +1 -0
  122. data/lib/capybara/spec/session/title_spec.rb +1 -1
  123. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  124. data/lib/capybara/spec/session/unselect_spec.rb +6 -5
  125. data/lib/capybara/spec/session/visit_spec.rb +9 -3
  126. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  127. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  128. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  129. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  130. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  131. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  132. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  133. data/lib/capybara/spec/session/window/within_window_spec.rb +13 -68
  134. data/lib/capybara/spec/session/within_spec.rb +1 -0
  135. data/lib/capybara/spec/spec_helper.rb +26 -18
  136. data/lib/capybara/spec/test_app.rb +8 -9
  137. data/lib/capybara/spec/views/form.erb +1 -0
  138. data/lib/capybara/spec/views/with_html.erb +3 -1
  139. data/lib/capybara/spec/views/within_frames.erb +4 -1
  140. data/lib/capybara/version.rb +2 -1
  141. data/lib/capybara/window.rb +6 -10
  142. data/spec/basic_node_spec.rb +1 -0
  143. data/spec/capybara_spec.rb +9 -32
  144. data/spec/dsl_spec.rb +5 -13
  145. data/spec/filter_set_spec.rb +5 -4
  146. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  147. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  148. data/spec/minitest_spec.rb +4 -3
  149. data/spec/minitest_spec_spec.rb +3 -2
  150. data/spec/per_session_config_spec.rb +9 -8
  151. data/spec/rack_test_spec.rb +21 -20
  152. data/spec/result_spec.rb +17 -16
  153. data/spec/rspec/features_spec.rb +17 -14
  154. data/spec/rspec/scenarios_spec.rb +5 -7
  155. data/spec/rspec/shared_spec_matchers.rb +96 -99
  156. data/spec/rspec/views_spec.rb +2 -1
  157. data/spec/rspec_matchers_spec.rb +19 -2
  158. data/spec/rspec_spec.rb +11 -15
  159. data/spec/selector_spec.rb +5 -6
  160. data/spec/selenium_spec_chrome.rb +7 -4
  161. data/spec/selenium_spec_marionette.rb +26 -12
  162. data/spec/server_spec.rb +33 -33
  163. data/spec/session_spec.rb +2 -1
  164. data/spec/shared_selenium_session.rb +27 -21
  165. data/spec/spec_helper.rb +2 -5
  166. metadata +66 -87
  167. data/lib/capybara/query.rb +0 -7
  168. data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,27 +1,31 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara/selector/selector'
3
4
  Capybara::Selector::FilterSet.add(:_field) do
4
- filter(:checked, :boolean) { |node, value| not(value ^ node.checked?) }
5
+ filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) }
5
6
  filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) }
6
- filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
7
+ filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
7
8
  filter(:multiple, :boolean) { |node, value| !(value ^ node.multiple?) }
8
9
 
9
- expression_filter(:name) { |xpath, val| xpath[XPath.attr(:name).equals(val)] }
10
- expression_filter(:placeholder) { |xpath, val| xpath[XPath.attr(:placeholder).equals(val)] }
10
+ expression_filter(:name) { |xpath, val| xpath[XPath.attr(:name) == val] }
11
+ expression_filter(:placeholder) { |xpath, val| xpath[XPath.attr(:placeholder) == val] }
11
12
 
12
- describe do |options|
13
- desc, states = String.new, []
14
- states << 'checked' if options[:checked] || (options[:unchecked] == false)
15
- states << 'not checked' if options[:unchecked] || (options[:checked] == false)
16
- states << 'disabled' if options[:disabled] == true
17
- states << 'not disabled' if options[:disabled] == false
13
+ describe do |checked: nil, unchecked: nil, disabled: nil, multiple: nil, **_options|
14
+ desc, states = "".dup, []
15
+ states << 'checked' if checked || (unchecked == false)
16
+ states << 'not checked' if unchecked || (checked == false)
17
+ states << 'disabled' if disabled == true
18
+ states << 'not disabled' if disabled == false
18
19
  desc << " that is #{states.join(' and ')}" unless states.empty?
19
- desc << " with the multiple attribute" if options[:multiple] == true
20
- desc << " without the multiple attribute" if options[:multiple] == false
20
+ desc << " with the multiple attribute" if multiple == true
21
+ desc << " without the multiple attribute" if multiple == false
21
22
  desc
22
23
  end
23
24
  end
24
25
 
26
+ # rubocop:disable Metrics/BlockLength
27
+ # rubocop:disable Metrics/ParameterLists
28
+
25
29
  ##
26
30
  #
27
31
  # Select elements by XPath expression
@@ -69,31 +73,31 @@ end
69
73
  # @filter [Boolean] :disabled Match disabled field?
70
74
  # @filter [Boolean] :multiple Match fields that accept multiple values
71
75
  Capybara.add_selector(:field) do
72
- xpath do |locator, options|
73
- xpath = XPath.descendant(:input, :textarea, :select)[~XPath.attr(:type).one_of('submit', 'image', 'hidden')]
76
+ xpath do |locator, **options|
77
+ xpath = XPath.descendant(:input, :textarea, :select)[!XPath.attr(:type).one_of('submit', 'image', 'hidden')]
74
78
  locate_field(xpath, locator, options)
75
79
  end
76
80
 
77
81
  expression_filter(:type) do |expr, type|
78
82
  type = type.to_s
79
- if ['textarea', 'select'].include?(type)
80
- expr.axis(:self, type.to_sym)
83
+ if %w[textarea select].include?(type)
84
+ expr.self(type.to_sym)
81
85
  else
82
- expr[XPath.attr(:type).equals(type)]
86
+ expr[XPath.attr(:type) == type]
83
87
  end
84
88
  end
85
89
 
86
90
  filter_set(:_field) # checked/unchecked/disabled/multiple/name/placeholder
87
91
 
88
- filter(:readonly, :boolean) { |node, value| not(value ^ node.readonly?) }
92
+ filter(:readonly, :boolean) { |node, value| !(value ^ node.readonly?) }
89
93
  filter(:with) do |node, with|
90
94
  with.is_a?(Regexp) ? node.value =~ with : node.value == with.to_s
91
95
  end
92
- describe do |options|
93
- desc = String.new
94
- (expression_filters.keys - [:type]).each { |ef| desc << " with #{ef} #{options[ef]}" if options.has_key?(ef) }
95
- desc << " of type #{options[:type].inspect}" if options[:type]
96
- desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
96
+ describe do |type: nil, **options|
97
+ desc = "".dup
98
+ (expression_filters.keys - [:type]).each { |ef| desc << " with #{ef} #{options[ef]}" if options.key?(ef) }
99
+ desc << " of type #{type.inspect}" if type
100
+ desc << " with value #{options[:with].to_s.inspect}" if options.key?(:with)
97
101
  desc
98
102
  end
99
103
  end
@@ -109,10 +113,10 @@ end
109
113
  # @filter [String, Array<String>] :class Matches the class(es) provided
110
114
  #
111
115
  Capybara.add_selector(:fieldset) do
112
- xpath(:legend) do |locator, options|
116
+ xpath(:legend) do |locator, legend: nil, **_options|
113
117
  xpath = XPath.descendant(:fieldset)
114
- xpath = xpath[XPath.attr(:id).equals(locator.to_s).or XPath.child(:legend)[XPath.string.n.is(locator.to_s)]] unless locator.nil?
115
- xpath = xpath[XPath.child(:legend)[XPath.string.n.is(options[:legend])]] if options[:legend]
118
+ xpath = xpath[(XPath.attr(:id) == locator.to_s) | XPath.child(:legend)[XPath.string.n.is(locator.to_s)]] unless locator.nil?
119
+ xpath = xpath[XPath.child(:legend)[XPath.string.n.is(legend)]] if legend
116
120
  xpath
117
121
  end
118
122
  end
@@ -130,24 +134,24 @@ end
130
134
  # @filter [String, Regexp,nil] :href Matches the normalized href of the link, if nil will find <a> elements with no href attribute
131
135
  #
132
136
  Capybara.add_selector(:link) do
133
- xpath(:title, :alt) do |locator, options={}|
137
+ xpath(:title, :alt) do |locator, href: true, enable_aria_label: false, alt: nil, title: nil, **_options|
134
138
  xpath = XPath.descendant(:a)
135
- xpath = if options.fetch(:href, true).nil?
136
- xpath[~XPath.attr(:href)]
139
+ xpath = if href.nil?
140
+ xpath[!XPath.attr(:href)]
137
141
  else
138
142
  xpath[XPath.attr(:href)]
139
143
  end
140
144
  unless locator.nil?
141
145
  locator = locator.to_s
142
- matchers = XPath.attr(:id).equals(locator).or(
143
- XPath.string.n.is(locator)).or(
144
- XPath.attr(:title).is(locator)).or(
145
- XPath.descendant(:img)[XPath.attr(:alt).is(locator)])
146
- matchers = matchers.or XPath.attr(:'aria-label').is(locator) if options[:enable_aria_label]
146
+ matchers = [XPath.attr(:id) == locator,
147
+ XPath.string.n.is(locator),
148
+ XPath.attr(:title).is(locator),
149
+ XPath.descendant(:img)[XPath.attr(:alt).is(locator)]].reduce(:|)
150
+ matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
147
151
  xpath = xpath[matchers]
148
152
  end
149
- xpath = [:title].inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
150
- xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt).equals(options[:alt])]] if options[:alt]
153
+ xpath = xpath[find_by_attr(:title, title)]
154
+ xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt) == alt]] if alt
151
155
  xpath
152
156
  end
153
157
 
@@ -158,12 +162,12 @@ Capybara.add_selector(:link) do
158
162
  when Regexp
159
163
  node[:href].match href
160
164
  else
161
- node.first(:xpath, XPath.axis(:self)[XPath.attr(:href).equals(href.to_s)], minimum: 0)
165
+ node.first(:xpath, XPath.self[XPath.attr(:href) == href.to_s], minimum: 0)
162
166
  end
163
167
  end
164
168
 
165
- describe do |options|
166
- desc = String.new()
169
+ describe do |**options|
170
+ desc = "".dup
167
171
  desc << " with href #{options[:href].inspect}" if options[:href]
168
172
  desc << " with no href attribute" if options.fetch(:href, true).nil?
169
173
  end
@@ -181,22 +185,22 @@ end
181
185
  # @filter [String] :value Matches the value of an input button
182
186
  #
183
187
  Capybara.add_selector(:button) do
184
- xpath(:value, :title) do |locator, options={}|
188
+ xpath(:value, :title) do |locator, **options|
185
189
  input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
186
190
  btn_xpath = XPath.descendant(:button)
187
- image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).equals('image')]
191
+ image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type) == 'image']
188
192
 
189
193
  unless locator.nil?
190
194
  locator = locator.to_s
191
- locator_matches = XPath.attr(:id).equals(locator).or XPath.attr(:value).is(locator).or XPath.attr(:title).is(locator)
192
- locator_matches = locator_matches.or XPath.attr(:'aria-label').is(locator) if options[:enable_aria_label]
195
+ locator_matches = XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.attr(:title).is(locator)
196
+ locator_matches |= XPath.attr(:'aria-label').is(locator) if options[:enable_aria_label]
193
197
 
194
198
  input_btn_xpath = input_btn_xpath[locator_matches]
195
199
 
196
- btn_xpath = btn_xpath[locator_matches.or XPath.string.n.is(locator).or XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]
200
+ btn_xpath = btn_xpath[locator_matches | XPath.string.n.is(locator) | XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]
197
201
 
198
202
  alt_matches = XPath.attr(:alt).is(locator)
199
- alt_matches = alt_matches.or XPath.attr(:'aria-label').is(locator) if options[:enable_aria_label]
203
+ alt_matches |= XPath.attr(:'aria-label').is(locator) if options[:enable_aria_label]
200
204
  image_btn_xpath = image_btn_xpath[alt_matches]
201
205
  end
202
206
 
@@ -207,11 +211,11 @@ Capybara.add_selector(:button) do
207
211
  res_xpath
208
212
  end
209
213
 
210
- filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
214
+ filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
211
215
 
212
- describe do |options|
213
- desc = String.new
214
- desc << " that is disabled" if options[:disabled] == true
216
+ describe do |disabled: nil, **options|
217
+ desc = "".dup
218
+ desc << " that is disabled" if disabled == true
215
219
  desc << describe_all_expression_filters(options)
216
220
  desc
217
221
  end
@@ -223,13 +227,13 @@ end
223
227
  #
224
228
  Capybara.add_selector(:link_or_button) do
225
229
  label "link or button"
226
- xpath do |locator, options|
227
- self.class.all.values_at(:link, :button).map {|selector| selector.xpath.call(locator, options)}.reduce(:union)
230
+ xpath do |locator, **options|
231
+ self.class.all.values_at(:link, :button).map { |selector| selector.xpath.call(locator, options) }.reduce(:union)
228
232
  end
229
233
 
230
- filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
234
+ filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| node.tag_name == "a" or !(value ^ node.disabled?) }
231
235
 
232
- describe { |options| " that is disabled" if options[:disabled] }
236
+ describe { |disabled: nil, **_options| " that is disabled" if disabled == true }
233
237
  end
234
238
 
235
239
  ##
@@ -248,30 +252,31 @@ end
248
252
  #
249
253
  Capybara.add_selector(:fillable_field) do
250
254
  label "field"
251
- xpath do |locator, options|
252
- xpath = XPath.descendant(:input, :textarea)[~XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
255
+
256
+ xpath do |locator, **options|
257
+ xpath = XPath.descendant(:input, :textarea)[!XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
253
258
  locate_field(xpath, locator, options)
254
259
  end
255
260
 
256
261
  expression_filter(:type) do |expr, type|
257
262
  type = type.to_s
258
263
  if ['textarea'].include?(type)
259
- expr.axis(:self, type.to_sym)
264
+ expr.self(type.to_sym)
260
265
  else
261
- expr[XPath.attr(:type).equals(type)]
266
+ expr[XPath.attr(:type) == type]
262
267
  end
263
268
  end
264
269
 
265
- filter_set(:_field, [:disabled, :multiple, :name, :placeholder])
270
+ filter_set(:_field, %i[disabled multiple name placeholder])
266
271
 
267
272
  filter(:with) do |node, with|
268
273
  with.is_a?(Regexp) ? node.value =~ with : node.value == with.to_s
269
274
  end
270
275
 
271
276
  describe do |options|
272
- desc = String.new
277
+ desc = "".dup
273
278
  desc << describe_all_expression_filters(options)
274
- desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
279
+ desc << " with value #{options[:with].to_s.inspect}" if options.key?(:with)
275
280
  desc
276
281
  end
277
282
  end
@@ -291,18 +296,19 @@ end
291
296
  #
292
297
  Capybara.add_selector(:radio_button) do
293
298
  label "radio button"
294
- xpath do |locator, options|
295
- xpath = XPath.descendant(:input)[XPath.attr(:type).equals('radio')]
299
+
300
+ xpath do |locator, **options|
301
+ xpath = XPath.descendant(:input)[XPath.attr(:type) == 'radio']
296
302
  locate_field(xpath, locator, options)
297
303
  end
298
304
 
299
- filter_set(:_field, [:checked, :unchecked, :disabled, :name])
305
+ filter_set(:_field, %i[checked unchecked disabled name])
300
306
 
301
- filter(:option) { |node, value| node.value == value.to_s }
307
+ filter(:option) { |node, value| node.value == value.to_s }
302
308
 
303
- describe do |options|
304
- desc = String.new
305
- desc << " with value #{options[:option].inspect}" if options[:option]
309
+ describe do |option: nil, **options|
310
+ desc = "".dup
311
+ desc << " with value #{option.inspect}" if option
306
312
  desc << describe_all_expression_filters(options)
307
313
  desc
308
314
  end
@@ -322,18 +328,18 @@ end
322
328
  # @filter [String] :option Match the value
323
329
  #
324
330
  Capybara.add_selector(:checkbox) do
325
- xpath do |locator, options|
326
- xpath = XPath.descendant(:input)[XPath.attr(:type).equals('checkbox')]
331
+ xpath do |locator, **options|
332
+ xpath = XPath.descendant(:input)[XPath.attr(:type) == 'checkbox']
327
333
  locate_field(xpath, locator, options)
328
334
  end
329
335
 
330
- filter_set(:_field, [:checked, :unchecked, :disabled, :name])
336
+ filter_set(:_field, %i[checked unchecked disabled name])
331
337
 
332
- filter(:option) { |node, value| node.value == value.to_s }
338
+ filter(:option) { |node, value| node.value == value.to_s }
333
339
 
334
- describe do |options|
335
- desc = String.new
336
- desc << " with value #{options[:option].inspect}" if options[:option]
340
+ describe do |option: nil, **options|
341
+ desc = "".dup
342
+ desc << " with value #{option.inspect}" if option
337
343
  desc << describe_all_expression_filters(options)
338
344
  desc
339
345
  end
@@ -357,47 +363,46 @@ end
357
363
  #
358
364
  Capybara.add_selector(:select) do
359
365
  label "select box"
360
- xpath do |locator, options|
366
+
367
+ xpath do |locator, **options|
361
368
  xpath = XPath.descendant(:select)
362
369
  locate_field(xpath, locator, options)
363
370
  end
364
371
 
365
- filter_set(:_field, [:disabled, :multiple, :name, :placeholder])
372
+ filter_set(:_field, %i[disabled multiple name placeholder])
366
373
 
367
374
  filter(:options) do |node, options|
368
- if node.visible?
369
- actual = node.all(:xpath, './/option').map { |option| option.text }
375
+ actual = if node.visible?
376
+ node.all(:xpath, './/option', wait: false).map(&:text)
370
377
  else
371
- actual = node.all(:xpath, './/option', visible: false).map { |option| option.text(:all) }
378
+ node.all(:xpath, './/option', visible: false, wait: false).map { |option| option.text(:all) }
372
379
  end
373
380
  options.sort == actual.sort
374
381
  end
375
382
 
376
383
  filter(:with_options) do |node, options|
377
384
  finder_settings = { minimum: 0 }
378
- if !node.visible?
379
- finder_settings[:visible] = false
380
- end
385
+ finder_settings[:visible] = false unless node.visible?
381
386
  options.all? { |option| node.first(:option, option, finder_settings) }
382
387
  end
383
388
 
384
389
  filter(:selected) do |node, selected|
385
- actual = node.all(:xpath, './/option', visible: false).select(&:selected?).map { |option| option.text(:all) }
390
+ actual = node.all(:xpath, './/option', visible: false, wait: false).select(&:selected?).map { |option| option.text(:all) }
386
391
  Array(selected).sort == actual.sort
387
392
  end
388
393
 
389
394
  filter(:with_selected) do |node, selected|
390
- actual = node.all(:xpath, './/option', visible: false).select(&:selected?).map { |option| option.text(:all) }
395
+ actual = node.all(:xpath, './/option', visible: false, wait: false).select(&:selected?).map { |option| option.text(:all) }
391
396
  (Array(selected) - actual).empty?
392
397
  end
393
398
 
394
- describe do |options|
395
- desc = String.new
396
- desc << " with options #{options[:options].inspect}" if options[:options]
397
- desc << " with at least options #{options[:with_options].inspect}" if options[:with_options]
398
- desc << " with #{options[:selected].inspect} selected" if options[:selected]
399
- desc << " with at least #{options[:with_selected].inspect} selected" if options[:with_selected]
400
- desc << describe_all_expression_filters(options)
399
+ describe do |options: nil, with_options: nil, selected: nil, with_selected: nil, **opts|
400
+ desc = "".dup
401
+ desc << " with options #{options.inspect}" if options
402
+ desc << " with at least options #{with_options.inspect}" if with_options
403
+ desc << " with #{selected.inspect} selected" if selected
404
+ desc << " with at least #{with_selected.inspect} selected" if with_selected
405
+ desc << describe_all_expression_filters(opts)
401
406
  desc
402
407
  end
403
408
  end
@@ -417,13 +422,13 @@ Capybara.add_selector(:option) do
417
422
  xpath
418
423
  end
419
424
 
420
- filter(:disabled, :boolean) { |node, value| not(value ^ node.disabled?) }
421
- filter(:selected, :boolean) { |node, value| not(value ^ node.selected?) }
425
+ filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }
426
+ filter(:selected, :boolean) { |node, value| !(value ^ node.selected?) }
422
427
 
423
- describe do |options|
424
- desc = String.new
425
- desc << " that is#{' not' unless options[:disabled]} disabled" if options.has_key?(:disabled)
426
- desc << " that is#{' not' unless options[:selected]} selected" if options.has_key?(:selected)
428
+ describe do |**options|
429
+ desc = "".dup
430
+ desc << " that is#{' not' unless options[:disabled]} disabled" if options.key?(:disabled)
431
+ desc << " that is#{' not' unless options[:selected]} selected" if options.key?(:selected)
427
432
  desc
428
433
  end
429
434
  end
@@ -442,14 +447,14 @@ end
442
447
  Capybara.add_selector(:file_field) do
443
448
  label "file field"
444
449
  xpath do |locator, options|
445
- xpath = XPath.descendant(:input)[XPath.attr(:type).equals('file')]
450
+ xpath = XPath.descendant(:input)[XPath.attr(:type) == 'file']
446
451
  locate_field(xpath, locator, options)
447
452
  end
448
453
 
449
- filter_set(:_field, [:disabled, :multiple, :name])
454
+ filter_set(:_field, %i[disabled multiple name])
450
455
 
451
- describe do |options|
452
- desc = String.new
456
+ describe do |**options|
457
+ desc = "".dup
453
458
  desc << describe_all_expression_filters(options)
454
459
  desc
455
460
  end
@@ -466,9 +471,13 @@ Capybara.add_selector(:label) do
466
471
  label "label"
467
472
  xpath(:for) do |locator, options|
468
473
  xpath = XPath.descendant(:label)
469
- xpath = xpath[XPath.string.n.is(locator.to_s).or XPath.attr(:id).equals(locator.to_s)] unless locator.nil?
470
- if options.has_key?(:for) && !options[:for].is_a?(Capybara::Node::Element)
471
- xpath = xpath[XPath.attr(:for).equals(options[:for].to_s).or((~XPath.attr(:for)).and(XPath.descendant()[XPath.attr(:id).equals(options[:for].to_s)]))]
474
+ xpath = xpath[XPath.string.n.is(locator.to_s) | (XPath.attr(:id) == locator.to_s)] unless locator.nil?
475
+ if options.key?(:for) && !options[:for].is_a?(Capybara::Node::Element)
476
+ with_attr = XPath.attr(:for) == options[:for].to_s
477
+ labelable_elements = %i[button input keygen meter output progress select textarea]
478
+ wrapped = !XPath.attr(:for) &
479
+ XPath.descendant(*labelable_elements)[XPath.attr(:id) == options[:for].to_s]
480
+ xpath = xpath[with_attr | wrapped]
472
481
  end
473
482
  xpath
474
483
  end
@@ -481,13 +490,13 @@ Capybara.add_selector(:label) do
481
490
  field_or_value.find_xpath('./ancestor::label[1]').include? node.base
482
491
  end
483
492
  else
484
- #Non element values were handled through the expression filter
493
+ # Non element values were handled through the expression filter
485
494
  true
486
495
  end
487
496
  end
488
497
 
489
- describe do |options|
490
- desc = String.new
498
+ describe do |**options|
499
+ desc = "".dup
491
500
  desc << " for #{options[:for]}" if options[:for]
492
501
  desc
493
502
  end
@@ -505,14 +514,14 @@ end
505
514
  Capybara.add_selector(:table) do
506
515
  xpath(:caption) do |locator, options|
507
516
  xpath = XPath.descendant(:table)
508
- xpath = xpath[XPath.attr(:id).equals(locator.to_s).or XPath.descendant(:caption).is(locator.to_s)] unless locator.nil?
509
- xpath = xpath[XPath.descendant(:caption).equals(options[:caption])] if options[:caption]
517
+ xpath = xpath[(XPath.attr(:id) == locator.to_s) | XPath.descendant(:caption).is(locator.to_s)] unless locator.nil?
518
+ xpath = xpath[XPath.descendant(:caption) == options[:caption]] if options[:caption]
510
519
  xpath
511
520
  end
512
521
 
513
- describe do |options|
514
- desc = String.new
515
- desc << " with caption #{options[:caption]}" if options[:caption]
522
+ describe do |caption: nil, **_options|
523
+ desc = "".dup
524
+ desc << " with caption #{caption}" if caption
516
525
  desc
517
526
  end
518
527
  end
@@ -527,16 +536,19 @@ end
527
536
  # @filter [String, Array<String>] :class Matches the class(es) provided
528
537
  #
529
538
  Capybara.add_selector(:frame) do
530
- xpath(:name) do |locator, options|
539
+ xpath(:name) do |locator, **options|
531
540
  xpath = XPath.descendant(:iframe).union(XPath.descendant(:frame))
532
- xpath = xpath[XPath.attr(:id).equals(locator.to_s).or XPath.attr(:name).equals(locator)] unless locator.nil?
541
+ xpath = xpath[(XPath.attr(:id) == locator.to_s) | (XPath.attr(:name) == locator.to_s)] unless locator.nil?
533
542
  xpath = expression_filters.keys.inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
534
543
  xpath
535
544
  end
536
545
 
537
- describe do |options|
538
- desc = String.new
539
- desc << " with name #{options[:name]}" if options[:name]
546
+ describe do |name: nil, **_options|
547
+ desc = "".dup
548
+ desc << " with name #{name}" if name
540
549
  desc
541
550
  end
542
551
  end
552
+
553
+ # rubocop:enable Metrics/BlockLength
554
+ # rubocop:enable Metrics/ParameterLists