capybara 2.15.0 → 3.0.0

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 (177) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +137 -2
  3. data/README.md +36 -25
  4. data/lib/capybara/config.rb +11 -57
  5. data/lib/capybara/cucumber.rb +2 -3
  6. data/lib/capybara/driver/base.rb +19 -16
  7. data/lib/capybara/driver/node.rb +5 -4
  8. data/lib/capybara/dsl.rb +1 -0
  9. data/lib/capybara/helpers.rb +19 -29
  10. data/lib/capybara/minitest/spec.rb +16 -13
  11. data/lib/capybara/minitest.rb +140 -137
  12. data/lib/capybara/node/actions.rb +68 -89
  13. data/lib/capybara/node/base.rb +11 -18
  14. data/lib/capybara/node/document.rb +2 -2
  15. data/lib/capybara/node/document_matchers.rb +8 -8
  16. data/lib/capybara/node/element.rb +32 -42
  17. data/lib/capybara/node/finders.rb +64 -71
  18. data/lib/capybara/node/matchers.rb +50 -71
  19. data/lib/capybara/node/simple.rb +11 -17
  20. data/lib/capybara/queries/ancestor_query.rb +12 -8
  21. data/lib/capybara/queries/base_query.rb +22 -18
  22. data/lib/capybara/queries/current_path_query.rb +12 -25
  23. data/lib/capybara/queries/match_query.rb +3 -7
  24. data/lib/capybara/queries/selector_query.rb +100 -96
  25. data/lib/capybara/queries/sibling_query.rb +5 -5
  26. data/lib/capybara/queries/text_query.rb +35 -35
  27. data/lib/capybara/queries/title_query.rb +8 -11
  28. data/lib/capybara/rack_test/browser.rb +15 -18
  29. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  30. data/lib/capybara/rack_test/driver.rb +6 -10
  31. data/lib/capybara/rack_test/form.rb +52 -39
  32. data/lib/capybara/rack_test/node.rb +93 -63
  33. data/lib/capybara/rails.rb +2 -6
  34. data/lib/capybara/result.rb +22 -22
  35. data/lib/capybara/rspec/compound.rb +5 -10
  36. data/lib/capybara/rspec/features.rb +17 -48
  37. data/lib/capybara/rspec/matcher_proxies.rb +31 -15
  38. data/lib/capybara/rspec/matchers.rb +116 -58
  39. data/lib/capybara/rspec.rb +5 -10
  40. data/lib/capybara/selector/css.rb +6 -11
  41. data/lib/capybara/selector/filter.rb +1 -17
  42. data/lib/capybara/selector/filter_set.rb +18 -15
  43. data/lib/capybara/selector/filters/base.rb +7 -6
  44. data/lib/capybara/selector/filters/expression_filter.rb +6 -23
  45. data/lib/capybara/selector/filters/node_filter.rb +2 -12
  46. data/lib/capybara/selector/selector.rb +28 -34
  47. data/lib/capybara/selector.rb +129 -117
  48. data/lib/capybara/selenium/driver.rb +172 -163
  49. data/lib/capybara/selenium/node.rb +218 -104
  50. data/lib/capybara/server.rb +3 -2
  51. data/lib/capybara/session/config.rb +47 -59
  52. data/lib/capybara/session/matchers.rb +23 -14
  53. data/lib/capybara/session.rb +175 -229
  54. data/lib/capybara/spec/fixtures/no_extension +1 -0
  55. data/lib/capybara/spec/public/test.js +38 -6
  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 +30 -1
  59. data/lib/capybara/spec/session/all_spec.rb +31 -18
  60. data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
  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 +31 -23
  65. data/lib/capybara/spec/session/assert_title.rb +13 -3
  66. data/lib/capybara/spec/session/attach_file_spec.rb +57 -29
  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 +24 -32
  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 +19 -8
  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 +23 -0
  81. data/lib/capybara/spec/session/evaluate_script_spec.rb +5 -4
  82. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  83. data/lib/capybara/spec/session/fill_in_spec.rb +30 -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 +9 -15
  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/frame_title_spec.rb +23 -0
  91. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  92. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  93. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  94. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  95. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  96. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  97. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  98. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  99. data/lib/capybara/spec/session/has_current_path_spec.rb +49 -22
  100. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  101. data/lib/capybara/spec/session/has_link_spec.rb +5 -4
  102. data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
  103. data/lib/capybara/spec/session/has_select_spec.rb +32 -31
  104. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  105. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  106. data/lib/capybara/spec/session/has_text_spec.rb +9 -13
  107. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  108. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  109. data/lib/capybara/spec/session/headers.rb +2 -1
  110. data/lib/capybara/spec/session/html_spec.rb +1 -0
  111. data/lib/capybara/spec/session/node_spec.rb +107 -58
  112. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  113. data/lib/capybara/spec/session/refresh_spec.rb +6 -2
  114. data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
  115. data/lib/capybara/spec/session/response_code.rb +1 -0
  116. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  117. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  118. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  119. data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
  120. data/lib/capybara/spec/session/select_spec.rb +21 -20
  121. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  122. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  123. data/lib/capybara/spec/session/text_spec.rb +17 -3
  124. data/lib/capybara/spec/session/title_spec.rb +11 -1
  125. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  126. data/lib/capybara/spec/session/unselect_spec.rb +7 -6
  127. data/lib/capybara/spec/session/visit_spec.rb +64 -3
  128. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  129. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  130. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  131. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  132. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  133. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  134. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  135. data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
  136. data/lib/capybara/spec/session/within_spec.rb +1 -0
  137. data/lib/capybara/spec/spec_helper.rb +36 -18
  138. data/lib/capybara/spec/test_app.rb +17 -9
  139. data/lib/capybara/spec/views/form.erb +7 -0
  140. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  141. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  142. data/lib/capybara/spec/views/with_hover.erb +5 -0
  143. data/lib/capybara/spec/views/with_html.erb +27 -1
  144. data/lib/capybara/spec/views/with_js.erb +11 -0
  145. data/lib/capybara/spec/views/within_frames.erb +4 -1
  146. data/lib/capybara/version.rb +2 -1
  147. data/lib/capybara/window.rb +6 -10
  148. data/lib/capybara.rb +29 -26
  149. data/spec/basic_node_spec.rb +1 -0
  150. data/spec/capybara_spec.rb +16 -69
  151. data/spec/dsl_spec.rb +5 -13
  152. data/spec/filter_set_spec.rb +5 -4
  153. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  154. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  155. data/spec/minitest_spec.rb +13 -4
  156. data/spec/minitest_spec_spec.rb +12 -3
  157. data/spec/per_session_config_spec.rb +9 -8
  158. data/spec/rack_test_spec.rb +21 -20
  159. data/spec/result_spec.rb +17 -16
  160. data/spec/rspec/features_spec.rb +17 -14
  161. data/spec/rspec/scenarios_spec.rb +5 -7
  162. data/spec/rspec/shared_spec_matchers.rb +96 -99
  163. data/spec/rspec/views_spec.rb +2 -1
  164. data/spec/rspec_matchers_spec.rb +18 -2
  165. data/spec/rspec_spec.rb +11 -15
  166. data/spec/selector_spec.rb +5 -6
  167. data/spec/selenium_spec_chrome.rb +20 -11
  168. data/spec/selenium_spec_edge.rb +27 -0
  169. data/spec/selenium_spec_ie.rb +31 -0
  170. data/spec/selenium_spec_marionette.rb +38 -12
  171. data/spec/server_spec.rb +33 -33
  172. data/spec/session_spec.rb +2 -1
  173. data/spec/shared_selenium_session.rb +82 -22
  174. data/spec/spec_helper.rb +3 -6
  175. metadata +76 -81
  176. data/lib/capybara/query.rb +0 -7
  177. data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
