capybara 2.18.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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +55 -1
  3. data/README.md +18 -17
  4. data/lib/capybara/config.rb +11 -58
  5. data/lib/capybara/cucumber.rb +2 -3
  6. data/lib/capybara/driver/base.rb +15 -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 +15 -14
  11. data/lib/capybara/minitest.rb +139 -138
  12. data/lib/capybara/node/actions.rb +60 -81
  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 +30 -40
  17. data/lib/capybara/node/finders.rb +62 -70
  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 +11 -7
  21. data/lib/capybara/queries/base_query.rb +22 -18
  22. data/lib/capybara/queries/current_path_query.rb +8 -24
  23. data/lib/capybara/queries/match_query.rb +3 -7
  24. data/lib/capybara/queries/selector_query.rb +92 -95
  25. data/lib/capybara/queries/sibling_query.rb +4 -4
  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 +50 -40
  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 +70 -61
  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 +131 -125
  49. data/lib/capybara/selenium/node.rb +197 -115
  50. data/lib/capybara/server.rb +3 -2
  51. data/lib/capybara/session/config.rb +47 -67
  52. data/lib/capybara/session/matchers.rb +8 -7
  53. data/lib/capybara/session.rb +138 -224
  54. data/lib/capybara/spec/public/test.js +25 -4
  55. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
  56. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
  57. data/lib/capybara/spec/session/accept_prompt_spec.rb +1 -0
  58. data/lib/capybara/spec/session/all_spec.rb +31 -18
  59. data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
  60. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
  61. data/lib/capybara/spec/session/assert_current_path.rb +12 -11
  62. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  63. data/lib/capybara/spec/session/assert_text.rb +23 -23
  64. data/lib/capybara/spec/session/assert_title.rb +13 -3
  65. data/lib/capybara/spec/session/attach_file_spec.rb +51 -30
  66. data/lib/capybara/spec/session/body_spec.rb +1 -0
  67. data/lib/capybara/spec/session/check_spec.rb +7 -6
  68. data/lib/capybara/spec/session/choose_spec.rb +5 -4
  69. data/lib/capybara/spec/session/click_button_spec.rb +24 -32
  70. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
  71. data/lib/capybara/spec/session/click_link_spec.rb +8 -7
  72. data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
  73. data/lib/capybara/spec/session/current_url_spec.rb +17 -6
  74. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
  75. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
  76. data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
  77. data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
  78. data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
  79. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +3 -2
  80. data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
  81. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  82. data/lib/capybara/spec/session/fill_in_spec.rb +30 -5
  83. data/lib/capybara/spec/session/find_button_spec.rb +4 -3
  84. data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
  85. data/lib/capybara/spec/session/find_field_spec.rb +9 -15
  86. data/lib/capybara/spec/session/find_link_spec.rb +6 -5
  87. data/lib/capybara/spec/session/find_spec.rb +37 -31
  88. data/lib/capybara/spec/session/first_spec.rb +60 -33
  89. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  90. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  91. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  92. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  93. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  94. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  95. data/lib/capybara/spec/session/has_all_selectors_spec.rb +15 -15
  96. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  97. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  98. data/lib/capybara/spec/session/has_current_path_spec.rb +12 -28
  99. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  100. data/lib/capybara/spec/session/has_link_spec.rb +1 -0
  101. data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
  102. data/lib/capybara/spec/session/has_select_spec.rb +30 -29
  103. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  104. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  105. data/lib/capybara/spec/session/has_text_spec.rb +9 -13
  106. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  107. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  108. data/lib/capybara/spec/session/headers.rb +2 -1
  109. data/lib/capybara/spec/session/html_spec.rb +1 -0
  110. data/lib/capybara/spec/session/node_spec.rb +91 -56
  111. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  112. data/lib/capybara/spec/session/refresh_spec.rb +6 -2
  113. data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
  114. data/lib/capybara/spec/session/response_code.rb +1 -0
  115. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  116. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  117. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  118. data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
  119. data/lib/capybara/spec/session/select_spec.rb +20 -20
  120. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  121. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  122. data/lib/capybara/spec/session/text_spec.rb +17 -3
  123. data/lib/capybara/spec/session/title_spec.rb +11 -1
  124. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  125. data/lib/capybara/spec/session/unselect_spec.rb +6 -5
  126. data/lib/capybara/spec/session/visit_spec.rb +9 -3
  127. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  128. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  129. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  130. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  131. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  132. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  133. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  134. data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
  135. data/lib/capybara/spec/session/within_spec.rb +1 -0
  136. data/lib/capybara/spec/spec_helper.rb +34 -18
  137. data/lib/capybara/spec/test_app.rb +17 -9
  138. data/lib/capybara/spec/views/form.erb +7 -0
  139. data/lib/capybara/spec/views/with_html.erb +23 -1
  140. data/lib/capybara/spec/views/within_frames.erb +4 -1
  141. data/lib/capybara/version.rb +2 -1
  142. data/lib/capybara/window.rb +6 -10
  143. data/lib/capybara.rb +28 -25
  144. data/spec/basic_node_spec.rb +1 -0
  145. data/spec/capybara_spec.rb +11 -50
  146. data/spec/dsl_spec.rb +5 -13
  147. data/spec/filter_set_spec.rb +5 -4
  148. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  149. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  150. data/spec/minitest_spec.rb +4 -3
  151. data/spec/minitest_spec_spec.rb +3 -2
  152. data/spec/per_session_config_spec.rb +9 -8
  153. data/spec/rack_test_spec.rb +21 -20
  154. data/spec/result_spec.rb +17 -16
  155. data/spec/rspec/features_spec.rb +17 -14
  156. data/spec/rspec/scenarios_spec.rb +5 -7
  157. data/spec/rspec/shared_spec_matchers.rb +96 -99
  158. data/spec/rspec/views_spec.rb +2 -1
  159. data/spec/rspec_matchers_spec.rb +18 -2
  160. data/spec/rspec_spec.rb +11 -15
  161. data/spec/selector_spec.rb +5 -6
  162. data/spec/selenium_spec_chrome.rb +9 -4
  163. data/spec/selenium_spec_edge.rb +27 -0
  164. data/spec/selenium_spec_ie.rb +31 -0
  165. data/spec/selenium_spec_marionette.rb +28 -12
  166. data/spec/server_spec.rb +33 -33
  167. data/spec/session_spec.rb +2 -1
  168. data/spec/shared_selenium_session.rb +36 -22
  169. data/spec/spec_helper.rb +3 -6
  170. metadata +68 -85
  171. data/lib/capybara/query.rb +0 -7
  172. data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
