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,278 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'minitest'
|
|
3
|
+
require 'capybara/dsl'
|
|
4
|
+
|
|
5
|
+
module Capybara
|
|
6
|
+
module Minitest
|
|
7
|
+
module Assertions
|
|
8
|
+
## Assert text exists
|
|
9
|
+
#
|
|
10
|
+
# @!method assert_text
|
|
11
|
+
# see {Capybara::Node::Matchers#assert_text}
|
|
12
|
+
|
|
13
|
+
## Assert text does not exist
|
|
14
|
+
#
|
|
15
|
+
# @!method assert_no_text
|
|
16
|
+
# see {Capybara::Node::Matchers#assert_no_text}
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Assertion that page title does match
|
|
20
|
+
#
|
|
21
|
+
# @!method assert_title
|
|
22
|
+
# see {Capybara::Node::DocumentMatchers#assert_title}
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# Assertion that page title does not match
|
|
26
|
+
#
|
|
27
|
+
# @!method refute_title
|
|
28
|
+
# @!method assert_no_title
|
|
29
|
+
# see {Capybara::Node::DocumentMatchers#assert_no_title}
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Assertion that current path matches
|
|
33
|
+
#
|
|
34
|
+
# @!method assert_current_path
|
|
35
|
+
# see {Capybara::SessionMatchers#assert_current_path}
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Assertion that current page does not match
|
|
39
|
+
#
|
|
40
|
+
# @!method refute_current_path
|
|
41
|
+
# @!method assert_no_current_path
|
|
42
|
+
# see {Capybara::SessionMatchers#assert_no_current_path}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
%w(assert_text assert_no_text assert_title assert_no_title assert_current_path assert_no_current_path).each do |assertion_name|
|
|
46
|
+
self.class_eval <<-EOM, __FILE__, __LINE__ + 1
|
|
47
|
+
def #{assertion_name} *args
|
|
48
|
+
self.assertions +=1
|
|
49
|
+
subject, *args = determine_subject(args)
|
|
50
|
+
subject.#{assertion_name}(*args)
|
|
51
|
+
rescue Capybara::ExpectationNotMet => e
|
|
52
|
+
raise ::Minitest::Assertion, e.message
|
|
53
|
+
end
|
|
54
|
+
EOM
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
alias_method :refute_title, :assert_no_title
|
|
58
|
+
alias_method :refute_text, :assert_no_text
|
|
59
|
+
alias_method :refute_content, :refute_text
|
|
60
|
+
alias_method :refute_current_path, :assert_no_current_path
|
|
61
|
+
alias_method :assert_content, :assert_text
|
|
62
|
+
alias_method :assert_no_content, :refute_text
|
|
63
|
+
|
|
64
|
+
## Assert selector exists on page
|
|
65
|
+
#
|
|
66
|
+
# @!method assert_selector
|
|
67
|
+
# see {Capybara::Node::Matchers#assert_selector}
|
|
68
|
+
|
|
69
|
+
## Assert selector does not exist on page
|
|
70
|
+
#
|
|
71
|
+
# @!method assert_no_selector
|
|
72
|
+
# see {Capybara::Node::Matchers#assert_no_selector}
|
|
73
|
+
|
|
74
|
+
## Assert element matches selector
|
|
75
|
+
#
|
|
76
|
+
# @!method assert_matches_selector
|
|
77
|
+
# see {Capybara::Node::Matchers#assert_matches_selector}
|
|
78
|
+
|
|
79
|
+
## Assert element does not match selector
|
|
80
|
+
#
|
|
81
|
+
# @!method assert_xpath
|
|
82
|
+
# see {Capybara::Node::Matchers#assert_not_matches_selector}
|
|
83
|
+
|
|
84
|
+
%w(assert_selector assert_no_selector
|
|
85
|
+
assert_all_of_selectors assert_none_of_selectors
|
|
86
|
+
assert_matches_selector assert_not_matches_selector).each do |assertion_name|
|
|
87
|
+
self.class_eval <<-EOM, __FILE__, __LINE__ + 1
|
|
88
|
+
def #{assertion_name} *args, &optional_filter_block
|
|
89
|
+
self.assertions +=1
|
|
90
|
+
subject, *args = determine_subject(args)
|
|
91
|
+
subject.#{assertion_name}(*args, &optional_filter_block)
|
|
92
|
+
rescue Capybara::ExpectationNotMet => e
|
|
93
|
+
raise ::Minitest::Assertion, e.message
|
|
94
|
+
end
|
|
95
|
+
EOM
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
alias_method :refute_selector, :assert_no_selector
|
|
99
|
+
alias_method :refute_matches_selector, :assert_not_matches_selector
|
|
100
|
+
|
|
101
|
+
%w(xpath css link button field select table).each do |selector_type|
|
|
102
|
+
define_method "assert_#{selector_type}" do |*args, &optional_filter_block|
|
|
103
|
+
subject, *args = determine_subject(args)
|
|
104
|
+
locator, options = extract_locator(args)
|
|
105
|
+
assert_selector(subject, selector_type.to_sym, locator, options, &optional_filter_block)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
define_method "assert_no_#{selector_type}" do |*args, &optional_filter_block|
|
|
109
|
+
subject, *args = determine_subject(args)
|
|
110
|
+
locator, options = extract_locator(args)
|
|
111
|
+
assert_no_selector(subject, selector_type.to_sym, locator, options, &optional_filter_block)
|
|
112
|
+
end
|
|
113
|
+
alias_method "refute_#{selector_type}", "assert_no_#{selector_type}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
%w(checked unchecked).each do |field_type|
|
|
117
|
+
define_method "assert_#{field_type}_field" do |*args, &optional_filter_block|
|
|
118
|
+
subject, *args = determine_subject(args)
|
|
119
|
+
locator, options = extract_locator(args)
|
|
120
|
+
assert_selector(subject, :field, locator, options.merge(field_type.to_sym => true), &optional_filter_block)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
define_method "assert_no_#{field_type}_field" do |*args, &optional_filter_block|
|
|
124
|
+
subject, *args = determine_subject(args)
|
|
125
|
+
locator, options = extract_locator(args)
|
|
126
|
+
assert_no_selector(subject, :field, locator, options.merge(field_type.to_sym => true), &optional_filter_block)
|
|
127
|
+
end
|
|
128
|
+
alias_method "refute_#{field_type}_field", "assert_no_#{field_type}_field"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
%w(xpath css).each do |selector_type|
|
|
132
|
+
define_method "assert_matches_#{selector_type}" do |*args, &optional_filter_block|
|
|
133
|
+
subject, *args = determine_subject(args)
|
|
134
|
+
assert_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
define_method "assert_not_matches_#{selector_type}" do |*args, &optional_filter_block|
|
|
138
|
+
subject, *args = determine_subject(args)
|
|
139
|
+
assert_not_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)
|
|
140
|
+
end
|
|
141
|
+
alias_method "refute_matches_#{selector_type}", "assert_not_matches_#{selector_type}"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
##
|
|
146
|
+
# Assertion that there is xpath
|
|
147
|
+
#
|
|
148
|
+
# @!method assert_xpath
|
|
149
|
+
# see Capybara::Node::Matchers#has_xpath?
|
|
150
|
+
|
|
151
|
+
##
|
|
152
|
+
# Assertion that there is no xpath
|
|
153
|
+
#
|
|
154
|
+
# @!method refute_xpath
|
|
155
|
+
# @!method assert_no_xpath
|
|
156
|
+
# see Capybara::Node::Matchers#has_no_xpath?
|
|
157
|
+
|
|
158
|
+
##
|
|
159
|
+
# Assertion that there is css
|
|
160
|
+
#
|
|
161
|
+
# @!method assert_css
|
|
162
|
+
# see Capybara::Node::Matchers#has_css?
|
|
163
|
+
|
|
164
|
+
##
|
|
165
|
+
# Assertion that there is no css
|
|
166
|
+
#
|
|
167
|
+
# @!method refute_css
|
|
168
|
+
# @!method assert_no_css
|
|
169
|
+
# see Capybara::Node::Matchers#has_no_css?
|
|
170
|
+
|
|
171
|
+
##
|
|
172
|
+
# Assertion that there is link
|
|
173
|
+
#
|
|
174
|
+
# @!method assert_link
|
|
175
|
+
# see {Capybara::Node::Matchers#has_link?}
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Assertion that there is no link
|
|
179
|
+
#
|
|
180
|
+
# @!method assert_no_link
|
|
181
|
+
# @!method refute_link
|
|
182
|
+
# see {Capybara::Node::Matchers#has_no_link?}
|
|
183
|
+
|
|
184
|
+
##
|
|
185
|
+
# Assertion that there is button
|
|
186
|
+
#
|
|
187
|
+
# @!method assert_button
|
|
188
|
+
# see {Capybara::Node::Matchers#has_button?}
|
|
189
|
+
|
|
190
|
+
##
|
|
191
|
+
# Assertion that there is no button
|
|
192
|
+
#
|
|
193
|
+
# @!method refute_button
|
|
194
|
+
# @!method assert_no_button
|
|
195
|
+
# see {Capybara::Node::Matchers#has_no_button?}
|
|
196
|
+
|
|
197
|
+
##
|
|
198
|
+
# Assertion that there is field
|
|
199
|
+
#
|
|
200
|
+
# @!method assert_field
|
|
201
|
+
# see {Capybara::Node::Matchers#has_field?}
|
|
202
|
+
|
|
203
|
+
##
|
|
204
|
+
# Assertion that there is no field
|
|
205
|
+
#
|
|
206
|
+
# @!method refute_field
|
|
207
|
+
# @!method assert_no_field
|
|
208
|
+
# see {Capybara::Node::Matchers#has_no_field?}
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
# Assertion that there is checked_field
|
|
212
|
+
#
|
|
213
|
+
# @!method assert_checked_field
|
|
214
|
+
# see {Capybara::Node::Matchers#has_checked_field?}
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# Assertion that there is no checked_field
|
|
218
|
+
#
|
|
219
|
+
# @!method assert_no_checked_field
|
|
220
|
+
# @!method refute_checked_field
|
|
221
|
+
|
|
222
|
+
##
|
|
223
|
+
# Assertion that there is unchecked_field
|
|
224
|
+
#
|
|
225
|
+
# @!method assert_unchecked_field
|
|
226
|
+
# see {Capybara::Node::Matchers#has_unchecked_field?}
|
|
227
|
+
|
|
228
|
+
##
|
|
229
|
+
# Assertion that there is no unchecked_field
|
|
230
|
+
#
|
|
231
|
+
# @!method assert_no_unchecked_field
|
|
232
|
+
# @!method refute_unchecked_field
|
|
233
|
+
|
|
234
|
+
##
|
|
235
|
+
# Assertion that there is select
|
|
236
|
+
#
|
|
237
|
+
# @!method assert_select
|
|
238
|
+
# see {Capybara::Node::Matchers#has_select?}
|
|
239
|
+
|
|
240
|
+
##
|
|
241
|
+
# Assertion that there is no select
|
|
242
|
+
#
|
|
243
|
+
# @!method refute_select
|
|
244
|
+
# @!method assert_no_select
|
|
245
|
+
# see {Capybara::Node::Matchers#has_no_select?}
|
|
246
|
+
|
|
247
|
+
##
|
|
248
|
+
# Assertion that there is table
|
|
249
|
+
#
|
|
250
|
+
# @!method assert_table
|
|
251
|
+
# see {Capybara::Node::Matchers#has_table?}
|
|
252
|
+
|
|
253
|
+
##
|
|
254
|
+
# Assertion that there is no table
|
|
255
|
+
#
|
|
256
|
+
# @!method refute_table
|
|
257
|
+
# @!method assert_no_table
|
|
258
|
+
# see {Capybara::Node::Matchers#has_no_table?}
|
|
259
|
+
|
|
260
|
+
private
|
|
261
|
+
|
|
262
|
+
def determine_subject(args)
|
|
263
|
+
case args.first
|
|
264
|
+
when Capybara::Session, Capybara::Node::Base, Capybara::Node::Simple
|
|
265
|
+
args
|
|
266
|
+
else
|
|
267
|
+
[page, *args]
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def extract_locator(args)
|
|
272
|
+
locator, options = *args, {}
|
|
273
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
274
|
+
[locator, options]
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
module Actions
|
|
4
5
|
|
|
5
6
|
##
|
|
6
7
|
#
|
|
7
|
-
# Finds a button or link
|
|
8
|
-
#
|
|
8
|
+
# Finds a button or link and clicks it. See {Capybara::Node::Actions#click_button} and
|
|
9
|
+
# {Capybara::Node::Actions#click_link} for what locator will match against for each type of element
|
|
10
|
+
# @!macro waiting_behavior
|
|
11
|
+
# If the driver is capable of executing JavaScript, +$0+ will wait for a set amount of time
|
|
12
|
+
# and continuously retry finding the element until either the element is found or the time
|
|
13
|
+
# expires. The length of time +find+ will wait is controlled through {Capybara.default_max_wait_time}
|
|
14
|
+
#
|
|
15
|
+
# @option options [false, Numeric] wait (Capybara.default_max_wait_time) Maximum time to wait for matching element to appear.
|
|
16
|
+
#
|
|
17
|
+
# @overload click_link_or_button([locator], options)
|
|
18
|
+
#
|
|
19
|
+
# @param [String] locator See {Capybara::Node::Actions#click_button} and {Capybara::Node::Actions#click_link}
|
|
9
20
|
#
|
|
10
|
-
# @
|
|
21
|
+
# @return [Capybara::Node::Element] The element clicked
|
|
11
22
|
#
|
|
12
|
-
def click_link_or_button(locator, options={})
|
|
23
|
+
def click_link_or_button(locator=nil, options={})
|
|
24
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
13
25
|
find(:link_or_button, locator, options).click
|
|
14
26
|
end
|
|
15
27
|
alias_method :click_on, :click_link_or_button
|
|
@@ -19,10 +31,15 @@ module Capybara
|
|
|
19
31
|
# Finds a link by id, text or title and clicks it. Also looks at image
|
|
20
32
|
# alt text inside the link.
|
|
21
33
|
#
|
|
22
|
-
# @
|
|
23
|
-
# @param options See {Capybara::Node::Finders#find_link}
|
|
34
|
+
# @macro waiting_behavior
|
|
24
35
|
#
|
|
25
|
-
|
|
36
|
+
# @overload click_link([locator], options)
|
|
37
|
+
# @param [String] locator text, id, title or nested image's alt attribute
|
|
38
|
+
# @param options See {Capybara::Node::Finders#find_link}
|
|
39
|
+
#
|
|
40
|
+
# @return [Capybara::Node::Element] The element clicked
|
|
41
|
+
def click_link(locator=nil, options={})
|
|
42
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
26
43
|
find(:link, locator, options).click
|
|
27
44
|
end
|
|
28
45
|
|
|
@@ -33,9 +50,14 @@ module Capybara
|
|
|
33
50
|
# \<button> element. All buttons can be found by their id, value, or title. \<button> elements can also be found
|
|
34
51
|
# by their text content, and image \<input> elements by their alt attribute
|
|
35
52
|
#
|
|
36
|
-
# @
|
|
37
|
-
#
|
|
38
|
-
|
|
53
|
+
# @macro waiting_behavior
|
|
54
|
+
#
|
|
55
|
+
# @overload click_button([locator], options)
|
|
56
|
+
# @param [String] locator Which button to find
|
|
57
|
+
# @param options See {Capybara::Node::Finders#find_button}
|
|
58
|
+
# @return [Capybara::Node::Element] The element clicked
|
|
59
|
+
def click_button(locator=nil, options={})
|
|
60
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
39
61
|
find(:button, locator, options).click
|
|
40
62
|
end
|
|
41
63
|
|
|
@@ -44,20 +66,35 @@ module Capybara
|
|
|
44
66
|
# Locate a text field or text area and fill it in with the given text
|
|
45
67
|
# The field can be found via its name, id or label text.
|
|
46
68
|
#
|
|
47
|
-
# page.fill_in 'Name', :
|
|
69
|
+
# page.fill_in 'Name', with: 'Bob'
|
|
48
70
|
#
|
|
49
|
-
# @param [String] locator Which field to fill in
|
|
50
|
-
# @param [Hash] options
|
|
51
|
-
# @option options [String] :with The value to fill in - required
|
|
52
|
-
# @option options [Hash] :fill_options Driver specific options regarding how to fill fields
|
|
53
71
|
#
|
|
72
|
+
# @overload fill_in([locator], options={})
|
|
73
|
+
# @param [String] locator Which field to fill in
|
|
74
|
+
# @param [Hash] options
|
|
75
|
+
# @macro waiting_behavior
|
|
76
|
+
# @option options [String] :with The value to fill in - required
|
|
77
|
+
# @option options [Hash] :fill_options Driver specific options regarding how to fill fields
|
|
78
|
+
# @option options [String] :currently_with The current value property of the field to fill in
|
|
79
|
+
# @option options [Boolean] :multiple Match fields that can have multiple values?
|
|
80
|
+
# @option options [String] :id Match fields that match the id attribute
|
|
81
|
+
# @option options [String] :name Match fields that match the name attribute
|
|
82
|
+
# @option options [String] :placeholder Match fields that match the placeholder attribute
|
|
83
|
+
# @option options [String, Array<String>] :class Match fields that match the class(es) provided
|
|
84
|
+
#
|
|
85
|
+
# @return [Capybara::Node::Element] The element filled_in
|
|
54
86
|
def fill_in(locator, options={})
|
|
87
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
55
88
|
raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
|
|
56
89
|
with = options.delete(:with)
|
|
57
90
|
fill_options = options.delete(:fill_options)
|
|
91
|
+
options[:with] = options.delete(:currently_with) if options.has_key?(:currently_with)
|
|
58
92
|
find(:fillable_field, locator, options).set(with, fill_options)
|
|
59
93
|
end
|
|
60
94
|
|
|
95
|
+
# @!macro label_click
|
|
96
|
+
# @option options [Boolean] :allow_label_click (Capybara.automatic_label_click) Attempt to click the label to toggle state if element is non-visible.
|
|
97
|
+
|
|
61
98
|
##
|
|
62
99
|
#
|
|
63
100
|
# Find a radio button and mark it as checked. The radio button can be found
|
|
@@ -65,10 +102,19 @@ module Capybara
|
|
|
65
102
|
#
|
|
66
103
|
# page.choose('Male')
|
|
67
104
|
#
|
|
68
|
-
# @
|
|
105
|
+
# @overload choose([locator], options)
|
|
106
|
+
# @param [String] locator Which radio button to choose
|
|
69
107
|
#
|
|
108
|
+
# @option options [String] :option Value of the radio_button to choose
|
|
109
|
+
# @option options [String] :id Match fields that match the id attribute
|
|
110
|
+
# @option options [String] :name Match fields that match the name attribute
|
|
111
|
+
# @option options [String, Array<String>] :class Match fields that match the class(es) provided
|
|
112
|
+
# @macro waiting_behavior
|
|
113
|
+
# @macro label_click
|
|
114
|
+
#
|
|
115
|
+
# @return [Capybara::Node::Element] The element chosen or the label clicked
|
|
70
116
|
def choose(locator, options={})
|
|
71
|
-
|
|
117
|
+
_check_with_label(:radio_button, true, locator, options)
|
|
72
118
|
end
|
|
73
119
|
|
|
74
120
|
##
|
|
@@ -78,10 +124,20 @@ module Capybara
|
|
|
78
124
|
#
|
|
79
125
|
# page.check('German')
|
|
80
126
|
#
|
|
81
|
-
# @param [String] locator Which check box to check
|
|
82
127
|
#
|
|
128
|
+
# @overload check([locator], options)
|
|
129
|
+
# @param [String] locator Which check box to check
|
|
130
|
+
#
|
|
131
|
+
# @option options [String] :option Value of the checkbox to select
|
|
132
|
+
# @option options [String] id Match fields that match the id attribute
|
|
133
|
+
# @option options [String] name Match fields that match the name attribute
|
|
134
|
+
# @option options [String, Array<String>] :class Match fields that match the class(es) provided
|
|
135
|
+
# @macro label_click
|
|
136
|
+
# @macro waiting_behavior
|
|
137
|
+
#
|
|
138
|
+
# @return [Capybara::Node::Element] The element checked or the label clicked
|
|
83
139
|
def check(locator, options={})
|
|
84
|
-
|
|
140
|
+
_check_with_label(:checkbox, true, locator, options)
|
|
85
141
|
end
|
|
86
142
|
|
|
87
143
|
##
|
|
@@ -91,10 +147,20 @@ module Capybara
|
|
|
91
147
|
#
|
|
92
148
|
# page.uncheck('German')
|
|
93
149
|
#
|
|
94
|
-
# @param [String] locator Which check box to uncheck
|
|
95
150
|
#
|
|
151
|
+
# @overload uncheck([locator], options)
|
|
152
|
+
# @param [String] locator Which check box to uncheck
|
|
153
|
+
#
|
|
154
|
+
# @option options [String] :option Value of the checkbox to deselect
|
|
155
|
+
# @option options [String] id Match fields that match the id attribute
|
|
156
|
+
# @option options [String] name Match fields that match the name attribute
|
|
157
|
+
# @option options [String, Array<String>] :class Match fields that match the class(es) provided
|
|
158
|
+
# @macro label_click
|
|
159
|
+
# @macro waiting_behavior
|
|
160
|
+
#
|
|
161
|
+
# @return [Capybara::Node::Element] The element unchecked or the label clicked
|
|
96
162
|
def uncheck(locator, options={})
|
|
97
|
-
|
|
163
|
+
_check_with_label(:checkbox, false, locator, options)
|
|
98
164
|
end
|
|
99
165
|
|
|
100
166
|
##
|
|
@@ -106,11 +172,14 @@ module Capybara
|
|
|
106
172
|
# one option.
|
|
107
173
|
# The select box can be found via its name, id or label text. The option can be found by its text.
|
|
108
174
|
#
|
|
109
|
-
# page.select 'March', :
|
|
175
|
+
# page.select 'March', from: 'Month'
|
|
176
|
+
#
|
|
177
|
+
# @macro waiting_behavior
|
|
110
178
|
#
|
|
111
179
|
# @param [String] value Which option to select
|
|
112
180
|
# @option options [String] :from The id, name or label of the select box
|
|
113
181
|
#
|
|
182
|
+
# @return [Capybara::Node::Element] The option element selected
|
|
114
183
|
def select(value, options={})
|
|
115
184
|
if options.has_key?(:from)
|
|
116
185
|
from = options.delete(:from)
|
|
@@ -126,11 +195,14 @@ module Capybara
|
|
|
126
195
|
# box is a multiple select, +unselect+ can be called multiple times to unselect more than
|
|
127
196
|
# one option. The select box can be found via its name, id or label text.
|
|
128
197
|
#
|
|
129
|
-
# page.unselect 'March', :
|
|
198
|
+
# page.unselect 'March', from: 'Month'
|
|
199
|
+
#
|
|
200
|
+
# @macro waiting_behavior
|
|
130
201
|
#
|
|
131
202
|
# @param [String] value Which option to unselect
|
|
132
203
|
# @param [Hash{:from => String}] options The id, name or label of the select box
|
|
133
204
|
#
|
|
205
|
+
# @return [Capybara::Node::Element] The option element unselected
|
|
134
206
|
def unselect(value, options={})
|
|
135
207
|
if options.has_key?(:from)
|
|
136
208
|
from = options.delete(:from)
|
|
@@ -147,15 +219,99 @@ module Capybara
|
|
|
147
219
|
#
|
|
148
220
|
# page.attach_file(locator, '/path/to/file.png')
|
|
149
221
|
#
|
|
222
|
+
# @macro waiting_behavior
|
|
223
|
+
#
|
|
150
224
|
# @param [String] locator Which field to attach the file to
|
|
151
225
|
# @param [String] path The path of the file that will be attached, or an array of paths
|
|
152
226
|
#
|
|
227
|
+
# @option options [Symbol] match (Capybara.match) The matching strategy to use (:one, :first, :prefer_exact, :smart).
|
|
228
|
+
# @option options [Boolean] exact (Capybara.exact) Match the exact label name/contents or accept a partial match.
|
|
229
|
+
# @option options [Boolean] multiple Match field which allows multiple file selection
|
|
230
|
+
# @option options [String] id Match fields that match the id attribute
|
|
231
|
+
# @option options [String] name Match fields that match the name attribute
|
|
232
|
+
# @option options [String, Array<String>] :class Match fields that match the class(es) provided
|
|
233
|
+
# @option options [true, Hash] make_visible A Hash of CSS styles to change before attempting to attach the file, if `true` { opacity: 1, display: 'block', visibility: 'visible' } is used (may not be supported by all drivers)
|
|
234
|
+
#
|
|
235
|
+
# @return [Capybara::Node::Element] The file field element
|
|
153
236
|
def attach_file(locator, path, options={})
|
|
237
|
+
locator, path, options = nil, locator, path if path.is_a? Hash
|
|
154
238
|
Array(path).each do |p|
|
|
155
239
|
raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s)
|
|
156
240
|
end
|
|
157
|
-
|
|
241
|
+
# Allow user to update the CSS style of the file input since they are so often hidden on a page
|
|
242
|
+
if style = options.delete(:make_visible)
|
|
243
|
+
style = { opacity: 1, display: 'block', visibility: 'visible' } if style == true
|
|
244
|
+
ff = find(:file_field, locator, options.merge({visible: :all}))
|
|
245
|
+
_update_style(ff, style)
|
|
246
|
+
if ff.visible?
|
|
247
|
+
begin
|
|
248
|
+
ff.set(path)
|
|
249
|
+
ensure
|
|
250
|
+
_reset_style(ff)
|
|
251
|
+
end
|
|
252
|
+
else
|
|
253
|
+
raise ExpectationNotMet, "The style changes in :make_visible did not make the file input visible"
|
|
254
|
+
end
|
|
255
|
+
else
|
|
256
|
+
find(:file_field, locator, options).set(path)
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
private
|
|
261
|
+
def _update_style(element, style)
|
|
262
|
+
script = <<-JS
|
|
263
|
+
var el = arguments[0];
|
|
264
|
+
el.capybara_style_cache = el.style.cssText;
|
|
265
|
+
var css = arguments[1];
|
|
266
|
+
for (var prop in css){
|
|
267
|
+
if (css.hasOwnProperty(prop)) {
|
|
268
|
+
el.style[prop] = css[prop]
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
JS
|
|
272
|
+
begin
|
|
273
|
+
session.execute_script(script, element, style)
|
|
274
|
+
rescue Capybara::NotSupportedByDriverError
|
|
275
|
+
warn "The :make_visible option is not supported by the current driver - ignoring"
|
|
276
|
+
end
|
|
158
277
|
end
|
|
278
|
+
|
|
279
|
+
def _reset_style(element)
|
|
280
|
+
script = <<-JS
|
|
281
|
+
var el = arguments[0];
|
|
282
|
+
if (el.hasOwnProperty('capybara_style_cache')) {
|
|
283
|
+
el.style.cssText = el.capybara_style_cache;
|
|
284
|
+
delete el.capybara_style_cache;
|
|
285
|
+
}
|
|
286
|
+
JS
|
|
287
|
+
begin
|
|
288
|
+
session.execute_script(script, element)
|
|
289
|
+
rescue
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _check_with_label(selector, checked, locator, options)
|
|
295
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
296
|
+
allow_label_click = options.delete(:allow_label_click) { session_options.automatic_label_click }
|
|
297
|
+
|
|
298
|
+
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
|
299
|
+
begin
|
|
300
|
+
el = find(selector, locator, options)
|
|
301
|
+
el.set(checked)
|
|
302
|
+
rescue => e
|
|
303
|
+
raise unless allow_label_click && catch_error?(e)
|
|
304
|
+
begin
|
|
305
|
+
el ||= find(selector, locator, options.merge(visible: :all))
|
|
306
|
+
label = find(:label, for: el, visible: true)
|
|
307
|
+
label.click unless (el.checked? == checked)
|
|
308
|
+
rescue
|
|
309
|
+
raise e
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
159
315
|
end
|
|
160
316
|
end
|
|
161
317
|
end
|
data/lib/capybara/node/base.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
|
|
@@ -16,13 +17,13 @@ module Capybara
|
|
|
16
17
|
#
|
|
17
18
|
# session = Capybara::Session.new(:rack_test, my_app)
|
|
18
19
|
# session.visit('/')
|
|
19
|
-
# session.fill_in('Foo', :
|
|
20
|
+
# session.fill_in('Foo', with: 'Bar') # from Capybara::Node::Actions
|
|
20
21
|
# bar = session.find('#bar') # from Capybara::Node::Finders
|
|
21
|
-
# bar.select('Baz', :
|
|
22
|
+
# bar.select('Baz', from: 'Quox') # from Capybara::Node::Actions
|
|
22
23
|
# session.has_css?('#foobar') # from Capybara::Node::Matchers
|
|
23
24
|
#
|
|
24
25
|
class Base
|
|
25
|
-
attr_reader :session, :base, :
|
|
26
|
+
attr_reader :session, :base, :query_scope
|
|
26
27
|
|
|
27
28
|
include Capybara::Node::Finders
|
|
28
29
|
include Capybara::Node::Actions
|
|
@@ -73,7 +74,7 @@ module Capybara
|
|
|
73
74
|
# @return [Object] The result of the given block
|
|
74
75
|
# @raise [Capybara::FrozenInTime] If the return value of `Time.now` appears stuck
|
|
75
76
|
#
|
|
76
|
-
def synchronize(seconds=
|
|
77
|
+
def synchronize(seconds=session_options.default_max_wait_time, options = {})
|
|
77
78
|
start_time = Capybara::Helpers.monotonic_time
|
|
78
79
|
|
|
79
80
|
if session.synchronized
|
|
@@ -89,7 +90,7 @@ module Capybara
|
|
|
89
90
|
raise e if (Capybara::Helpers.monotonic_time - start_time) >= seconds
|
|
90
91
|
sleep(0.05)
|
|
91
92
|
raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Capybara::Helpers.monotonic_time == start_time
|
|
92
|
-
reload if
|
|
93
|
+
reload if session_options.automatic_reload
|
|
93
94
|
retry
|
|
94
95
|
ensure
|
|
95
96
|
session.synchronized = false
|
|
@@ -107,6 +108,17 @@ module Capybara
|
|
|
107
108
|
base.find_xpath(xpath)
|
|
108
109
|
end
|
|
109
110
|
|
|
111
|
+
# @deprecated Use query_scope instead
|
|
112
|
+
def parent
|
|
113
|
+
warn "DEPRECATED: #parent is deprecated in favor of #query_scope - Note: #parent was not the elements parent in the document so it's most likely not what you wanted anyway"
|
|
114
|
+
query_scope
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @api private
|
|
118
|
+
def session_options
|
|
119
|
+
session.config
|
|
120
|
+
end
|
|
121
|
+
|
|
110
122
|
protected
|
|
111
123
|
|
|
112
124
|
def catch_error?(error, errors = nil)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
|
|
@@ -23,6 +24,10 @@ module Capybara
|
|
|
23
24
|
find(:xpath, '/html').text(type)
|
|
24
25
|
end
|
|
25
26
|
|
|
27
|
+
##
|
|
28
|
+
#
|
|
29
|
+
# @return [String] The title of the document
|
|
30
|
+
#
|
|
26
31
|
def title
|
|
27
32
|
session.driver.title
|
|
28
33
|
end
|