4
  module RSpecMatchers
4
5
  class Matcher
5
- if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.0'))
6
+ if defined?(::RSpec::Expectations::Version)
6
7
  require 'capybara/rspec/compound'
7
8
  include ::Capybara::RSpecMatchers::Compound
8
9
  end
@@ -10,18 +11,15 @@ module Capybara
10
11
  attr_reader :failure_message, :failure_message_when_negated
11
12
 
12
13
  def wrap(actual)
13
- @context_el = if actual.respond_to?("has_selector?")
14
+ actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
15
+ @context_el = if actual.respond_to?(:has_selector?)
14
16
  actual
15
17
  else
16
18
  Capybara.string(actual.to_s)
17
19
  end
18
20
  end
19
21
 
20
- # RSpec 2 compatibility:
21
- def failure_message_for_should; failure_message end
22
- def failure_message_for_should_not; failure_message_when_negated end
23
-
24
- private
22
+ private
25
23
 
26
24
  def wrap_matches?(actual)
27
25
  yield(wrap(actual))
@@ -59,18 +57,17 @@ module Capybara
59
57
  end
60
58
 
61
59
  class HaveSelector < Matcher
62
-
63
60
  def initialize(*args, &filter_block)
64
61
  @args = args
65
62
  @filter_block = filter_block