4
  module RSpecMatcherProxies
4
- def all(*args)
5
+ def all(*args, &block)
5
6
  if defined?(::RSpec::Matchers::BuiltIn::All) && args.first.respond_to?(:matches?)
6
7
  ::RSpec::Matchers::BuiltIn::All.new(*args)
7
8
  else
8
- find_all(*args)
9
+ find_all(*args, &block)
9
10
  end
10
11
  end
11
12
 
@@ -18,28 +19,43 @@ module Capybara
18
19
  end
19
20
  end
20
21
 
21
- module DSL
22
- class <<self
23
- remove_method :included
24
-
22
+ module DSLRSpecProxyInstaller
23
+ module ClassMethods
25
24
  def included(base)
26
- warn "including Capybara::DSL in the global scope is not recommended!" if base == Object
27
-
28
- if defined?(::RSpec::Matchers) && base.include?(::RSpec::Matchers)
29
- base.send(:include, ::Capybara::RSpecMatcherProxies)
25
+ if defined?(::RSpec::Matchers)
26
+ base.include(::Capybara::RSpecMatcherProxies) if base.include?(::RSpec::Matchers)
30
27
  end
28
+ super
29
+ end
30
+ end
31
+
32
+ def self.prepended(base)
33
+ class <<base
34
+ prepend ClassMethods
35
+ end
36
+ end
37
+ end
31
38
 
39
+ module RSpecMatcherProxyInstaller
40
+ module ClassMethods
41
+ def included(base)
42
+ base.include(::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)
32
43
  super
33
44
  end
34
45
  end
46
+
47
+ def self.prepended(base)
48
+ class <<base
49
+ prepend ClassMethods
50
+ end
51
+ end
35
52
  end
53
+
54
+ DSL.prepend ::Capybara::DSLRSpecProxyInstaller
36
55
  end
37
56
 
38
57
  if defined?(::RSpec::Matchers)
39
- module ::RSpec::Matchers
40
- def self.included(base)
41
- base.send(:include, ::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)
42
- super
43
- end
58
+ module ::RSpec::Matchers
59
+ prepend ::Capybara::RSpecMatcherProxyInstaller
44
60
  end
45
61
  end
@@ -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))
@@ -65,11 +63,11 @@ module Capybara
65
63
  end
66
64
 
67
65
  def matches?(actual)
68
- wrap_matches?(actual){ |el| el.assert_selector(*@args, &@filter_block) }
66
+ wrap_matches?(actual) { |el| el.assert_selector(*@args, &@filter_block) }
69
67
  end
70
68
 
71
69
  def does_not_match?(actual)
72
- 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) }
73
71
  end
74
72
 
