capybara 2.18.0 → 3.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +26 -1
- data/README.md +12 -12
- data/lib/capybara.rb +13 -25
- data/lib/capybara/config.rb +11 -57
- data/lib/capybara/cucumber.rb +2 -3
- data/lib/capybara/driver/base.rb +5 -16
- data/lib/capybara/driver/node.rb +5 -4
- data/lib/capybara/dsl.rb +1 -0
- data/lib/capybara/helpers.rb +16 -28
- data/lib/capybara/minitest.rb +139 -138
- data/lib/capybara/minitest/spec.rb +15 -14
- data/lib/capybara/node/actions.rb +59 -81
- 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 +30 -40
- data/lib/capybara/node/finders.rb +62 -70
- data/lib/capybara/node/matchers.rb +48 -71
- data/lib/capybara/node/simple.rb +11 -17
- data/lib/capybara/queries/ancestor_query.rb +4 -6
- data/lib/capybara/queries/base_query.rb +18 -17
- data/lib/capybara/queries/current_path_query.rb +8 -24
- data/lib/capybara/queries/match_query.rb +3 -7
- data/lib/capybara/queries/selector_query.rb +92 -95
- data/lib/capybara/queries/sibling_query.rb +4 -4
- data/lib/capybara/queries/text_query.rb +37 -34
- 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 +50 -40
- data/lib/capybara/rack_test/node.rb +70 -56
- data/lib/capybara/rails.rb +2 -6
- data/lib/capybara/result.rb +22 -22
- data/lib/capybara/rspec.rb +5 -10
- 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 +70 -60
- data/lib/capybara/selector.rb +129 -117
- data/lib/capybara/selector/css.rb +6 -11
- data/lib/capybara/selector/filter.rb +1 -17
- data/lib/capybara/selector/filter_set.rb +17 -14
- 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 +27 -33
- data/lib/capybara/selenium/driver.rb +113 -127
- data/lib/capybara/selenium/node.rb +148 -113
- data/lib/capybara/server.rb +3 -2
- data/lib/capybara/session.rb +137 -223
- data/lib/capybara/session/config.rb +47 -67
- data/lib/capybara/session/matchers.rb +8 -7
- data/lib/capybara/spec/public/test.js +26 -4
- 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 +1 -0
- data/lib/capybara/spec/session/all_spec.rb +31 -18
- data/lib/capybara/spec/session/ancestor_spec.rb +2 -4
- 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 +18 -17
- data/lib/capybara/spec/session/assert_title.rb +1 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +14 -13
- 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 +20 -28
- 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 +7 -6
- 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 +3 -2
- data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
- data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +6 -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 +8 -14
- 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/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 +15 -15
- 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 +12 -28
- data/lib/capybara/spec/session/has_field_spec.rb +4 -3
- data/lib/capybara/spec/session/has_link_spec.rb +1 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
- data/lib/capybara/spec/session/has_select_spec.rb +30 -29
- 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 +6 -5
- 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 +91 -56
- data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
- data/lib/capybara/spec/session/refresh_spec.rb +4 -2
- data/lib/capybara/spec/session/reset_session_spec.rb +1 -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 +1 -1
- data/lib/capybara/spec/session/select_spec.rb +20 -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 +1 -0
- data/lib/capybara/spec/session/title_spec.rb +1 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
- data/lib/capybara/spec/session/unselect_spec.rb +6 -5
- data/lib/capybara/spec/session/visit_spec.rb +9 -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 +13 -68
- data/lib/capybara/spec/session/within_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +26 -18
- data/lib/capybara/spec/test_app.rb +8 -9
- data/lib/capybara/spec/views/form.erb +1 -0
- data/lib/capybara/spec/views/with_html.erb +3 -1
- 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/spec/basic_node_spec.rb +1 -0
- data/spec/capybara_spec.rb +9 -32
- 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 +4 -3
- data/spec/minitest_spec_spec.rb +3 -2
- 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 +19 -2
- data/spec/rspec_spec.rb +11 -15
- data/spec/selector_spec.rb +5 -6
- data/spec/selenium_spec_chrome.rb +7 -4
- data/spec/selenium_spec_marionette.rb +26 -12
- data/spec/server_spec.rb +33 -33
- data/spec/session_spec.rb +2 -1
- data/spec/shared_selenium_session.rb +27 -21
- data/spec/spec_helper.rb +2 -5
- metadata +66 -87
- data/lib/capybara/query.rb +0 -7
- data/spec/selenium_spec_firefox.rb +0 -68
data/lib/capybara/rails.rb
CHANGED
@@ -1,14 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'capybara/dsl'
|
3
4
|
|
4
5
|
Capybara.app = Rack::Builder.new do
|
5
6
|
map "/" do
|
6
|
-
|
7
|
-
run Rails.application
|
8
|
-
else # Rails 2
|
9
|
-
use Rails::Rack::Static
|
10
|
-
run ActionController::Dispatcher.new
|
11
|
-
end
|
7
|
+
run Rails.application
|
12
8
|
end
|
13
9
|
end.to_app
|
14
10
|
|
data/lib/capybara/result.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'forwardable'
|
3
4
|
|
4
5
|
module Capybara
|
5
|
-
|
6
6
|
##
|
7
7
|
# A {Capybara::Result} represents a collection of {Capybara::Node::Element} on the page. It is possible to interact with this
|
8
8
|
# collection similar to an Array because it implements Enumerable and offers the following Array methods through delegation:
|
@@ -41,7 +41,7 @@ module Capybara
|
|
41
41
|
loop do
|
42
42
|
next_result = @results_enum.next
|
43
43
|
@result_cache << next_result
|
44
|
-
|
44
|
+
yield next_result
|
45
45
|
end
|
46
46
|
self
|
47
47
|
end
|
@@ -62,7 +62,7 @@ module Capybara
|
|
62
62
|
!any?
|
63
63
|
end
|
64
64
|
|
65
|
-
def
|
65
|
+
def compare_count
|
66
66
|
# Only check filters for as many elements as necessary to determine result
|
67
67
|
if @query.options[:count]
|
68
68
|
count_opt = Integer(@query.options[:count])
|
@@ -70,7 +70,7 @@ module Capybara
|
|
70
70
|
break if @result_cache.size > count_opt
|
71
71
|
@result_cache << @results_enum.next
|
72
72
|
end
|
73
|
-
return @result_cache.size
|
73
|
+
return @result_cache.size <=> count_opt
|
74
74
|
end
|
75
75
|
|
76
76
|
if @query.options[:minimum]
|
@@ -78,7 +78,7 @@ module Capybara
|
|
78
78
|
begin
|
79
79
|
@result_cache << @results_enum.next while @result_cache.size < min_opt
|
80
80
|
rescue StopIteration
|
81
|
-
return
|
81
|
+
return -1
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -86,32 +86,38 @@ module Capybara
|
|
86
86
|
max_opt = Integer(@query.options[:maximum])
|
87
87
|
begin
|
88
88
|
@result_cache << @results_enum.next while @result_cache.size <= max_opt
|
89
|
-
return
|
89
|
+
return 1
|
90
90
|
rescue StopIteration
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
94
|
if @query.options[:between]
|
95
|
-
max =
|
95
|
+
min, max = @query.options[:between].minmax
|
96
96
|
loop do
|
97
97
|
break if @result_cache.size > max
|
98
98
|
@result_cache << @results_enum.next
|
99
99
|
end
|
100
|
-
return
|
100
|
+
return 0 if @query.options[:between].include?(@result_cache.size)
|
101
|
+
return -1 if @result_cache.size < min
|
102
|
+
return 1
|
101
103
|
end
|
102
104
|
|
103
|
-
return
|
105
|
+
return 0
|
106
|
+
end
|
107
|
+
|
108
|
+
def matches_count?
|
109
|
+
compare_count.zero?
|
104
110
|
end
|
105
111
|
|
106
112
|
def failure_message
|
107
113
|
message = @query.failure_message
|
108
|
-
if count
|
109
|
-
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << full_results.map(&:text).map(&:inspect).join(", ")
|
110
|
-
else
|
114
|
+
if count.zero?
|
111
115
|
message << " but there were no matches"
|
116
|
+
else
|
117
|
+
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << full_results.map(&:text).map(&:inspect).join(", ")
|
112
118
|
end
|
113
119
|
unless rest.empty?
|
114
|
-
elements = rest.map
|
120
|
+
elements = rest.map { |el| el.text rescue "<<ERROR>>" }.map(&:inspect).join(", ")
|
115
121
|
message << ". Also found " << elements << ", which matched the selector but not all filters."
|
116
122
|
end
|
117
123
|
message
|
@@ -121,7 +127,7 @@ module Capybara
|
|
121
127
|
failure_message.sub(/(to find)/, 'not \1')
|
122
128
|
end
|
123
129
|
|
124
|
-
|
130
|
+
private
|
125
131
|
|
126
132
|
def full_results
|
127
133
|
loop { @result_cache << @results_enum.next }
|
@@ -137,15 +143,9 @@ module Capybara
|
|
137
143
|
# causes a concurrency issue with network requests here
|
138
144
|
# https://github.com/jruby/jruby/issues/4212
|
139
145
|
if RUBY_PLATFORM == 'java'
|
140
|
-
@elements.select(&block).to_enum
|
141
|
-
elsif @elements.respond_to? :lazy #Ruby 2.0+
|
142
|
-
@elements.lazy.select(&block)
|
146
|
+
@elements.select(&block).to_enum # non-lazy evaluation
|
143
147
|
else
|
144
|
-
|
145
|
-
@elements.each do |val|
|
146
|
-
yielder.yield(val) if block.call(val)
|
147
|
-
end
|
148
|
-
end
|
148
|
+
@elements.lazy.select(&block)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
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
|
-
|
@@ -4,7 +4,7 @@ module Capybara
|
|
4
4
|
include ::RSpec::Matchers::Composable
|
5
5
|
|
6
6
|
def and(matcher)
|
7
|
-
Capybara::RSpecMatchers::Compound::And.new(self,matcher)
|
7
|
+
Capybara::RSpecMatchers::Compound::And.new(self, matcher)
|
8
8
|
end
|
9
9
|
|
10
10
|
def and_then(matcher)
|
@@ -15,12 +15,9 @@ module Capybara
|
|
15
15
|
Capybara::RSpecMatchers::Compound::Or.new(self, matcher)
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
18
|
class CapybaraEvaluator
|
20
|
-
def initialize(actual
|
21
|
-
@actual
|
22
|
-
@matcher_1 = matcher_1
|
23
|
-
@matcher_2 = matcher_2
|
19
|
+
def initialize(actual)
|
20
|
+
@actual = actual
|
24
21
|
@match_results = Hash.new { |h, matcher| h[matcher] = matcher.matches?(@actual) }
|
25
22
|
end
|
26
23
|
|
@@ -34,11 +31,10 @@ module Capybara
|
|
34
31
|
end
|
35
32
|
|
36
33
|
class And < ::RSpec::Matchers::BuiltIn::Compound::And
|
37
|
-
|
38
34
|
private
|
39
35
|
|
40
36
|
def match(_expected, actual)
|
41
|
-
@evaluator = CapybaraEvaluator.new(actual
|
37
|
+
@evaluator = CapybaraEvaluator.new(actual)
|
42
38
|
syncer = sync_element(actual)
|
43
39
|
begin
|
44
40
|
syncer.synchronize do
|
@@ -63,11 +59,10 @@ module Capybara
|
|
63
59
|
end
|
64
60
|
|
65
61
|
class Or < ::RSpec::Matchers::BuiltIn::Compound::Or
|
66
|
-
|
67
62
|
private
|
68
63
|
|
69
64
|
def match(_expected, actual)
|
70
|
-
@evaluator = CapybaraEvaluator.new(actual
|
65
|
+
@evaluator = CapybaraEvaluator.new(actual)
|
71
66
|
syncer = sync_element(actual)
|
72
67
|
begin
|
73
68
|
syncer.synchronize do
|
@@ -1,56 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
if RSpec::Core::Version::STRING.to_f >= 3.0
|
3
|
-
RSpec.shared_context "Capybara Features", capybara_feature: true do
|
4
|
-
instance_eval do
|
5
|
-
alias background before
|
6
|
-
alias given let
|
7
|
-
alias given! let!
|
8
|
-
end
|
9
|
-
end
|
10
2
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
RSpec.shared_context "Capybara Features", capybara_feature: true do
|
4
|
+
instance_eval do
|
5
|
+
alias background before
|
6
|
+
alias given let
|
7
|
+
alias given! let!
|
16
8
|
end
|
9
|
+
end
|
17
10
|
|
11
|
+
# ensure shared_context is included if default shared_context_metadata_behavior is changed
|
12
|
+
if RSpec::Core::Version::STRING.to_f >= 3.5
|
18
13
|
RSpec.configure do |config|
|
19
|
-
config.
|
20
|
-
config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: "Temporarily disabled with xfeature"
|
21
|
-
config.alias_example_group_to :ffeature, capybara_feature: true, type: :feature, focus: true
|
22
|
-
config.alias_example_to :scenario
|
23
|
-
config.alias_example_to :xscenario, skip: "Temporarily disabled with xscenario"
|
24
|
-
config.alias_example_to :fscenario, focus: true
|
25
|
-
end
|
26
|
-
else
|
27
|
-
module Capybara
|
28
|
-
module Features
|
29
|
-
def self.included(base)
|
30
|
-
base.instance_eval do
|
31
|
-
alias :background :before
|
32
|
-
alias :scenario :it
|
33
|
-
alias :xscenario :xit
|
34
|
-
alias :given :let
|
35
|
-
alias :given! :let!
|
36
|
-
alias :feature :describe
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.feature(*args, &block)
|
43
|
-
options = if args.last.is_a?(Hash) then args.pop else {} end
|
44
|
-
options[:capybara_feature] = true
|
45
|
-
options[:type] = :feature
|
46
|
-
options[:caller] ||= caller
|
47
|
-
args.push(options)
|
48
|
-
|
49
|
-
#call describe on RSpec in case user has expose_dsl_globally set to false
|
50
|
-
RSpec.describe(*args, &block)
|
14
|
+
config.include_context "Capybara Features", capybara_feature: true
|
51
15
|
end
|
16
|
+
end
|
52
17
|
|
53
|
-
|
54
|
-
|
55
|
-
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.alias_example_group_to :feature, capybara_feature: true, type: :feature
|
20
|
+
config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: "Temporarily disabled with xfeature"
|
21
|
+
config.alias_example_group_to :ffeature, capybara_feature: true, type: :feature, focus: true
|
22
|
+
config.alias_example_to :scenario
|
23
|
+
config.alias_example_to :xscenario, skip: "Temporarily disabled with xscenario"
|
24
|
+
config.alias_example_to :fscenario, focus: true
|
56
25
|
end
|
@@ -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
|
22
|
-
|
23
|
-
remove_method :included
|
24
|
-
|
22
|
+
module DSLRSpecProxyInstaller
|
23
|
+
module ClassMethods
|
25
24
|
def included(base)
|
26
|
-
|
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
|
40
|
-
|
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)
|
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))
|
@@ -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?(
|
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?(
|
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,7 +150,7 @@ 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)
|
@@ -168,8 +160,6 @@ module Capybara
|
|
168
160
|
end
|
169
161
|
|
170
162
|
class HaveTitle < Matcher
|
171
|
-
attr_reader :title
|
172
|
-
|
173
163
|
def initialize(*args)
|
174
164
|
@args = args
|
175
165
|
|
@@ -186,17 +176,13 @@ module Capybara
|
|
186
176
|
end
|
187
177
|
|
188
178
|
def description
|
189
|
-
"have title #{title.inspect}"
|
179
|
+
"have title #{@title.inspect}"
|
190
180
|
end
|
191
181
|
end
|
192
182
|
|
193
183
|
class HaveCurrentPath < Matcher
|
194
|
-
attr_reader :current_path
|
195
|
-
|
196
184
|
def initialize(*args)
|
197
185
|
@args = args
|
198
|
-
|
199
|
-
# are set just for backwards compatability
|
200
186
|
@current_path = args.first
|
201
187
|
end
|
202
188
|
|
@@ -209,7 +195,33 @@ module Capybara
|
|
209
195
|
end
|
210
196
|
|
211
197
|
def description
|
212
|
-
"have current path #{current_path.inspect}"
|
198
|
+
"have current path #{@current_path.inspect}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class NegatedMatcher
|
203
|
+
def initialize(matcher)
|
204
|
+
@matcher = matcher
|
205
|
+
end
|
206
|
+
|
207
|
+
def matches?(actual)
|
208
|
+
@matcher.does_not_match?(actual)
|
209
|
+
end
|
210
|
+
|
211
|
+
def does_not_match?(actual)
|
212
|
+
@matcher.matches?(actual)
|
213
|
+
end
|
214
|
+
|
215
|
+
def description
|
216
|
+
"not #{@matcher.description}"
|
217
|
+
end
|
218
|
+
|
219
|
+
def failure_message
|
220
|
+
@matcher.failure_message_when_negated
|
221
|
+
end
|
222
|
+
|
223
|
+
def failure_message_when_negated
|
224
|
+
@matcher.failure_message
|
213
225
|
end
|
214
226
|
end
|
215
227
|
|
@@ -236,10 +248,6 @@ module Capybara
|
|
236
248
|
def failure_message_when_negated
|
237
249
|
"expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
|
238
250
|
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
251
|
end
|
244
252
|
|
245
253
|
# RSpec matcher for whether the element(s) matching a given selector exist
|
@@ -265,107 +273,109 @@ module Capybara
|
|
265
273
|
def match_selector(*args, &optional_filter_block)
|
266
274
|
MatchSelector.new(*args, &optional_filter_block)
|
267
275
|
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
276
|
|
273
277
|
# RSpec matcher for whether elements(s) matching a given xpath selector exist
|
274
278
|
# See {Capybara::Node::Matchers#has_xpath?}
|
275
|
-
def have_xpath(xpath, options
|
279
|
+
def have_xpath(xpath, **options, &optional_filter_block)
|
276
280
|
HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
|
277
281
|
end
|
278
282
|
|
279
283
|
# RSpec matcher for whether the current element matches a given xpath selector
|
280
|
-
def match_xpath(xpath, options
|
284
|
+
def match_xpath(xpath, **options, &optional_filter_block)
|
281
285
|
MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
|
282
286
|
end
|
283
287
|
|
284
288
|
# RSpec matcher for whether elements(s) matching a given css selector exist
|
285
289
|
# See {Capybara::Node::Matchers#has_css?}
|
286
|
-
def have_css(css, options
|
290
|
+
def have_css(css, **options, &optional_filter_block)
|
287
291
|
HaveSelector.new(:css, css, options, &optional_filter_block)
|
288
292
|
end
|
289
293
|
|
290
294
|
# RSpec matcher for whether the current element matches a given css selector
|
291
|
-
def match_css(css, options
|
295
|
+
def match_css(css, **options, &optional_filter_block)
|
292
296
|
MatchSelector.new(:css, css, options, &optional_filter_block)
|
293
297
|
end
|
294
298
|
|
295
|
-
# RSpec matcher for text
|
299
|
+
# RSpec matcher for text content
|
296
300
|
# See {Capybara::SessionMatchers#assert_text}
|
297
301
|
def have_text(*args)
|
298
302
|
HaveText.new(*args)
|
299
303
|
end
|
300
304
|
alias_method :have_content, :have_text
|
301
305
|
|
302
|
-
def have_title(title, options
|
306
|
+
def have_title(title, **options)
|
303
307
|
HaveTitle.new(title, options)
|
304
308
|
end
|
305
309
|
|
306
310
|
# RSpec matcher for the current path
|
307
311
|
# See {Capybara::SessionMatchers#assert_current_path}
|
308
|
-
def have_current_path(path, options
|
312
|
+
def have_current_path(path, **options)
|
309
313
|
HaveCurrentPath.new(path, options)
|
310
314
|
end
|
311
315
|
|
312
316
|
# RSpec matcher for links
|
313
317
|
# See {Capybara::Node::Matchers#has_link?}
|
314
|
-
def have_link(locator=nil, options
|
315
|
-
locator, options = nil, locator if locator.is_a? Hash
|
318
|
+
def have_link(locator = nil, **options, &optional_filter_block)
|
316
319
|
HaveSelector.new(:link, locator, options, &optional_filter_block)
|
317
320
|
end
|
318
321
|
|
319
322
|
# RSpec matcher for buttons
|
320
323
|
# See {Capybara::Node::Matchers#has_button?}
|
321
|
-
def have_button(locator=nil, options
|
322
|
-
locator, options = nil, locator if locator.is_a? Hash
|
324
|
+
def have_button(locator = nil, **options, &optional_filter_block)
|
323
325
|
HaveSelector.new(:button, locator, options, &optional_filter_block)
|
324
326
|
end
|
325
327
|
|
326
328
|
# RSpec matcher for links
|
327
329
|
# See {Capybara::Node::Matchers#has_field?}
|
328
|
-
def have_field(locator=nil, options
|
329
|
-
locator, options = nil, locator if locator.is_a? Hash
|
330
|
+
def have_field(locator = nil, **options, &optional_filter_block)
|
330
331
|
HaveSelector.new(:field, locator, options, &optional_filter_block)
|
331
332
|
end
|
332
333
|
|
333
334
|
# RSpec matcher for checked fields
|
334
335
|
# See {Capybara::Node::Matchers#has_checked_field?}
|
335
|
-
def have_checked_field(locator=nil, options
|
336
|
-
locator, options = nil, locator if locator.is_a? Hash
|
336
|
+
def have_checked_field(locator = nil, **options, &optional_filter_block)
|
337
337
|
HaveSelector.new(:field, locator, options.merge(checked: true), &optional_filter_block)
|
338
338
|
end
|
339
339
|
|
340
340
|
# RSpec matcher for unchecked fields
|
341
341
|
# See {Capybara::Node::Matchers#has_unchecked_field?}
|
342
|
-
def have_unchecked_field(locator=nil, options
|
343
|
-
locator, options = nil, locator if locator.is_a? Hash
|
342
|
+
def have_unchecked_field(locator = nil, **options, &optional_filter_block)
|
344
343
|
HaveSelector.new(:field, locator, options.merge(unchecked: true), &optional_filter_block)
|
345
344
|
end
|
346
345
|
|
347
346
|
# RSpec matcher for select elements
|
348
347
|
# See {Capybara::Node::Matchers#has_select?}
|
349
|
-
def have_select(locator=nil, options
|
350
|
-
locator, options = nil, locator if locator.is_a? Hash
|
348
|
+
def have_select(locator = nil, **options, &optional_filter_block)
|
351
349
|
HaveSelector.new(:select, locator, options, &optional_filter_block)
|
352
350
|
end
|
353
351
|
|
354
352
|
# RSpec matcher for table elements
|
355
353
|
# See {Capybara::Node::Matchers#has_table?}
|
356
|
-
def have_table(locator=nil, options
|
357
|
-
locator, options = nil, locator if locator.is_a? Hash
|
354
|
+
def have_table(locator = nil, **options, &optional_filter_block)
|
358
355
|
HaveSelector.new(:table, locator, options, &optional_filter_block)
|
359
356
|
end
|
360
357
|
|
358
|
+
%w[selector css xpath text title current_path link button field checked_field unchecked_field select table].each do |matcher_type|
|
359
|
+
define_method "have_no_#{matcher_type}" do |*args, &optional_filter_block|
|
360
|
+
NegatedMatcher.new(send("have_#{matcher_type}", *args, &optional_filter_block))
|
361
|
+
end
|
362
|
+
end
|
363
|
+
alias_method :have_no_content, :have_no_text
|
364
|
+
|
365
|
+
%w[selector css xpath].each do |matcher_type|
|
366
|
+
define_method "not_match_#{matcher_type}" do |*args, &optional_filter_block|
|
367
|
+
NegatedMatcher.new(send("match_#{matcher_type}", *args, &optional_filter_block))
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
361
371
|
##
|
362
372
|
# Wait for window to become closed.
|
363
373
|
# @example
|
364
374
|
# expect(window).to become_closed(wait: 0.8)
|
365
375
|
# @param options [Hash] optional param
|
366
376
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum wait time
|
367
|
-
def become_closed(options
|
377
|
+
def become_closed(**options)
|
368
378
|
BecomeClosed.new(options)
|
369
379
|
end
|
370
380
|
end
|
371
|
-
end
|
381
|
+
end
|