66
63
  end
67
64
 
68
65
  def matches?(actual)
69
- wrap_matches?(actual){ |el| el.assert_selector(*@args, &@filter_block) }
66
+ wrap_matches?(actual) { |el| el.assert_selector(*@args, &@filter_block) }
70
67
  end
71
68
 
72
69
  def does_not_match?(actual)
73
- wrap_does_not_match?(actual){ |el| el.assert_no_selector(*@args, &@filter_block) }
70
+ wrap_does_not_match?(actual) { |el| el.assert_no_selector(*@args, &@filter_block) }
74
71
  end
75
72
 
76
73
  def description
@@ -82,6 +79,44 @@ module Capybara
82
79
  end
83
80
  end
84
81
 
82
+ class HaveAllSelectors < Matcher
83
+ def initialize(*args, &filter_block)
84
+ @args = args
85
+ @filter_block = filter_block
86
+ end
87
+
88
+ def matches?(actual)
89
+ wrap_matches?(actual) { |el| el.assert_all_of_selectors(*@args, &@filter_block) }
90
+ end
91
+
92
+ def does_not_match?(_actual)
93
+ raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
94
+ end
95
+
96
+ def description
97
+ "have all selectors"
98
+ end
99
+ end
100
+
101
+ class HaveNoSelectors < Matcher
102
+ def initialize(*args, &filter_block)
103
+ @args = args
104
+ @filter_block = filter_block
105
+ end
106
+
107
+ def matches?(actual)
108
+ wrap_matches?(actual) { |el| el.assert_none_of_selectors(*@args, &@filter_block) }
109
+ end
110
+
111
+ def does_not_match?(_actual)
112
+ raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
113
+ end
114
+
115
+ def description
116
+ "have no selectors"
117
+ end
118
+ end
119
+
85
120
  class MatchSelector < HaveSelector
86
121
  def matches?(actual)
87
122
  wrap_matches?(actual) { |el| el.assert_matches_selector(*@args, &@filter_block) }
@@ -101,15 +136,9 @@ module Capybara
101
136
  end
102
137
 
103
138
  class HaveText < Matcher
104
- attr_reader :type, :content, :options
105
-
106
139
  def initialize(*args)
107
140
  @args = args.dup
108
-
109
- # are set just for backwards compatability
110
- @type = args.shift if args.first.is_a?(Symbol)
111
- @content = args.shift
112
- @options = (args.first.is_a?(Hash))? args.first : {}
141
+ @content = args[0].is_a?(Symbol) ? args[1] : args[0]
113
142
  end
114
143
 
115
144
  def matches?(actual)
@@ -121,18 +150,15 @@ module Capybara
121
150
  end
122
151
 
123
152
  def description
124
- "text #{format(content)}"
153
+ "text #{format(@content)}"
125
154
  end
126
155
 
127
156
  def format(content)
128
- content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
129
157
  content.inspect
130
158
  end
131
159
  end
132
160
 
133
161
  class HaveTitle < Matcher
134
- attr_reader :title
135
-
136
162
  def initialize(*args)
137
163
  @args = args
138
164
 
@@ -149,17 +175,13 @@ module Capybara
149
175
  end
150
176
 
151
177
  def description
152
- "have title #{title.inspect}"
178
+ "have title #{@title.inspect}"
153
179
  end
154
180
  end
155
181
 
156
182
  class HaveCurrentPath < Matcher
157
- attr_reader :current_path
158
-
159
183
  def initialize(*args)
160
184
  @args = args
161
-
162
- # are set just for backwards compatability
163
185
  @current_path = args.first
164
186
  end
165
187
 
@@ -172,7 +194,33 @@ module Capybara
172
194
  end
173
195
 
174
196
  def description
