capybara 2.18.0 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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