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.
- checksums.yaml +5 -5
- data/History.md +137 -2
- data/README.md +36 -25
- data/lib/capybara/config.rb +11 -57
- data/lib/capybara/cucumber.rb +2 -3
- data/lib/capybara/driver/base.rb +19 -16
- data/lib/capybara/driver/node.rb +5 -4
- data/lib/capybara/dsl.rb +1 -0
- data/lib/capybara/helpers.rb +19 -29
- data/lib/capybara/minitest/spec.rb +16 -13
- data/lib/capybara/minitest.rb +140 -137
- data/lib/capybara/node/actions.rb +68 -89
- data/lib/capybara/node/base.rb +11 -18
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +8 -8
- data/lib/capybara/node/element.rb +32 -42
- data/lib/capybara/node/finders.rb +64 -71
- data/lib/capybara/node/matchers.rb +50 -71
- data/lib/capybara/node/simple.rb +11 -17
- data/lib/capybara/queries/ancestor_query.rb +12 -8
- data/lib/capybara/queries/base_query.rb +22 -18
- data/lib/capybara/queries/current_path_query.rb +12 -25
- data/lib/capybara/queries/match_query.rb +3 -7
- data/lib/capybara/queries/selector_query.rb +100 -96
- data/lib/capybara/queries/sibling_query.rb +5 -5
- data/lib/capybara/queries/text_query.rb +35 -35
- data/lib/capybara/queries/title_query.rb +8 -11
- data/lib/capybara/rack_test/browser.rb +15 -18
- data/lib/capybara/rack_test/css_handlers.rb +6 -4
- data/lib/capybara/rack_test/driver.rb +6 -10
- data/lib/capybara/rack_test/form.rb +52 -39
- data/lib/capybara/rack_test/node.rb +93 -63
- data/lib/capybara/rails.rb +2 -6
- data/lib/capybara/result.rb +22 -22
- data/lib/capybara/rspec/compound.rb +5 -10
- data/lib/capybara/rspec/features.rb +17 -48
- data/lib/capybara/rspec/matcher_proxies.rb +31 -15
- data/lib/capybara/rspec/matchers.rb +116 -58
- data/lib/capybara/rspec.rb +5 -10
- data/lib/capybara/selector/css.rb +6 -11
- data/lib/capybara/selector/filter.rb +1 -17
- data/lib/capybara/selector/filter_set.rb +18 -15
- data/lib/capybara/selector/filters/base.rb +7 -6
- data/lib/capybara/selector/filters/expression_filter.rb +6 -23
- data/lib/capybara/selector/filters/node_filter.rb +2 -12
- data/lib/capybara/selector/selector.rb +28 -34
- data/lib/capybara/selector.rb +129 -117
- data/lib/capybara/selenium/driver.rb +172 -163
- data/lib/capybara/selenium/node.rb +218 -104
- data/lib/capybara/server.rb +3 -2
- data/lib/capybara/session/config.rb +47 -59
- data/lib/capybara/session/matchers.rb +23 -14
- data/lib/capybara/session.rb +175 -229
- data/lib/capybara/spec/fixtures/no_extension +1 -0
- data/lib/capybara/spec/public/test.js +38 -6
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
- data/lib/capybara/spec/session/accept_prompt_spec.rb +30 -1
- data/lib/capybara/spec/session/all_spec.rb +31 -18
- data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
- data/lib/capybara/spec/session/assert_current_path.rb +12 -11
- data/lib/capybara/spec/session/assert_selector.rb +1 -0
- data/lib/capybara/spec/session/assert_text.rb +31 -23
- data/lib/capybara/spec/session/assert_title.rb +13 -3
- data/lib/capybara/spec/session/attach_file_spec.rb +57 -29
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +7 -6
- data/lib/capybara/spec/session/choose_spec.rb +5 -4
- data/lib/capybara/spec/session/click_button_spec.rb +24 -32
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
- data/lib/capybara/spec/session/click_link_spec.rb +8 -7
- data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
- data/lib/capybara/spec/session/current_url_spec.rb +19 -8
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
- data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +5 -4
- data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +30 -5
- data/lib/capybara/spec/session/find_button_spec.rb +4 -3
- data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
- data/lib/capybara/spec/session/find_field_spec.rb +9 -15
- data/lib/capybara/spec/session/find_link_spec.rb +6 -5
- data/lib/capybara/spec/session/find_spec.rb +37 -31
- data/lib/capybara/spec/session/first_spec.rb +60 -33
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
- data/lib/capybara/spec/session/go_back_spec.rb +1 -0
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_button_spec.rb +2 -1
- data/lib/capybara/spec/session/has_css_spec.rb +3 -2
- data/lib/capybara/spec/session/has_current_path_spec.rb +49 -22
- data/lib/capybara/spec/session/has_field_spec.rb +4 -3
- data/lib/capybara/spec/session/has_link_spec.rb +5 -4
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
- data/lib/capybara/spec/session/has_select_spec.rb +32 -31
- data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
- data/lib/capybara/spec/session/has_table_spec.rb +2 -1
- data/lib/capybara/spec/session/has_text_spec.rb +9 -13
- data/lib/capybara/spec/session/has_title_spec.rb +1 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
- data/lib/capybara/spec/session/headers.rb +2 -1
- data/lib/capybara/spec/session/html_spec.rb +1 -0
- data/lib/capybara/spec/session/node_spec.rb +107 -58
- data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
- data/lib/capybara/spec/session/refresh_spec.rb +6 -2
- data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
- data/lib/capybara/spec/session/response_code.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
- data/lib/capybara/spec/session/save_page_spec.rb +1 -17
- data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
- data/lib/capybara/spec/session/select_spec.rb +21 -20
- data/lib/capybara/spec/session/selectors_spec.rb +2 -2
- data/lib/capybara/spec/session/sibling_spec.rb +1 -1
- data/lib/capybara/spec/session/text_spec.rb +17 -3
- data/lib/capybara/spec/session/title_spec.rb +11 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
- data/lib/capybara/spec/session/unselect_spec.rb +7 -6
- data/lib/capybara/spec/session/visit_spec.rb +64 -3
- data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
- data/lib/capybara/spec/session/window/window_spec.rb +12 -12
- data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
- data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
- data/lib/capybara/spec/session/within_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +36 -18
- data/lib/capybara/spec/test_app.rb +17 -9
- data/lib/capybara/spec/views/form.erb +7 -0
- data/lib/capybara/spec/views/initial_alert.erb +10 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
- data/lib/capybara/spec/views/with_hover.erb +5 -0
- data/lib/capybara/spec/views/with_html.erb +27 -1
- data/lib/capybara/spec/views/with_js.erb +11 -0
- data/lib/capybara/spec/views/within_frames.erb +4 -1
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +6 -10
- data/lib/capybara.rb +29 -26
- data/spec/basic_node_spec.rb +1 -0
- data/spec/capybara_spec.rb +16 -69
- data/spec/dsl_spec.rb +5 -13
- data/spec/filter_set_spec.rb +5 -4
- data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
- data/spec/minitest_spec.rb +13 -4
- data/spec/minitest_spec_spec.rb +12 -3
- data/spec/per_session_config_spec.rb +9 -8
- data/spec/rack_test_spec.rb +21 -20
- data/spec/result_spec.rb +17 -16
- data/spec/rspec/features_spec.rb +17 -14
- data/spec/rspec/scenarios_spec.rb +5 -7
- data/spec/rspec/shared_spec_matchers.rb +96 -99
- data/spec/rspec/views_spec.rb +2 -1
- data/spec/rspec_matchers_spec.rb +18 -2
- data/spec/rspec_spec.rb +11 -15
- data/spec/selector_spec.rb +5 -6
- data/spec/selenium_spec_chrome.rb +20 -11
- data/spec/selenium_spec_edge.rb +27 -0
- data/spec/selenium_spec_ie.rb +31 -0
- data/spec/selenium_spec_marionette.rb +38 -12
- data/spec/server_spec.rb +33 -33
- data/spec/session_spec.rb +2 -1
- data/spec/shared_selenium_session.rb +82 -22
- data/spec/spec_helper.rb +3 -6
- metadata +76 -81
- data/lib/capybara/query.rb +0 -7
- 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)
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
data/lib/capybara/rspec.rb
CHANGED
@@ -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, :
|
10
|
-
config.include Capybara::RSpecMatchers, :
|
11
|
-
config.include Capybara::RSpecMatchers, :
|
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 =
|
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 <<
|
9
|
-
|
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
|
-
|
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
|
-
|
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(
|
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)
|
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
|
-
|
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, *
|
68
|
-
|
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.
|
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.
|
23
|
+
@options.key?(:skip_if) && value == @options[:skip_if]
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
+
private
|
26
27
|
|
27
28
|
def valid_value?(value)
|
28
|
-
!@options.
|
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
|