175
- "have current path #{current_path.inspect}"
197
+ "have current path #{@current_path.inspect}"
198
+ end
199
+ end
200
+
201
+ class NegatedMatcher
202
+ def initialize(matcher)
203
+ @matcher = matcher
204
+ end
205
+
206
+ def matches?(actual)
207
+ @matcher.does_not_match?(actual)
208
+ end
209
+
210
+ def does_not_match?(actual)
211
+ @matcher.matches?(actual)
212
+ end
213
+
214
+ def description
215
+ "not #{@matcher.description}"
216
+ end
217
+
218
+ def failure_message
219
+ @matcher.failure_message_when_negated
220
+ end
221
+
222
+ def failure_message_when_negated
223
+ @matcher.failure_message
176
224
  end
177
225
  end
178
226
 
@@ -199,10 +247,6 @@ module Capybara
199
247
  def failure_message_when_negated
200
248
  "expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
201
249
  end
202
-
203
- # RSpec 2 compatibility:
204
- alias_method :failure_message_for_should, :failure_message
205
- alias_method :failure_message_for_should_not, :failure_message_when_negated
206
250
  end
207
251
 
208
252
  # RSpec matcher for whether the element(s) matching a given selector exist
@@ -211,112 +255,126 @@ module Capybara
211
255
  HaveSelector.new(*args, &optional_filter_block)
212
256
  end
213
257
 
258
+ # RSpec matcher for whether the element(s) matching a group of selectors exist
259
+ # See {Capybara::Node::Matcher#assert_all_of_selectors}
260
+ def have_all_of_selectors(*args, &optional_filter_block)
261
+ HaveAllSelectors.new(*args, &optional_filter_block)
262
+ end
263
+
264
+ # RSpec matcher for whether no element(s) matching a group of selectors exist
265
+ # See {Capybara::Node::Matcher#assert_none_of_selectors}
266
+ def have_none_of_selectors(*args, &optional_filter_block)
267
+ HaveNoSelectors.new(*args, &optional_filter_block)
268
+ end
269
+
214
270
  # RSpec matcher for whether the current element matches a given selector
215
271
  # See {Capybara::Node::Matchers#assert_matches_selector}
216
272
  def match_selector(*args, &optional_filter_block)
217
273
  MatchSelector.new(*args, &optional_filter_block)
218
274
  end
219
- # defined_negated_matcher was added in RSpec 3.1 - it's syntactic sugar only since a user can do
220
- # expect(page).not_to match_selector, so not sure we really need to support not_match_selector for prior to RSpec 3.1
221
- ::RSpec::Matchers.define_negated_matcher :not_match_selector, :match_selector if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.1'))
222
-
223
275
 
224
276
  # RSpec matcher for whether elements(s) matching a given xpath selector exist
225
277
  # See {Capybara::Node::Matchers#has_xpath?}
226
- def have_xpath(xpath, options={}, &optional_filter_block)
278
+ def have_xpath(xpath, **options, &optional_filter_block)
227
279
  HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
228
280
  end
229
281
 
230
282
  # RSpec matcher for whether the current element matches a given xpath selector
231
- def match_xpath(xpath, options={}, &optional_filter_block)
283
+ def match_xpath(xpath, **options, &optional_filter_block)
232
284
  MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
233
285
  end
234
286
 
235
287
  # RSpec matcher for whether elements(s) matching a given css selector exist
236
288
  # See {Capybara::Node::Matchers#has_css?}
237
- def have_css(css, options={}, &optional_filter_block)
289
+ def have_css(css, **options, &optional_filter_block)
238
290
  HaveSelector.new(:css, css, options, &optional_filter_block)
239
291
  end
240
292
 
241
293
  # RSpec matcher for whether the current element matches a given css selector
242
- def match_css(css, options={}, &optional_filter_block)
294
+ def match_css(css, **options, &optional_filter_block)
243
295
  MatchSelector.new(:css, css, options, &optional_filter_block)
244
296
  end
245
297
 
246
- # RSpec matcher for text on the page
298
+ # RSpec matcher for text content
247
299
  # See {Capybara::SessionMatchers#assert_text}
248
300
  def have_text(*args)
249
301
  HaveText.new(*args)
250
302
  end
251
303
  alias_method :have_content, :have_text
252
304
 
253
- def have_title(title, options = {})
305
+ def have_title(title, **options)
254
306
  HaveTitle.new(title, options)
255
307
  end
256
308
 
257
309
  # RSpec matcher for the current path
258
310
  # See {Capybara::SessionMatchers#assert_current_path}
259
- def have_current_path(path, options = {})
311
+ def have_current_path(path, **options)
260
312
  HaveCurrentPath.new(path, options)
