capybara 2.5.0 → 2.18.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/.yard/templates_custom/default/class/html/selectors.erb +38 -0
- data/.yard/templates_custom/default/class/html/setup.rb +17 -0
- data/.yard/yard_extensions.rb +78 -0
- data/.yardopts +1 -0
- data/History.md +413 -10
- data/License.txt +1 -1
- data/README.md +237 -130
- data/lib/capybara/config.rb +132 -0
- data/lib/capybara/cucumber.rb +3 -1
- data/lib/capybara/driver/base.rb +27 -6
- data/lib/capybara/driver/node.rb +14 -5
- data/lib/capybara/dsl.rb +2 -3
- data/lib/capybara/helpers.rb +13 -65
- data/lib/capybara/minitest/spec.rb +177 -0
- data/lib/capybara/minitest.rb +278 -0
- data/lib/capybara/node/actions.rb +180 -24
- data/lib/capybara/node/base.rb +17 -5
- data/lib/capybara/node/document.rb +5 -0
- data/lib/capybara/node/document_matchers.rb +15 -14
- data/lib/capybara/node/element.rb +55 -7
- data/lib/capybara/node/finders.rb +179 -67
- data/lib/capybara/node/matchers.rb +301 -105
- data/lib/capybara/node/simple.rb +15 -4
- data/lib/capybara/queries/ancestor_query.rb +25 -0
- data/lib/capybara/queries/base_query.rb +69 -3
- data/lib/capybara/queries/current_path_query.rb +17 -8
- data/lib/capybara/queries/match_query.rb +19 -0
- data/lib/capybara/queries/selector_query.rb +251 -0
- data/lib/capybara/queries/sibling_query.rb +25 -0
- data/lib/capybara/queries/text_query.rb +67 -16
- data/lib/capybara/queries/title_query.rb +4 -2
- data/lib/capybara/query.rb +3 -131
- data/lib/capybara/rack_test/browser.rb +14 -5
- data/lib/capybara/rack_test/css_handlers.rb +1 -0
- data/lib/capybara/rack_test/driver.rb +15 -8
- data/lib/capybara/rack_test/form.rb +34 -12
- data/lib/capybara/rack_test/node.rb +29 -12
- data/lib/capybara/rails.rb +3 -3
- data/lib/capybara/result.rb +104 -9
- data/lib/capybara/rspec/compound.rb +95 -0
- data/lib/capybara/rspec/features.rb +17 -6
- data/lib/capybara/rspec/matcher_proxies.rb +45 -0
- data/lib/capybara/rspec/matchers.rb +199 -80
- data/lib/capybara/rspec.rb +4 -2
- data/lib/capybara/selector/css.rb +30 -0
- data/lib/capybara/selector/filter.rb +20 -0
- data/lib/capybara/selector/filter_set.rb +74 -0
- data/lib/capybara/selector/filters/base.rb +33 -0
- data/lib/capybara/selector/filters/expression_filter.rb +40 -0
- data/lib/capybara/selector/filters/node_filter.rb +27 -0
- data/lib/capybara/selector/selector.rb +276 -0
- data/lib/capybara/selector.rb +452 -157
- data/lib/capybara/selenium/driver.rb +282 -81
- data/lib/capybara/selenium/node.rb +144 -46
- data/lib/capybara/server.rb +59 -16
- data/lib/capybara/session/config.rb +114 -0
- data/lib/capybara/session/matchers.rb +29 -19
- data/lib/capybara/session.rb +378 -143
- data/lib/capybara/spec/fixtures/no_extension +1 -0
- data/lib/capybara/spec/public/jquery-ui.js +13 -791
- data/lib/capybara/spec/public/jquery.js +4 -9045
- data/lib/capybara/spec/public/test.js +45 -11
- data/lib/capybara/spec/session/accept_alert_spec.rb +30 -7
- data/lib/capybara/spec/session/accept_confirm_spec.rb +14 -2
- data/lib/capybara/spec/session/accept_prompt_spec.rb +35 -6
- data/lib/capybara/spec/session/all_spec.rb +45 -32
- data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +110 -0
- data/lib/capybara/spec/session/assert_current_path.rb +15 -2
- data/lib/capybara/spec/session/assert_selector.rb +29 -28
- data/lib/capybara/spec/session/assert_text.rb +59 -20
- data/lib/capybara/spec/session/assert_title.rb +25 -11
- data/lib/capybara/spec/session/attach_file_spec.rb +42 -4
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +90 -14
- data/lib/capybara/spec/session/choose_spec.rb +31 -5
- data/lib/capybara/spec/session/click_button_spec.rb +20 -9
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +15 -9
- data/lib/capybara/spec/session/click_link_spec.rb +39 -15
- data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
- data/lib/capybara/spec/session/current_url_spec.rb +12 -3
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +6 -5
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +4 -3
- data/lib/capybara/spec/session/element/assert_match_selector.rb +36 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +23 -0
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +106 -0
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +23 -1
- data/lib/capybara/spec/session/execute_script_spec.rb +22 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +50 -32
- data/lib/capybara/spec/session/find_button_spec.rb +43 -2
- data/lib/capybara/spec/session/find_by_id_spec.rb +3 -2
- data/lib/capybara/spec/session/find_field_spec.rb +42 -6
- data/lib/capybara/spec/session/find_link_spec.rb +22 -3
- data/lib/capybara/spec/session/find_spec.rb +103 -57
- data/lib/capybara/spec/session/first_spec.rb +34 -18
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +103 -0
- data/lib/capybara/spec/session/{within_frame_spec.rb → frame/within_frame_spec.rb} +44 -2
- data/lib/capybara/spec/session/go_back_spec.rb +2 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_button_spec.rb +17 -8
- data/lib/capybara/spec/session/has_css_spec.rb +85 -73
- data/lib/capybara/spec/session/has_current_path_spec.rb +91 -7
- data/lib/capybara/spec/session/has_field_spec.rb +93 -58
- data/lib/capybara/spec/session/has_link_spec.rb +9 -8
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
- data/lib/capybara/spec/session/has_select_spec.rb +159 -59
- data/lib/capybara/spec/session/has_selector_spec.rb +64 -28
- data/lib/capybara/spec/session/has_table_spec.rb +1 -0
- data/lib/capybara/spec/session/has_text_spec.rb +27 -12
- data/lib/capybara/spec/session/has_title_spec.rb +22 -4
- data/lib/capybara/spec/session/has_xpath_spec.rb +32 -29
- data/lib/capybara/spec/session/headers.rb +2 -1
- data/lib/capybara/spec/session/html_spec.rb +4 -3
- data/lib/capybara/spec/session/node_spec.rb +198 -38
- data/lib/capybara/spec/session/refresh_spec.rb +28 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +46 -5
- data/lib/capybara/spec/session/response_code.rb +2 -1
- 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 -5
- data/lib/capybara/spec/session/save_page_spec.rb +34 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
- data/lib/capybara/spec/session/screenshot_spec.rb +4 -2
- data/lib/capybara/spec/session/select_spec.rb +34 -32
- data/lib/capybara/spec/session/selectors_spec.rb +65 -0
- data/lib/capybara/spec/session/sibling_spec.rb +52 -0
- data/lib/capybara/spec/session/text_spec.rb +4 -4
- data/lib/capybara/spec/session/title_spec.rb +2 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +42 -2
- data/lib/capybara/spec/session/unselect_spec.rb +17 -16
- data/lib/capybara/spec/session/visit_spec.rb +77 -2
- data/lib/capybara/spec/session/window/become_closed_spec.rb +12 -11
- 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 +16 -11
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +7 -4
- data/lib/capybara/spec/session/window/window_spec.rb +36 -29
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +31 -7
- data/lib/capybara/spec/session/within_spec.rb +14 -6
- data/lib/capybara/spec/spec_helper.rb +37 -4
- data/lib/capybara/spec/test_app.rb +15 -3
- data/lib/capybara/spec/views/buttons.erb +1 -0
- data/lib/capybara/spec/views/fieldsets.erb +2 -1
- data/lib/capybara/spec/views/form.erb +169 -9
- data/lib/capybara/spec/views/frame_child.erb +10 -2
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +3 -2
- data/lib/capybara/spec/views/frame_two.erb +2 -1
- data/lib/capybara/spec/views/header_links.erb +1 -0
- data/lib/capybara/spec/views/host_links.erb +1 -0
- data/lib/capybara/spec/views/initial_alert.erb +10 -0
- data/lib/capybara/spec/views/path.erb +1 -0
- data/lib/capybara/spec/views/popup_one.erb +1 -0
- data/lib/capybara/spec/views/popup_two.erb +1 -0
- data/lib/capybara/spec/views/postback.erb +2 -1
- data/lib/capybara/spec/views/tables.erb +1 -0
- data/lib/capybara/spec/views/with_base_tag.erb +1 -0
- data/lib/capybara/spec/views/with_count.erb +2 -1
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
- data/lib/capybara/spec/views/with_hover.erb +7 -1
- data/lib/capybara/spec/views/with_html.erb +40 -2
- data/lib/capybara/spec/views/with_html_entities.erb +1 -0
- data/lib/capybara/spec/views/with_js.erb +32 -1
- data/lib/capybara/spec/views/with_scope.erb +1 -0
- data/lib/capybara/spec/views/with_simple_html.erb +2 -1
- data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
- data/lib/capybara/spec/views/with_title.erb +2 -1
- data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
- data/lib/capybara/spec/views/with_windows.erb +7 -0
- data/lib/capybara/spec/views/within_frames.erb +3 -2
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +20 -3
- data/lib/capybara.rb +189 -93
- data/spec/basic_node_spec.rb +7 -6
- data/spec/capybara_spec.rb +90 -4
- data/spec/dsl_spec.rb +3 -1
- data/spec/filter_set_spec.rb +28 -0
- data/spec/fixtures/capybara.csv +1 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +5 -1
- data/spec/minitest_spec.rb +130 -0
- data/spec/minitest_spec_spec.rb +135 -0
- data/spec/per_session_config_spec.rb +67 -0
- data/spec/rack_test_spec.rb +50 -7
- data/spec/result_spec.rb +76 -0
- data/spec/rspec/features_spec.rb +21 -8
- data/spec/rspec/scenarios_spec.rb +21 -0
- data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +160 -54
- data/spec/rspec/views_spec.rb +5 -0
- data/spec/rspec_matchers_spec.rb +46 -0
- data/spec/rspec_spec.rb +79 -1
- data/spec/selector_spec.rb +199 -0
- data/spec/selenium_spec_chrome.rb +54 -9
- data/spec/selenium_spec_firefox.rb +68 -0
- data/spec/selenium_spec_marionette.rb +127 -0
- data/spec/server_spec.rb +102 -14
- data/spec/session_spec.rb +54 -0
- data/spec/shared_selenium_session.rb +215 -0
- data/spec/spec_helper.rb +7 -0
- metadata +140 -15
- data/spec/selenium_spec.rb +0 -128
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module Capybara
|
|
2
|
+
module RSpecMatchers
|
|
3
|
+
module Compound
|
|
4
|
+
include ::RSpec::Matchers::Composable
|
|
5
|
+
|
|
6
|
+
def and(matcher)
|
|
7
|
+
Capybara::RSpecMatchers::Compound::And.new(self,matcher)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def and_then(matcher)
|
|
11
|
+
::RSpec::Matchers::BuiltIn::Compound::And.new(self, matcher)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def or(matcher)
|
|
15
|
+
Capybara::RSpecMatchers::Compound::Or.new(self, matcher)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CapybaraEvaluator
|
|
20
|
+
def initialize(actual, matcher_1, matcher_2)
|
|
21
|
+
@actual = actual
|
|
22
|
+
@matcher_1 = matcher_1
|
|
23
|
+
@matcher_2 = matcher_2
|
|
24
|
+
@match_results = Hash.new { |h, matcher| h[matcher] = matcher.matches?(@actual) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def matcher_matches?(matcher)
|
|
28
|
+
@match_results[matcher]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reset
|
|
32
|
+
@match_results.clear
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class And < ::RSpec::Matchers::BuiltIn::Compound::And
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def match(_expected, actual)
|
|
41
|
+
@evaluator = CapybaraEvaluator.new(actual, matcher_1, matcher_2)
|
|
42
|
+
syncer = sync_element(actual)
|
|
43
|
+
begin
|
|
44
|
+
syncer.synchronize do
|
|
45
|
+
@evaluator.reset
|
|
46
|
+
raise ::Capybara::ElementNotFound unless [matcher_1_matches?, matcher_2_matches?].all?
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
rescue
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sync_element(el)
|
|
55
|
+
if el.respond_to? :synchronize
|
|
56
|
+
el
|
|
57
|
+
elsif el.respond_to? :current_scope
|
|
58
|
+
el.current_scope
|
|
59
|
+
else
|
|
60
|
+
Capybara.string(el)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class Or < ::RSpec::Matchers::BuiltIn::Compound::Or
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def match(_expected, actual)
|
|
70
|
+
@evaluator = CapybaraEvaluator.new(actual, matcher_1, matcher_2)
|
|
71
|
+
syncer = sync_element(actual)
|
|
72
|
+
begin
|
|
73
|
+
syncer.synchronize do
|
|
74
|
+
@evaluator.reset
|
|
75
|
+
raise ::Capybara::ElementNotFound unless [matcher_1_matches?, matcher_2_matches?].any?
|
|
76
|
+
true
|
|
77
|
+
end
|
|
78
|
+
rescue
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def sync_element(el)
|
|
84
|
+
if el.respond_to? :synchronize
|
|
85
|
+
el
|
|
86
|
+
elsif el.respond_to? :current_scope
|
|
87
|
+
el.current_scope
|
|
88
|
+
else
|
|
89
|
+
Capybara.string(el)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
if RSpec::Core::Version::STRING.to_f >= 3.0
|
|
2
|
-
RSpec.shared_context "Capybara Features", :
|
|
3
|
+
RSpec.shared_context "Capybara Features", capybara_feature: true do
|
|
3
4
|
instance_eval do
|
|
4
5
|
alias background before
|
|
5
6
|
alias given let
|
|
@@ -7,11 +8,20 @@ if RSpec::Core::Version::STRING.to_f >= 3.0
|
|
|
7
8
|
end
|
|
8
9
|
end
|
|
9
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
|
|
13
|
+
RSpec.configure do |config|
|
|
14
|
+
config.include_context "Capybara Features", capybara_feature: true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
10
18
|
RSpec.configure do |config|
|
|
11
|
-
config.alias_example_group_to :feature, :
|
|
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
|
|
12
22
|
config.alias_example_to :scenario
|
|
13
|
-
config.alias_example_to :xscenario, :
|
|
14
|
-
config.alias_example_to :fscenario, :
|
|
23
|
+
config.alias_example_to :xscenario, skip: "Temporarily disabled with xscenario"
|
|
24
|
+
config.alias_example_to :fscenario, focus: true
|
|
15
25
|
end
|
|
16
26
|
else
|
|
17
27
|
module Capybara
|
|
@@ -29,7 +39,6 @@ else
|
|
|
29
39
|
end
|
|
30
40
|
end
|
|
31
41
|
|
|
32
|
-
|
|
33
42
|
def self.feature(*args, &block)
|
|
34
43
|
options = if args.last.is_a?(Hash) then args.pop else {} end
|
|
35
44
|
options[:capybara_feature] = true
|
|
@@ -41,5 +50,7 @@ else
|
|
|
41
50
|
RSpec.describe(*args, &block)
|
|
42
51
|
end
|
|
43
52
|
|
|
44
|
-
RSpec.
|
|
53
|
+
RSpec.configure do |config|
|
|
54
|
+
config.include(Capybara::Features, capybara_feature: true)
|
|
55
|
+
end
|
|
45
56
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Capybara
|
|
3
|
+
module RSpecMatcherProxies
|
|
4
|
+
def all(*args)
|
|
5
|
+
if defined?(::RSpec::Matchers::BuiltIn::All) && args.first.respond_to?(:matches?)
|
|
6
|
+
::RSpec::Matchers::BuiltIn::All.new(*args)
|
|
7
|
+
else
|
|
8
|
+
find_all(*args)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def within(*args)
|
|
13
|
+
if block_given?
|
|
14
|
+
within_element(*args, &Proc.new)
|
|
15
|
+
else
|
|
16
|
+
be_within(*args)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module DSL
|
|
22
|
+
class <<self
|
|
23
|
+
remove_method :included
|
|
24
|
+
|
|
25
|
+
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)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
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
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -1,56 +1,145 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module RSpecMatchers
|
|
3
4
|
class Matcher
|
|
4
|
-
|
|
5
|
+
if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.0'))
|
|
6
|
+
require 'capybara/rspec/compound'
|
|
7
|
+
include ::Capybara::RSpecMatchers::Compound
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :failure_message, :failure_message_when_negated
|
|
5
11
|
|
|
6
12
|
def wrap(actual)
|
|
7
|
-
if actual.respond_to?("has_selector?")
|
|
13
|
+
@context_el = if actual.respond_to?("has_selector?")
|
|
8
14
|
actual
|
|
9
15
|
else
|
|
10
16
|
Capybara.string(actual.to_s)
|
|
11
17
|
end
|
|
12
18
|
end
|
|
13
|
-
end
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
@args = args
|
|
20
|
-
end
|
|
24
|
+
private
|
|
21
25
|
|
|
22
|
-
def
|
|
23
|
-
wrap(actual)
|
|
26
|
+
def wrap_matches?(actual)
|
|
27
|
+
yield(wrap(actual))
|
|
24
28
|
rescue Capybara::ExpectationNotMet => e
|
|
25
29
|
@failure_message = e.message
|
|
26
30
|
return false
|
|
27
31
|
end
|
|
28
32
|
|
|
29
|
-
def
|
|
30
|
-
wrap(actual)
|
|
33
|
+
def wrap_does_not_match?(actual)
|
|
34
|
+
yield(wrap(actual))
|
|
31
35
|
rescue Capybara::ExpectationNotMet => e
|
|
32
36
|
@failure_message_when_negated = e.message
|
|
33
37
|
return false
|
|
34
38
|
end
|
|
35
39
|
|
|
40
|
+
def session_query_args
|
|
41
|
+
if @args.last.is_a? Hash
|
|
42
|
+
@args.last[:session_options] = session_options
|
|
43
|
+
else
|
|
44
|
+
@args.push(session_options: session_options)
|
|
45
|
+
end
|
|
46
|
+
@args
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def session_options
|
|
50
|
+
@context_el ||= nil
|
|
51
|
+
if @context_el.respond_to? :session_options
|
|
52
|
+
@context_el.session_options
|
|
53
|
+
elsif @context_el.respond_to? :current_scope
|
|
54
|
+
@context_el.current_scope.session_options
|
|
55
|
+
else
|
|
56
|
+
Capybara.session_options
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class HaveSelector < Matcher
|
|
62
|
+
def initialize(*args, &filter_block)
|
|
63
|
+
@args = args
|
|
64
|
+
@filter_block = filter_block
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def matches?(actual)
|
|
68
|
+
wrap_matches?(actual){ |el| el.assert_selector(*@args, &@filter_block) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def does_not_match?(actual)
|
|
72
|
+
wrap_does_not_match?(actual){ |el| el.assert_no_selector(*@args, &@filter_block) }
|
|
73
|
+
end
|
|
74
|
+
|
|
36
75
|
def description
|
|
37
76
|
"have #{query.description}"
|
|
38
77
|
end
|
|
39
78
|
|
|
40
79
|
def query
|
|
41
|
-
@query ||= Capybara::
|
|
80
|
+
@query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
|
|
42
81
|
end
|
|
82
|
+
end
|
|
43
83
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
84
|
+
class HaveAllSelectors < Matcher
|
|
85
|
+
def initialize(*args, &filter_block)
|
|
86
|
+
@args = args
|
|
87
|
+
@filter_block = filter_block
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def matches?(actual)
|
|
91
|
+
wrap_matches?(actual){ |el| el.assert_all_of_selectors(*@args, &@filter_block) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def does_not_match?(actual)
|
|
95
|
+
raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def description
|
|
99
|
+
"have all selectors"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class HaveNoSelectors < Matcher
|
|
104
|
+
def initialize(*args, &filter_block)
|
|
105
|
+
@args = args
|
|
106
|
+
@filter_block = filter_block
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def matches?(actual)
|
|
110
|
+
wrap_matches?(actual){ |el| el.assert_none_of_selectors(*@args, &@filter_block) }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def does_not_match?(actual)
|
|
114
|
+
raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def description
|
|
118
|
+
"have no selectors"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
class MatchSelector < HaveSelector
|
|
123
|
+
def matches?(actual)
|
|
124
|
+
wrap_matches?(actual) { |el| el.assert_matches_selector(*@args, &@filter_block) }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def does_not_match?(actual)
|
|
128
|
+
wrap_does_not_match?(actual) { |el| el.assert_not_matches_selector(*@args, &@filter_block) }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def description
|
|
132
|
+
"match #{query.description}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def query
|
|
136
|
+
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
|
|
137
|
+
end
|
|
47
138
|
end
|
|
48
139
|
|
|
49
140
|
class HaveText < Matcher
|
|
50
141
|
attr_reader :type, :content, :options
|
|
51
142
|
|
|
52
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
53
|
-
|
|
54
143
|
def initialize(*args)
|
|
55
144
|
@args = args.dup
|
|
56
145
|
|
|
@@ -61,17 +150,11 @@ module Capybara
|
|
|
61
150
|
end
|
|
62
151
|
|
|
63
152
|
def matches?(actual)
|
|
64
|
-
|
|
65
|
-
rescue Capybara::ExpectationNotMet => e
|
|
66
|
-
@failure_message = e.message
|
|
67
|
-
return false
|
|
153
|
+
wrap_matches?(actual) { |el| el.assert_text(*@args) }
|
|
68
154
|
end
|
|
69
155
|
|
|
70
156
|
def does_not_match?(actual)
|
|
71
|
-
|
|
72
|
-
rescue Capybara::ExpectationNotMet => e
|
|
73
|
-
@failure_message_when_negated = e.message
|
|
74
|
-
return false
|
|
157
|
+
wrap_does_not_match?(actual) { |el| el.assert_no_text(*@args) }
|
|
75
158
|
end
|
|
76
159
|
|
|
77
160
|
def description
|
|
@@ -82,17 +165,11 @@ module Capybara
|
|
|
82
165
|
content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
|
|
83
166
|
content.inspect
|
|
84
167
|
end
|
|
85
|
-
|
|
86
|
-
# RSpec 2 compatibility:
|
|
87
|
-
alias_method :failure_message_for_should, :failure_message
|
|
88
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
89
168
|
end
|
|
90
169
|
|
|
91
170
|
class HaveTitle < Matcher
|
|
92
171
|
attr_reader :title
|
|
93
172
|
|
|
94
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
95
|
-
|
|
96
173
|
def initialize(*args)
|
|
97
174
|
@args = args
|
|
98
175
|
|
|
@@ -101,33 +178,21 @@ module Capybara
|
|
|
101
178
|
end
|
|
102
179
|
|
|
103
180
|
def matches?(actual)
|
|
104
|
-
|
|
105
|
-
rescue Capybara::ExpectationNotMet => e
|
|
106
|
-
@failure_message = e.message
|
|
107
|
-
return false
|
|
181
|
+
wrap_matches?(actual) { |el| el.assert_title(*@args) }
|
|
108
182
|
end
|
|
109
183
|
|
|
110
184
|
def does_not_match?(actual)
|
|
111
|
-
|
|
112
|
-
rescue Capybara::ExpectationNotMet => e
|
|
113
|
-
@failure_message_when_negated = e.message
|
|
114
|
-
return false
|
|
185
|
+
wrap_does_not_match?(actual) { |el| el.assert_no_title(*@args) }
|
|
115
186
|
end
|
|
116
187
|
|
|
117
188
|
def description
|
|
118
189
|
"have title #{title.inspect}"
|
|
119
190
|
end
|
|
120
|
-
|
|
121
|
-
# RSpec 2 compatibility:
|
|
122
|
-
alias_method :failure_message_for_should, :failure_message
|
|
123
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
124
191
|
end
|
|
125
192
|
|
|
126
193
|
class HaveCurrentPath < Matcher
|
|
127
194
|
attr_reader :current_path
|
|
128
195
|
|
|
129
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
130
|
-
|
|
131
196
|
def initialize(*args)
|
|
132
197
|
@args = args
|
|
133
198
|
|
|
@@ -136,35 +201,26 @@ module Capybara
|
|
|
136
201
|
end
|
|
137
202
|
|
|
138
203
|
def matches?(actual)
|
|
139
|
-
|
|
140
|
-
rescue Capybara::ExpectationNotMet => e
|
|
141
|
-
@failure_message = e.message
|
|
142
|
-
return false
|
|
204
|
+
wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
|
|
143
205
|
end
|
|
144
206
|
|
|
145
207
|
def does_not_match?(actual)
|
|
146
|
-
|
|
147
|
-
rescue Capybara::ExpectationNotMet => e
|
|
148
|
-
@failure_message_when_negated = e.message
|
|
149
|
-
return false
|
|
208
|
+
wrap_does_not_match?(actual) { |el| el.assert_no_current_path(*@args) }
|
|
150
209
|
end
|
|
151
210
|
|
|
152
211
|
def description
|
|
153
212
|
"have current path #{current_path.inspect}"
|
|
154
213
|
end
|
|
155
|
-
|
|
156
|
-
# RSpec 2 compatibility:
|
|
157
|
-
alias_method :failure_message_for_should, :failure_message
|
|
158
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
159
214
|
end
|
|
160
215
|
|
|
161
216
|
class BecomeClosed
|
|
162
217
|
def initialize(options)
|
|
163
|
-
@
|
|
218
|
+
@options = options
|
|
164
219
|
end
|
|
165
220
|
|
|
166
221
|
def matches?(window)
|
|
167
222
|
@window = window
|
|
223
|
+
@wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)
|
|
168
224
|
start_time = Capybara::Helpers.monotonic_time
|
|
169
225
|
while window.exists?
|
|
170
226
|
return false if (Capybara::Helpers.monotonic_time - start_time) > @wait_time
|
|
@@ -186,18 +242,58 @@ module Capybara
|
|
|
186
242
|
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
187
243
|
end
|
|
188
244
|
|
|
189
|
-
|
|
190
|
-
|
|
245
|
+
# RSpec matcher for whether the element(s) matching a given selector exist
|
|
246
|
+
# See {Capybara::Node::Matcher#assert_selector}
|
|
247
|
+
def have_selector(*args, &optional_filter_block)
|
|
248
|
+
HaveSelector.new(*args, &optional_filter_block)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# RSpec matcher for whether the element(s) matching a group of selectors exist
|
|
252
|
+
# See {Capybara::Node::Matcher#assert_all_of_selectors}
|
|
253
|
+
def have_all_of_selectors(*args, &optional_filter_block)
|
|
254
|
+
HaveAllSelectors.new(*args, &optional_filter_block)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# RSpec matcher for whether no element(s) matching a group of selectors exist
|
|
258
|
+
# See {Capybara::Node::Matcher#assert_none_of_selectors}
|
|
259
|
+
def have_none_of_selectors(*args, &optional_filter_block)
|
|
260
|
+
HaveNoSelectors.new(*args, &optional_filter_block)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# RSpec matcher for whether the current element matches a given selector
|
|
264
|
+
# See {Capybara::Node::Matchers#assert_matches_selector}
|
|
265
|
+
def match_selector(*args, &optional_filter_block)
|
|
266
|
+
MatchSelector.new(*args, &optional_filter_block)
|
|
267
|
+
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
|
+
|
|
273
|
+
# RSpec matcher for whether elements(s) matching a given xpath selector exist
|
|
274
|
+
# See {Capybara::Node::Matchers#has_xpath?}
|
|
275
|
+
def have_xpath(xpath, options={}, &optional_filter_block)
|
|
276
|
+
HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# RSpec matcher for whether the current element matches a given xpath selector
|
|
280
|
+
def match_xpath(xpath, options={}, &optional_filter_block)
|
|
281
|
+
MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
191
282
|
end
|
|
192
283
|
|
|
193
|
-
|
|
194
|
-
|
|
284
|
+
# RSpec matcher for whether elements(s) matching a given css selector exist
|
|
285
|
+
# See {Capybara::Node::Matchers#has_css?}
|
|
286
|
+
def have_css(css, options={}, &optional_filter_block)
|
|
287
|
+
HaveSelector.new(:css, css, options, &optional_filter_block)
|
|
195
288
|
end
|
|
196
289
|
|
|
197
|
-
|
|
198
|
-
|
|
290
|
+
# RSpec matcher for whether the current element matches a given css selector
|
|
291
|
+
def match_css(css, options={}, &optional_filter_block)
|
|
292
|
+
MatchSelector.new(:css, css, options, &optional_filter_block)
|
|
199
293
|
end
|
|
200
294
|
|
|
295
|
+
# RSpec matcher for text on the page
|
|
296
|
+
# See {Capybara::SessionMatchers#assert_text}
|
|
201
297
|
def have_text(*args)
|
|
202
298
|
HaveText.new(*args)
|
|
203
299
|
end
|
|
@@ -207,36 +303,59 @@ module Capybara
|
|
|
207
303
|
HaveTitle.new(title, options)
|
|
208
304
|
end
|
|
209
305
|
|
|
306
|
+
# RSpec matcher for the current path
|
|
307
|
+
# See {Capybara::SessionMatchers#assert_current_path}
|
|
210
308
|
def have_current_path(path, options = {})
|
|
211
309
|
HaveCurrentPath.new(path, options)
|
|
212
310
|
end
|
|
213
311
|
|
|
214
|
-
|
|
215
|
-
|
|
312
|
+
# RSpec matcher for links
|
|
313
|
+
# 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
|
|
316
|
+
HaveSelector.new(:link, locator, options, &optional_filter_block)
|
|
216
317
|
end
|
|
217
318
|
|
|
218
|
-
|
|
219
|
-
|
|
319
|
+
# RSpec matcher for buttons
|
|
320
|
+
# 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
|
+
HaveSelector.new(:button, locator, options, &optional_filter_block)
|
|
220
324
|
end
|
|
221
325
|
|
|
222
|
-
|
|
223
|
-
|
|
326
|
+
# RSpec matcher for links
|
|
327
|
+
# 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
|
|
330
|
+
HaveSelector.new(:field, locator, options, &optional_filter_block)
|
|
224
331
|
end
|
|
225
332
|
|
|
226
|
-
|
|
227
|
-
|
|
333
|
+
# RSpec matcher for checked fields
|
|
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
|
|
337
|
+
HaveSelector.new(:field, locator, options.merge(checked: true), &optional_filter_block)
|
|
228
338
|
end
|
|
229
339
|
|
|
230
|
-
|
|
231
|
-
|
|
340
|
+
# RSpec matcher for unchecked fields
|
|
341
|
+
# 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
|
|
344
|
+
HaveSelector.new(:field, locator, options.merge(unchecked: true), &optional_filter_block)
|
|
232
345
|
end
|
|
233
346
|
|
|
234
|
-
|
|
235
|
-
|
|
347
|
+
# RSpec matcher for select elements
|
|
348
|
+
# 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
|
|
351
|
+
HaveSelector.new(:select, locator, options, &optional_filter_block)
|
|
236
352
|
end
|
|
237
353
|
|
|
238
|
-
|
|
239
|
-
|
|
354
|
+
# RSpec matcher for table elements
|
|
355
|
+
# 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
|
|
358
|
+
HaveSelector.new(:table, locator, options, &optional_filter_block)
|
|
240
359
|
end
|
|
241
360
|
|
|
242
361
|
##
|
|
@@ -249,4 +368,4 @@ module Capybara
|
|
|
249
368
|
BecomeClosed.new(options)
|
|
250
369
|
end
|
|
251
370
|
end
|
|
252
|
-
end
|
|
371
|
+
end
|
data/lib/capybara/rspec.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
require 'capybara/dsl'
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
require 'rspec/core'
|
|
3
|
+
require 'capybara/dsl'
|
|
4
4
|
require 'capybara/rspec/matchers'
|
|
5
5
|
require 'capybara/rspec/features'
|
|
6
|
+
require 'capybara/rspec/matcher_proxies'
|
|
6
7
|
|
|
7
8
|
RSpec.configure do |config|
|
|
8
9
|
config.include Capybara::DSL, :type => :feature
|
|
@@ -22,6 +23,7 @@ RSpec.configure do |config|
|
|
|
22
23
|
Capybara.use_default_driver
|
|
23
24
|
end
|
|
24
25
|
end
|
|
26
|
+
|
|
25
27
|
config.before do
|
|
26
28
|
if self.class.include?(Capybara::DSL)
|
|
27
29
|
example = fetch_current_example.call(self)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Capybara
|
|
2
|
+
class Selector
|
|
3
|
+
class CSS
|
|
4
|
+
def self.escape(str)
|
|
5
|
+
out = String.new("")
|
|
6
|
+
value = str.dup
|
|
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}
|
|
14
|
+
out
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.escape_char(c)
|
|
18
|
+
return "\\%06x" % c.ord() unless c =~ %r{[ -/:-~]}
|
|
19
|
+
"\\#{c}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
S = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
|
|
23
|
+
H = /[0-9a-fA-F]/
|
|
24
|
+
UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
|
|
25
|
+
NONASCII = /[#{S}]/
|
|
26
|
+
ESCAPE = /#{UNICODE}|\\[ -~#{S}]/
|
|
27
|
+
NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'capybara/selector/filters/node_filter'
|
|
3
|
+
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
|