75
73
  def description
@@ -88,10 +86,10 @@ module Capybara
88
86
  end
89
87
 
90
88
  def matches?(actual)
91
- wrap_matches?(actual){ |el| el.assert_all_of_selectors(*@args, &@filter_block) }
89
+ wrap_matches?(actual) { |el| el.assert_all_of_selectors(*@args, &@filter_block) }
92
90
  end
93
91
 
94
- def does_not_match?(actual)
92
+ def does_not_match?(_actual)
95
93
  raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
96
94
  end
97
95
 
@@ -107,10 +105,10 @@ module Capybara
107
105
  end
108
106
 
109
107
  def matches?(actual)
110
- wrap_matches?(actual){ |el| el.assert_none_of_selectors(*@args, &@filter_block) }
108
+ wrap_matches?(actual) { |el| el.assert_none_of_selectors(*@args, &@filter_block) }
111
109
  end
112
110
 
113
- def does_not_match?(actual)
111
+ def does_not_match?(_actual)
114
112
  raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
115
113
  end
116
114
 
@@ -138,15 +136,9 @@ module Capybara
138
136
  end
139
137
 
140
138
  class HaveText < Matcher
141
- attr_reader :type, :content, :options
142
-
143
139
  def initialize(*args)
144
140
  @args = args.dup
145
-
146
- # are set just for backwards compatability
147
- @type = args.shift if args.first.is_a?(Symbol)
148
- @content = args.shift
149
- @options = (args.first.is_a?(Hash))? args.first : {}
141
+ @content = args[0].is_a?(Symbol) ? args[1] : args[0]
150
142
  end
151
143
 
152
144
  def matches?(actual)
@@ -158,18 +150,15 @@ module Capybara
158
150
  end
159
151
 
160
152
  def description
161
- "text #{format(content)}"
153
+ "text #{format(@content)}"
162
154
  end
163
155
 
164
156
  def format(content)
165
- content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
166
157
  content.inspect
167
158
  end
168
159
  end
169
160
 
170
161
  class HaveTitle < Matcher
171
- attr_reader :title
172
-
173
162
  def initialize(*args)
174
163
  @args = args
175
164
 
@@ -186,17 +175,13 @@ module Capybara
186
175
  end
187
176
 
188
177
  def description
189
- "have title #{title.inspect}"
178
+ "have title #{@title.inspect}"
190
179
  end
191
180
  end
192
181
 
193
182
  class HaveCurrentPath < Matcher
194
- attr_reader :current_path
195
-
196
183
  def initialize(*args)
197
184
  @args = args
198
-
199
- # are set just for backwards compatability
200
185
  @current_path = args.first
201
186
  end
202
187
 
@@ -209,7 +194,33 @@ module Capybara
209
194
  end
210
195
 
211
196
  def description
212
- "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
213
224
  end
214
225
  end
215
226
 
@@ -236,10 +247,6 @@ module Capybara
236
247
  def failure_message_when_negated
237
248
  "expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
238
249
  end
239
-
240
- # RSpec 2 compatibility:
241
- alias_method :failure_message_for_should, :failure_message
242
- alias_method :failure_message_for_should_not, :failure_message_when_negated
243
250
  end
244
251
 
245
252
  # RSpec matcher for whether the element(s) matching a given selector exist
@@ -265,107 +272,109 @@ module Capybara
265
272
  def match_selector(*args, &optional_filter_block)
266
273
  MatchSelector.new(*args, &optional_filter_block)
267
274
  end
268
- # defined_negated_matcher was added in RSpec 3.1 - it's syntactic sugar only since a user can do
269
- # expect(page).not_to match_selector, so not sure we really need to support not_match_selector for prior to RSpec 3.1
270
- ::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'))
271
-
272
275
 
273
276
  # RSpec matcher for whether elements(s) matching a given xpath selector exist
274
277
  # See {Capybara::Node::Matchers#has_xpath?}
275
- def have_xpath(xpath, options={}, &optional_filter_block)
278
+ def have_xpath(xpath, **options, &optional_filter_block)
276
279
  HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
277
280
  end
278
281
 
279
282
  # RSpec matcher for whether the current element matches a given xpath selector
280
- def match_xpath(xpath, options={}, &optional_filter_block)
283
+ def match_xpath(xpath, **options, &optional_filter_block)
281
284
  MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
282
285
  end
283
286
 
284
287
  # RSpec matcher for whether elements(s) matching a given css selector exist
285
288
  # See {Capybara::Node::Matchers#has_css?}
286
- def have_css(css, options={}, &optional_filter_block)
289
+ def have_css(css, **options, &optional_filter_block)
287
290
  HaveSelector.new(:css, css, options, &optional_filter_block)