261
313
  end
262
314
 
263
315
  # RSpec matcher for links
264
316
  # See {Capybara::Node::Matchers#has_link?}
265
- def have_link(locator=nil, options={}, &optional_filter_block)
266
- locator, options = nil, locator if locator.is_a? Hash
317
+ def have_link(locator = nil, **options, &optional_filter_block)
267
318
  HaveSelector.new(:link, locator, options, &optional_filter_block)
268
319
  end
269
320
 
270
321
  # RSpec matcher for buttons
271
322
  # See {Capybara::Node::Matchers#has_button?}
272
- def have_button(locator=nil, options={}, &optional_filter_block)
273
- locator, options = nil, locator if locator.is_a? Hash
323
+ def have_button(locator = nil, **options, &optional_filter_block)
274
324
  HaveSelector.new(:button, locator, options, &optional_filter_block)
275
325
  end
276
326
 
277
327
  # RSpec matcher for links
278
328
  # See {Capybara::Node::Matchers#has_field?}
279
- def have_field(locator=nil, options={}, &optional_filter_block)
280
- locator, options = nil, locator if locator.is_a? Hash
329
+ def have_field(locator = nil, **options, &optional_filter_block)
281
330
  HaveSelector.new(:field, locator, options, &optional_filter_block)
282
331
  end
283
332
 
284
333
  # RSpec matcher for checked fields
285
334
  # See {Capybara::Node::Matchers#has_checked_field?}
286
- def have_checked_field(locator=nil, options={}, &optional_filter_block)
287
- locator, options = nil, locator if locator.is_a? Hash
335
+ def have_checked_field(locator = nil, **options, &optional_filter_block)
288
336
  HaveSelector.new(:field, locator, options.merge(checked: true), &optional_filter_block)
289
337
  end
290
338
 
291
339
  # RSpec matcher for unchecked fields
292
340
  # See {Capybara::Node::Matchers#has_unchecked_field?}
293
- def have_unchecked_field(locator=nil, options={}, &optional_filter_block)
294
- locator, options = nil, locator if locator.is_a? Hash
341
+ def have_unchecked_field(locator = nil, **options, &optional_filter_block)
295
342
  HaveSelector.new(:field, locator, options.merge(unchecked: true), &optional_filter_block)
296
343
  end
297
344
 
298
345
  # RSpec matcher for select elements
299
346
  # See {Capybara::Node::Matchers#has_select?}
300
- def have_select(locator=nil, options={}, &optional_filter_block)
301
- locator, options = nil, locator if locator.is_a? Hash
347
+ def have_select(locator = nil, **options, &optional_filter_block)
302
348
  HaveSelector.new(:select, locator, options, &optional_filter_block)
303
349
  end
304
350
 
305
351
  # RSpec matcher for table elements
306
352
  # See {Capybara::Node::Matchers#has_table?}
307
- def have_table(locator=nil, options={}, &optional_filter_block)
308
- locator, options = nil, locator if locator.is_a? Hash
353
+ def have_table(locator = nil, **options, &optional_filter_block)
309
354
  HaveSelector.new(:table, locator, options, &optional_filter_block)
310
355
  end
311
356
 
357
+ %w[selector css xpath text title current_path link button field checked_field unchecked_field select table].each do |matcher_type|
358
+ define_method "have_no_#{matcher_type}" do |*args, &optional_filter_block|
359
+ NegatedMatcher.new(send("have_#{matcher_type}", *args, &optional_filter_block))
360
+ end
361
+ end
362
+ alias_method :have_no_content, :have_no_text
363
+
364
+ %w[selector css xpath].each do |matcher_type|
365
+ define_method "not_match_#{matcher_type}" do |*args, &optional_filter_block|
366
+ NegatedMatcher.new(send("match_#{matcher_type}", *args, &optional_filter_block))
367
+ end
368
+ end
369
+
312
370
  ##
313
371
  # Wait for window to become closed.
314
372
  # @example
315
373
  # expect(window).to become_closed(wait: 0.8)
316
374
  # @param options [Hash] optional param
317
375
  # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum wait time
318
- def become_closed(options = {})
376
+ def become_closed(**options)
319
377
  BecomeClosed.new(options)
320
378
  end
321
379
  end
322
- end
380
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'rspec/core'
3
4
  require 'capybara/dsl'
4
5
  require 'capybara/rspec/matchers'
@@ -6,14 +7,9 @@ require 'capybara/rspec/features'
6
7
  require 'capybara/rspec/matcher_proxies'
7
8
 
8
9
  RSpec.configure do |config|
9
- config.include Capybara::DSL, :type => :feature
10
- config.include Capybara::RSpecMatchers, :type => :feature
11
- config.include Capybara::RSpecMatchers, :type => :view
12
-
13
- # A work-around to support accessing the current example that works in both
14
- # RSpec 2 and RSpec 3.
15
- fetch_current_example = RSpec.respond_to?(:current_example) ?
16
- proc { RSpec.current_example } : proc { |context| context.example }
10
+ config.include Capybara::DSL, type: :feature
11
+ config.include Capybara::RSpecMatchers, type: :feature
12
+ config.include Capybara::RSpecMatchers, type: :view
17
13
 
18
14
  # The before and after blocks must run instantaneously, because Capybara
19
15
  # might not actually be used in all examples where it's included.
@@ -26,10 +22,9 @@ RSpec.configure do |config|
26
22
 
27
23
  config.before do
28
24
  if self.class.include?(Capybara::DSL)
29
- example = fetch_current_example.call(self)
25
+ example = RSpec.current_example
30
26
  Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]
31
27
  Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]
32
28
  end
33
29
  end
34
30
  end
35
-
@@ -2,24 +2,19 @@ module Capybara
2
2
  class Selector
3
3
  class CSS
4
4
  def self.escape(str)
5
- out = String.new("")
6
5
  value = str.dup
6
+ out = "".dup
7
7
  out << value.slice!(0...1) if value =~ /^[-_]/
8
- out << if value[0] =~ NMSTART
9
- value.slice!(0...1)
10
- else
11
- escape_char(value.slice!(0...1))
12
- end
13
- out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
8
+ out << (value[0] =~ NMSTART ? value.slice!(0...1) : escape_char(value.slice!(0...1)))
9
+ out << value.gsub(/[^a-zA-Z0-9_-]/) { |c| escape_char c }
14
10
  out
15
11
  end
16
12
 
17
13
  def self.escape_char(c)
18
- return "\\%06x" % c.ord() unless c =~ %r{[ -/:-~]}
19
- "\\#{c}"
14
+ c =~ %r{[ -/:-~]} ? "\\#{c}" : format("\\%06x", c.ord)
20
15
  end
21
16
 
22
- S = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
17
+ S = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'.freeze
23
18
  H = /[0-9a-fA-F]/
24
19
  UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