288
291
  end
289
292
 
290
293
  # RSpec matcher for whether the current element matches a given css selector
291
- def match_css(css, options={}, &optional_filter_block)
294
+ def match_css(css, **options, &optional_filter_block)
292
295
  MatchSelector.new(:css, css, options, &optional_filter_block)
293
296
  end
294
297
 
295
- # RSpec matcher for text on the page
298
+ # RSpec matcher for text content
296
299
  # See {Capybara::SessionMatchers#assert_text}
297
300
  def have_text(*args)
298
301
  HaveText.new(*args)
299
302
  end
300
303
  alias_method :have_content, :have_text
301
304
 
302
- def have_title(title, options = {})
305
+ def have_title(title, **options)
303
306
  HaveTitle.new(title, options)
304
307
  end
305
308
 
306
309
  # RSpec matcher for the current path
307
310
  # See {Capybara::SessionMatchers#assert_current_path}
308
- def have_current_path(path, options = {})
311
+ def have_current_path(path, **options)
309
312
  HaveCurrentPath.new(path, options)
310
313
  end
311
314
 
312
315
  # RSpec matcher for links
313
316
  # See {Capybara::Node::Matchers#has_link?}
314
- def have_link(locator=nil, options={}, &optional_filter_block)
315
- locator, options = nil, locator if locator.is_a? Hash
317
+ def have_link(locator = nil, **options, &optional_filter_block)
316
318
  HaveSelector.new(:link, locator, options, &optional_filter_block)
317
319
  end
318
320
 
319
321
  # RSpec matcher for buttons
320
322
  # See {Capybara::Node::Matchers#has_button?}
321
- def have_button(locator=nil, options={}, &optional_filter_block)
322
- locator, options = nil, locator if locator.is_a? Hash
323
+ def have_button(locator = nil, **options, &optional_filter_block)
323
324
  HaveSelector.new(:button, locator, options, &optional_filter_block)
324
325
  end
325
326
 
326
327
  # RSpec matcher for links
327
328
  # See {Capybara::Node::Matchers#has_field?}
328
- def have_field(locator=nil, options={}, &optional_filter_block)
329
- locator, options = nil, locator if locator.is_a? Hash
329
+ def have_field(locator = nil, **options, &optional_filter_block)
330
330
  HaveSelector.new(:field, locator, options, &optional_filter_block)
331
331
  end
332
332
 
333
333
  # RSpec matcher for checked fields
334
334
  # See {Capybara::Node::Matchers#has_checked_field?}
335
- def have_checked_field(locator=nil, options={}, &optional_filter_block)
336
- locator, options = nil, locator if locator.is_a? Hash
335
+ def have_checked_field(locator = nil, **options, &optional_filter_block)
337
336
  HaveSelector.new(:field, locator, options.merge(checked: true), &optional_filter_block)
338
337
  end
339
338
 
340
339
  # RSpec matcher for unchecked fields
341
340
  # See {Capybara::Node::Matchers#has_unchecked_field?}
342
- def have_unchecked_field(locator=nil, options={}, &optional_filter_block)
343
- locator, options = nil, locator if locator.is_a? Hash
341
+ def have_unchecked_field(locator = nil, **options, &optional_filter_block)
344
342
  HaveSelector.new(:field, locator, options.merge(unchecked: true), &optional_filter_block)
345
343
  end
346
344
 
347
345
  # RSpec matcher for select elements
348
346
  # See {Capybara::Node::Matchers#has_select?}
349
- def have_select(locator=nil, options={}, &optional_filter_block)
350
- locator, options = nil, locator if locator.is_a? Hash
347
+ def have_select(locator = nil, **options, &optional_filter_block)
351
348
  HaveSelector.new(:select, locator, options, &optional_filter_block)
352
349
  end
353
350
 
354
351
  # RSpec matcher for table elements
355
352
  # See {Capybara::Node::Matchers#has_table?}
356
- def have_table(locator=nil, options={}, &optional_filter_block)
357
- locator, options = nil, locator if locator.is_a? Hash
353
+ def have_table(locator = nil, **options, &optional_filter_block)
358
354
  HaveSelector.new(:table, locator, options, &optional_filter_block)
359
355
  end
360
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
+
361
370
  ##
362
371
  # Wait for window to become closed.
363
372
  # @example
364
373
  # expect(window).to become_closed(wait: 0.8)
365
374
  # @param options [Hash] optional param
366
375
  # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum wait time
367
- def become_closed(options = {})
376
+ def become_closed(**options)
368
377
  BecomeClosed.new(options)
369
378
  end
370
379
  end
371
- 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