25
20
  NONASCII = /[#{S}]/
@@ -27,4 +22,4 @@ module Capybara
27
22
  NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
28
23
  end
29
24
  end
30
- end
25
+ end
@@ -1,20 +1,4 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara/selector/filters/node_filter'
3
4
  require 'capybara/selector/filters/expression_filter'
4
-
5
- module Capybara
6
- class Selector
7
- def self.const_missing(const_name)
8
- case const_name
9
- when :Filter
10
- warn "DEPRECATED: Capybara::Selector::Filter is deprecated, please use Capybara::Selector::Filters::NodeFilter instead"
11
- Filters::NodeFilter
12
- when :ExpressionFilter
13
- warn "DEPRECATED: Capybara::Selector::ExpressionFilter is deprecated, please use Capybara::Selector::Filters::ExpressionFilter instead"
14
- Filters::ExpressionFilter
15
- else
16
- super
17
- end
18
- end
19
- end
20
- end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara/selector/filter'
3
4
 
4
5
  module Capybara
@@ -24,14 +25,10 @@ module Capybara
24
25
  descriptions.push block
25
26
  end
26
27
 
27
- def description(options={})
28
- options_with_defaults = options.dup
29
- filters.each do |name, filter|
30
- options_with_defaults[name] = filter.default if filter.default? && !options_with_defaults.has_key?(name)
31
- end
32
-
28
+ def description(**options)
29
+ opts = options_with_defaults(options)
33
30
  @descriptions.map do |desc|
34
- desc.call(options_with_defaults).to_s
31
+ desc.call(opts).to_s
35
32
  end.join
36
33
  end
37
34
 
@@ -44,13 +41,12 @@ module Capybara
44
41
  end
45
42
 
46
43
  def expression_filters
47
- filters.select { |_n, f| f.nil? || f.is_a?(Filters::ExpressionFilter) }.freeze
44
+ filters.select { |_n, f| f.nil? || f.is_a?(Filters::ExpressionFilter) }.freeze
48
45
  end
49
46
 
50
47
  class << self
51
-
52
48
  def all
53
- @filter_sets ||= {}
49
+ @filter_sets ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
54
50
  end
55
51
 
56
52
  def add(name, &block)
@@ -62,13 +58,20 @@ module Capybara
62
58
  end
63
59
  end
64
60
 
65
- private
61
+ private
62
+
63
+ def options_with_defaults(options)
64
+ options = options.dup
65
+ filters.each do |name, filter|
66
+ options[name] = filter.default if filter.default? && !options.key?(name)
67
+ end
68
+ options
69
+ end
66
70
 
67
- def add_filter(name, filter_class, *types_and_options, &block)
68
- options = types_and_options.last.is_a?(Hash) ? types_and_options.pop.dup : {}
69
- types_and_options.each { |k| options[k] = true}
71
+ def add_filter(name, filter_class, *types, **options, &block)
72
+ types.each { |k| options[k] = true }
70
73
  filters[name] = filter_class.new(name, block, options)
71
74
  end
72
75
  end
73
76
  end
74
- end
77
+ end
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
4
  class Selector
4
5
  module Filters
5
6
  class Base
6
- def initialize(name, block, options={})
7
+ def initialize(name, block, **options)
7
8
  @name = name
8
9
  @block = block
9
10
  @options = options
10
- @options[:valid_values] = [true,false] if options[:boolean]
11
+ @options[:valid_values] = [true, false] if options[:boolean]
11
12
  end
12
13
 
13
14
  def default?
14
- @options.has_key?(:default)
15
+ @options.key?(:default)
15
16
  end
16
17
 
17
18
  def default
@@ -19,13 +20,13 @@ module Capybara
19
20
  end
20
21
 
21
22
  def skip?(value)
22
- @options.has_key?(:skip_if) && value == @options[:skip_if]
23
+ @options.key?(:skip_if) && value == @options[:skip_if]
23
24
  end
24
25
 
25
- private
26
+ private
26
27
 
27
28
  def valid_value?(value)
28
- !@options.has_key?(:valid_values) || Array(@options[:valid_values]).include?(value)
29
+ !@options.key?(:valid_values) || Array(@options[:valid_values]).include?(value)
29
30
  end
30
31
  end
31
32
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara/selector/filters/base'
3
4
 
4
5
  module Capybara
@@ -7,34 +8,16 @@ module Capybara
7
8
  class ExpressionFilter < Base
8
9
  def apply_filter(expr, value)
9
10
  return expr if skip?(value)
10
-
11
- if !valid_value?(value)
12
- msg = "Invalid value #{value.inspect} passed to expression filter #{@name} - "
13
- if default?
14
- warn msg + "defaulting to #{default}"
15
- value = default
16
- else
17
- warn msg + "skipping"
18
- return expr
19
- end
20
- end
21
-
11
+ raise "ArgumentError", "Invalid value #{value.inspect} passed to expression filter #{@name}" unless valid_value?(value)
22
12
  @block.call(expr, value)
23
13
  end
24
14
  end
25
15
 
26
16
  class IdentityExpressionFilter < ExpressionFilter
27
- def initialize
28
- end
29
-
30
- def default?
31
- false
32
- end
33
-
34
- def apply_filter(expr, _value)
35
- return expr
36
- end
17
+ def initialize; end
18
+ def default?; false; end
19
+ def apply_filter(expr, _value); expr; end
37
20
  end
38
21
  end
39
22
  end
40
- end
23
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara/selector/filters/base'
3
4
 
4
5
  module Capybara
@@ -7,18 +8,7 @@ module Capybara
7
8
  class NodeFilter < Base
8
9
  def matches?(node, value)
9
10
  return true if skip?(value)
10
-
11
- if !valid_value?(value)
12
- msg = "Invalid value #{value.inspect} passed to filter #{@name} - "
13
- if default?
14
- warn msg + "defaulting to #{default}"
15
- value = default
16
- else
17
- warn msg + "skipping"
18
- return true
19
- end
20
- end
21
-
11
+ raise ArgumentError, "Invalid value #{value.inspect} passed to filter #{@name}" unless valid_value?(value)
22
12
  @block.call(node, value)
23
13
  end
24
14
  end