capybara 3.32.2 → 3.35.2
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 +97 -15
- data/README.md +9 -4
- data/lib/capybara.rb +18 -8
- data/lib/capybara/config.rb +4 -6
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/helpers.rb +25 -1
- data/lib/capybara/minitest.rb +2 -3
- data/lib/capybara/minitest/spec.rb +14 -11
- data/lib/capybara/node/actions.rb +16 -21
- data/lib/capybara/node/base.rb +6 -6
- data/lib/capybara/node/element.rb +1 -5
- data/lib/capybara/node/finders.rb +7 -6
- data/lib/capybara/node/matchers.rb +12 -12
- data/lib/capybara/node/simple.rb +5 -1
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/current_path_query.rb +14 -4
- data/lib/capybara/queries/selector_query.rb +40 -18
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +7 -1
- data/lib/capybara/rack_test/browser.rb +7 -3
- data/lib/capybara/rack_test/driver.rb +1 -0
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +1 -1
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/drivers.rb +18 -12
- data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
- data/lib/capybara/registrations/servers.rb +2 -1
- data/lib/capybara/result.rb +6 -10
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/rspec/matcher_proxies.rb +1 -1
- data/lib/capybara/rspec/matchers.rb +7 -6
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/match_style.rb +5 -0
- data/lib/capybara/selector.rb +12 -3
- data/lib/capybara/selector/builders/css_builder.rb +1 -1
- data/lib/capybara/selector/builders/xpath_builder.rb +3 -1
- data/lib/capybara/selector/definition.rb +11 -9
- data/lib/capybara/selector/definition/button.rb +26 -14
- data/lib/capybara/selector/definition/css.rb +1 -1
- data/lib/capybara/selector/definition/datalist_input.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +2 -1
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/label.rb +1 -1
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/select.rb +1 -1
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector/filter_set.rb +2 -2
- data/lib/capybara/selector/selector.rb +9 -1
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
- data/lib/capybara/selenium/driver.rb +48 -4
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +9 -11
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -11
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
- data/lib/capybara/selenium/extensions/find.rb +4 -4
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/logger_suppressor.rb +8 -2
- data/lib/capybara/selenium/node.rb +9 -5
- data/lib/capybara/selenium/nodes/chrome_node.rb +23 -5
- data/lib/capybara/selenium/nodes/firefox_node.rb +7 -2
- data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/logs.rb +7 -9
- data/lib/capybara/server/animation_disabler.rb +8 -3
- data/lib/capybara/server/middleware.rb +4 -2
- data/lib/capybara/session.rb +23 -14
- data/lib/capybara/session/config.rb +3 -1
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/test.js +13 -1
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/check_spec.rb +6 -0
- data/lib/capybara/spec/session/click_button_spec.rb +11 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/has_button_spec.rb +51 -0
- data/lib/capybara/spec/session/has_css_spec.rb +2 -1
- data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
- data/lib/capybara/spec/session/has_field_spec.rb +16 -0
- data/lib/capybara/spec/session/has_select_spec.rb +4 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
- data/lib/capybara/spec/session/has_text_spec.rb +0 -11
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +29 -9
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +12 -12
- data/lib/capybara/spec/test_app.rb +23 -21
- data/lib/capybara/spec/views/form.erb +25 -2
- data/lib/capybara/spec/views/with_animation.erb +8 -0
- data/lib/capybara/spec/views/with_dragula.erb +3 -1
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +3 -0
- data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +3 -7
- data/spec/basic_node_spec.rb +9 -8
- data/spec/capybara_spec.rb +1 -1
- data/spec/dsl_spec.rb +14 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +3 -2
- data/spec/rack_test_spec.rb +16 -5
- data/spec/rspec/features_spec.rb +3 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +61 -49
- data/spec/rspec_spec.rb +4 -0
- data/spec/selector_spec.rb +17 -2
- data/spec/selenium_spec_chrome.rb +39 -20
- data/spec/selenium_spec_chrome_remote.rb +5 -1
- data/spec/selenium_spec_firefox.rb +15 -13
- data/spec/server_spec.rb +60 -49
- data/spec/shared_selenium_session.rb +83 -1
- data/spec/spec_helper.rb +1 -1
- metadata +49 -14
- data/lib/capybara/spec/session/source_spec.rb +0 -0
|
@@ -45,20 +45,18 @@ module Capybara
|
|
|
45
45
|
JS
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
SCROLL_POSITIONS = {
|
|
49
|
+
top: '0',
|
|
50
|
+
bottom: 'arguments[0].scrollHeight',
|
|
51
|
+
center: '(arguments[0].scrollHeight - arguments[0].clientHeight)/2'
|
|
52
|
+
}.freeze
|
|
53
|
+
|
|
48
54
|
def scroll_to_location(location)
|
|
49
|
-
scroll_y = case location
|
|
50
|
-
when :top
|
|
51
|
-
'0'
|
|
52
|
-
when :bottom
|
|
53
|
-
'arguments[0].scrollHeight'
|
|
54
|
-
when :center
|
|
55
|
-
'(arguments[0].scrollHeight - arguments[0].clientHeight)/2'
|
|
56
|
-
end
|
|
57
55
|
driver.execute_script <<~JS, self
|
|
58
56
|
if (arguments[0].scrollTo){
|
|
59
|
-
arguments[0].scrollTo(0, #{
|
|
57
|
+
arguments[0].scrollTo(0, #{SCROLL_POSITIONS[location]});
|
|
60
58
|
} else {
|
|
61
|
-
arguments[0].scrollTop = #{
|
|
59
|
+
arguments[0].scrollTop = #{SCROLL_POSITIONS[location]};
|
|
62
60
|
}
|
|
63
61
|
JS
|
|
64
62
|
end
|
|
@@ -8,8 +8,14 @@ module Capybara
|
|
|
8
8
|
super
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def deprecate(*)
|
|
12
|
-
|
|
11
|
+
def deprecate(*args, **opts, &block)
|
|
12
|
+
return if @suppress_for_capybara
|
|
13
|
+
|
|
14
|
+
if opts.empty?
|
|
15
|
+
super(*args, &block) # support Selenium 3
|
|
16
|
+
else
|
|
17
|
+
super
|
|
18
|
+
end
|
|
13
19
|
end
|
|
14
20
|
|
|
15
21
|
def suppress_deprecations
|
|
@@ -120,7 +120,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
|
120
120
|
end
|
|
121
121
|
rescue StandardError => e
|
|
122
122
|
if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) ||
|
|
123
|
-
e.message.
|
|
123
|
+
e.message.include?('Other element would receive the click')
|
|
124
124
|
scroll_to_center
|
|
125
125
|
end
|
|
126
126
|
|
|
@@ -281,7 +281,7 @@ private
|
|
|
281
281
|
driver.execute_script 'arguments[0].select()', self unless clear == :none
|
|
282
282
|
if rapid == true || ((value.length > auto_rapid_set_length) && rapid != false)
|
|
283
283
|
send_keys(value[0..3])
|
|
284
|
-
driver.execute_script
|
|
284
|
+
driver.execute_script RAPID_APPEND_TEXT, self, value[4...-3]
|
|
285
285
|
send_keys(value[-3..-1])
|
|
286
286
|
else
|
|
287
287
|
send_keys(value)
|
|
@@ -464,8 +464,8 @@ private
|
|
|
464
464
|
end
|
|
465
465
|
end
|
|
466
466
|
|
|
467
|
-
def each_key(keys)
|
|
468
|
-
normalize_keys(keys).each
|
|
467
|
+
def each_key(keys, &block)
|
|
468
|
+
normalize_keys(keys).each(&block)
|
|
469
469
|
end
|
|
470
470
|
|
|
471
471
|
def find_context
|
|
@@ -493,6 +493,9 @@ private
|
|
|
493
493
|
var xpath = '';
|
|
494
494
|
var pos, tempitem2;
|
|
495
495
|
|
|
496
|
+
if (el.getRootNode && el.getRootNode() instanceof ShadowRoot) {
|
|
497
|
+
return "(: Shadow DOM element - no XPath :)";
|
|
498
|
+
};
|
|
496
499
|
while(el !== xml.documentElement) {
|
|
497
500
|
pos = 0;
|
|
498
501
|
tempitem2 = el;
|
|
@@ -534,8 +537,9 @@ private
|
|
|
534
537
|
})(arguments[0], arguments[1], arguments[2])
|
|
535
538
|
JS
|
|
536
539
|
|
|
537
|
-
|
|
540
|
+
RAPID_APPEND_TEXT = <<~'JS'
|
|
538
541
|
(function(el, value) {
|
|
542
|
+
value = el.value + value;
|
|
539
543
|
if (el.maxLength && el.maxLength != -1){
|
|
540
544
|
value = value.slice(0, el.maxLength);
|
|
541
545
|
}
|
|
@@ -42,7 +42,7 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
|
42
42
|
raise
|
|
43
43
|
rescue ::Selenium::WebDriver::Error::WebDriverError => e
|
|
44
44
|
# chromedriver 74 (at least on mac) raises the wrong error for this
|
|
45
|
-
if e.message.
|
|
45
|
+
if e.message.include?('element click intercepted')
|
|
46
46
|
raise ::Selenium::WebDriver::Error::ElementClickInterceptedError, e.message
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -73,6 +73,24 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
def send_keys(*args)
|
|
77
|
+
args.chunk { |inp| inp.is_a?(String) && inp.match?(/\p{Emoji Presentation}/) }
|
|
78
|
+
.each do |contains_emoji, inputs|
|
|
79
|
+
if contains_emoji
|
|
80
|
+
inputs.join.grapheme_clusters.chunk { |gc| gc.match?(/\p{Emoji Presentation}/) }
|
|
81
|
+
.each do |emoji, clusters|
|
|
82
|
+
if emoji
|
|
83
|
+
driver.send(:execute_cdp, 'Input.insertText', text: clusters.join)
|
|
84
|
+
else
|
|
85
|
+
super(clusters.join)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
super(*inputs)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
76
94
|
private
|
|
77
95
|
|
|
78
96
|
def perform_legacy_drag(element, drop_modifiers)
|
|
@@ -92,7 +110,7 @@ private
|
|
|
92
110
|
end
|
|
93
111
|
end
|
|
94
112
|
|
|
95
|
-
def browser_version(to_float
|
|
113
|
+
def browser_version(to_float: true)
|
|
96
114
|
caps = capabilities
|
|
97
115
|
ver = (caps[:browser_version] || caps[:version])
|
|
98
116
|
ver = ver.to_f if to_float
|
|
@@ -100,15 +118,15 @@ private
|
|
|
100
118
|
end
|
|
101
119
|
|
|
102
120
|
def chromedriver_fixed_actions_key_state?
|
|
103
|
-
Gem::
|
|
121
|
+
Gem::Requirement.new('>= 76.0.3809.68').satisfied_by?(chromedriver_version)
|
|
104
122
|
end
|
|
105
123
|
|
|
106
124
|
def chromedriver_supports_displayed_endpoint?
|
|
107
|
-
Gem::
|
|
125
|
+
Gem::Requirement.new('>= 76.0.3809.25').satisfied_by?(chromedriver_version)
|
|
108
126
|
end
|
|
109
127
|
|
|
110
128
|
def chromedriver_version
|
|
111
|
-
capabilities['chrome']['chromedriverVersion'].split(' ')[0]
|
|
129
|
+
Gem::Version.new(capabilities['chrome']['chromedriverVersion'].split(' ')[0]) # rubocop:disable Style/RedundantArgument
|
|
112
130
|
end
|
|
113
131
|
|
|
114
132
|
def native_displayed?
|
|
@@ -40,11 +40,16 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
|
40
40
|
path_names.each { |path| native.send_keys(path) }
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def focused?
|
|
44
|
+
driver.evaluate_script('arguments[0] == document.activeElement', self)
|
|
45
|
+
end
|
|
46
|
+
|
|
43
47
|
def send_keys(*args)
|
|
44
48
|
# https://github.com/mozilla/geckodriver/issues/846
|
|
45
|
-
return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?
|
|
49
|
+
return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)
|
|
50
|
+
|
|
51
|
+
native.click unless focused?
|
|
46
52
|
|
|
47
|
-
native.click
|
|
48
53
|
_send_keys(args).perform
|
|
49
54
|
end
|
|
50
55
|
|
|
@@ -43,7 +43,7 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
|
|
|
43
43
|
return '' unless visible?
|
|
44
44
|
|
|
45
45
|
vis_text = driver.execute_script('return arguments[0].innerText', self)
|
|
46
|
-
vis_text.
|
|
46
|
+
vis_text.squeeze(' ')
|
|
47
47
|
.gsub(/[\ \n]*\n[\ \n]*/, "\n")
|
|
48
48
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
|
|
49
49
|
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
|
|
@@ -6,10 +6,10 @@ private
|
|
|
6
6
|
def read_atom(function)
|
|
7
7
|
@atoms ||= Hash.new do |hash, key|
|
|
8
8
|
hash[key] = begin
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
File.read(File.expand_path("../../atoms/#{key}.min.js", __FILE__))
|
|
10
|
+
rescue Errno::ENOENT
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
13
|
end
|
|
14
14
|
@atoms[function]
|
|
15
15
|
end
|
|
@@ -27,17 +27,15 @@ module Capybara
|
|
|
27
27
|
|
|
28
28
|
def log(type)
|
|
29
29
|
data = begin
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
execute :get_log, {}, type: type.to_s
|
|
31
|
+
rescue ::Selenium::WebDriver::Error::UnknownCommandError
|
|
32
|
+
execute :get_log_legacy, {}, type: type.to_s
|
|
33
|
+
end
|
|
34
34
|
|
|
35
35
|
Array(data).map do |l|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
next
|
|
40
|
-
end
|
|
36
|
+
::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
|
|
37
|
+
rescue KeyError
|
|
38
|
+
next
|
|
41
39
|
end
|
|
42
40
|
rescue ::Selenium::WebDriver::Error::UnknownCommandError
|
|
43
41
|
raise NotImplementedError, LOG_MSG
|
|
@@ -40,16 +40,21 @@ module Capybara
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def insert_disable(html)
|
|
43
|
-
html.sub(%r{(</
|
|
43
|
+
html.sub(%r{(</body>)}, "#{disable_markup}\\1")
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
DISABLE_MARKUP_TEMPLATE = <<~HTML
|
|
47
|
-
<script
|
|
47
|
+
<script>
|
|
48
|
+
//<![CDATA[
|
|
49
|
+
(typeof jQuery !== 'undefined') && (jQuery.fx.off = true);
|
|
50
|
+
//]]>
|
|
51
|
+
</script>
|
|
48
52
|
<style>
|
|
49
|
-
|
|
53
|
+
%<selector>s, %<selector>s::before, %<selector>s::after {
|
|
50
54
|
transition: none !important;
|
|
51
55
|
animation-duration: 0s !important;
|
|
52
56
|
animation-delay: 0s !important;
|
|
57
|
+
scroll-behavior: auto !important;
|
|
53
58
|
}
|
|
54
59
|
</style>
|
|
55
60
|
HTML
|
|
@@ -53,14 +53,16 @@ module Capybara
|
|
|
53
53
|
if env['PATH_INFO'] == '/__identify__'
|
|
54
54
|
[200, {}, [@app.object_id.to_s]]
|
|
55
55
|
else
|
|
56
|
-
|
|
56
|
+
request_uri = env['REQUEST_URI']
|
|
57
|
+
@counter.increment(request_uri)
|
|
58
|
+
|
|
57
59
|
begin
|
|
58
60
|
@extended_app.call(env)
|
|
59
61
|
rescue *@server_errors => e
|
|
60
62
|
@error ||= e
|
|
61
63
|
raise e
|
|
62
64
|
ensure
|
|
63
|
-
@counter.decrement(
|
|
65
|
+
@counter.decrement(request_uri)
|
|
64
66
|
end
|
|
65
67
|
end
|
|
66
68
|
end
|
data/lib/capybara/session.rb
CHANGED
|
@@ -58,7 +58,7 @@ module Capybara
|
|
|
58
58
|
].freeze
|
|
59
59
|
SESSION_METHODS = %i[
|
|
60
60
|
body html source current_url current_host current_path
|
|
61
|
-
execute_script evaluate_script visit refresh go_back go_forward
|
|
61
|
+
execute_script evaluate_script visit refresh go_back go_forward send_keys
|
|
62
62
|
within within_element within_fieldset within_table within_frame switch_to_frame
|
|
63
63
|
current_window windows open_new_window switch_to_window within_window window_opened_by
|
|
64
64
|
save_page save_and_open_page save_screenshot
|
|
@@ -97,8 +97,8 @@ module Capybara
|
|
|
97
97
|
|
|
98
98
|
def driver
|
|
99
99
|
@driver ||= begin
|
|
100
|
-
unless Capybara.drivers
|
|
101
|
-
other_drivers = Capybara.drivers.
|
|
100
|
+
unless Capybara.drivers[mode]
|
|
101
|
+
other_drivers = Capybara.drivers.names.map(&:inspect)
|
|
102
102
|
raise Capybara::DriverNotFoundError, "no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}"
|
|
103
103
|
end
|
|
104
104
|
driver = Capybara.drivers[mode].call(app)
|
|
@@ -192,7 +192,7 @@ module Capybara
|
|
|
192
192
|
# @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
|
|
193
193
|
#
|
|
194
194
|
def html
|
|
195
|
-
driver.html
|
|
195
|
+
driver.html || ''
|
|
196
196
|
end
|
|
197
197
|
alias_method :body, :html
|
|
198
198
|
alias_method :source, :html
|
|
@@ -303,6 +303,14 @@ module Capybara
|
|
|
303
303
|
driver.go_forward
|
|
304
304
|
end
|
|
305
305
|
|
|
306
|
+
##
|
|
307
|
+
# @!method send_keys
|
|
308
|
+
# @see Capybara::Node::Element#send_keys
|
|
309
|
+
#
|
|
310
|
+
def send_keys(*args, **kw_args)
|
|
311
|
+
driver.send_keys(*args, **kw_args)
|
|
312
|
+
end
|
|
313
|
+
|
|
306
314
|
##
|
|
307
315
|
#
|
|
308
316
|
# Executes the given block within the context of a node. {#within} takes the
|
|
@@ -355,8 +363,8 @@ module Capybara
|
|
|
355
363
|
#
|
|
356
364
|
# @param [String] locator Id or legend of the fieldset
|
|
357
365
|
#
|
|
358
|
-
def within_fieldset(locator)
|
|
359
|
-
within(:fieldset, locator)
|
|
366
|
+
def within_fieldset(locator, &block)
|
|
367
|
+
within(:fieldset, locator, &block)
|
|
360
368
|
end
|
|
361
369
|
|
|
362
370
|
##
|
|
@@ -365,8 +373,8 @@ module Capybara
|
|
|
365
373
|
#
|
|
366
374
|
# @param [String] locator Id or caption of the table
|
|
367
375
|
#
|
|
368
|
-
def within_table(locator)
|
|
369
|
-
within(:table, locator)
|
|
376
|
+
def within_table(locator, &block)
|
|
377
|
+
within(:table, locator, &block)
|
|
370
378
|
end
|
|
371
379
|
|
|
372
380
|
##
|
|
@@ -398,8 +406,9 @@ module Capybara
|
|
|
398
406
|
driver.switch_to_frame(:parent)
|
|
399
407
|
when :top
|
|
400
408
|
idx = scopes.index(:frame)
|
|
409
|
+
top_level_scopes = [:frame, nil]
|
|
401
410
|
if idx
|
|
402
|
-
if scopes.slice(idx..-1).any? { |scope| !
|
|
411
|
+
if scopes.slice(idx..-1).any? { |scope| !top_level_scopes.include?(scope) }
|
|
403
412
|
raise Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's "\
|
|
404
413
|
'`within` block.'
|
|
405
414
|
end
|
|
@@ -488,8 +497,8 @@ module Capybara
|
|
|
488
497
|
# @raise [ArgumentError] if both or neither arguments were provided
|
|
489
498
|
#
|
|
490
499
|
def switch_to_window(window = nil, **options, &window_locator)
|
|
491
|
-
raise ArgumentError, '`switch_to_window` can take either a block or a window, not both' if window &&
|
|
492
|
-
raise ArgumentError, '`switch_to_window`: either window or block should be provided' if !window && !
|
|
500
|
+
raise ArgumentError, '`switch_to_window` can take either a block or a window, not both' if window && window_locator
|
|
501
|
+
raise ArgumentError, '`switch_to_window`: either window or block should be provided' if !window && !window_locator
|
|
493
502
|
|
|
494
503
|
unless scopes.last.nil?
|
|
495
504
|
raise Capybara::ScopeError, '`switch_to_window` is not supposed to be invoked from '\
|
|
@@ -738,7 +747,7 @@ module Capybara
|
|
|
738
747
|
# @param [Hash] options a customizable set of options
|
|
739
748
|
#
|
|
740
749
|
def save_and_open_screenshot(path = nil, **options)
|
|
741
|
-
save_screenshot(path, **options).tap { |s_path| open_file(s_path) }
|
|
750
|
+
save_screenshot(path, **options).tap { |s_path| open_file(s_path) }
|
|
742
751
|
end
|
|
743
752
|
|
|
744
753
|
def document
|
|
@@ -788,7 +797,7 @@ module Capybara
|
|
|
788
797
|
#
|
|
789
798
|
# Yield a block using a specific maximum wait time.
|
|
790
799
|
#
|
|
791
|
-
def using_wait_time(seconds)
|
|
800
|
+
def using_wait_time(seconds, &block)
|
|
792
801
|
if Capybara.threadsafe
|
|
793
802
|
begin
|
|
794
803
|
previous_wait_time = config.default_max_wait_time
|
|
@@ -798,7 +807,7 @@ module Capybara
|
|
|
798
807
|
config.default_max_wait_time = previous_wait_time
|
|
799
808
|
end
|
|
800
809
|
else
|
|
801
|
-
Capybara.using_wait_time(seconds)
|
|
810
|
+
Capybara.using_wait_time(seconds, &block)
|
|
802
811
|
end
|
|
803
812
|
end
|
|
804
813
|
|
|
@@ -8,7 +8,7 @@ module Capybara
|
|
|
8
8
|
automatic_reload match exact exact_text raise_server_errors visible_text_only
|
|
9
9
|
automatic_label_click enable_aria_label save_path asset_host default_host app_host
|
|
10
10
|
server_host server_port server_errors default_set_options disable_animation test_id
|
|
11
|
-
predicates_wait default_normalize_ws w3c_click_offset].freeze
|
|
11
|
+
predicates_wait default_normalize_ws w3c_click_offset enable_aria_role].freeze
|
|
12
12
|
|
|
13
13
|
attr_accessor(*OPTIONS)
|
|
14
14
|
|
|
@@ -37,6 +37,8 @@ module Capybara
|
|
|
37
37
|
# See {Capybara.configure}
|
|
38
38
|
# @!method enable_aria_label
|
|
39
39
|
# See {Capybara.configure}
|
|
40
|
+
# @!method enable_aria_role
|
|
41
|
+
# See {Capybara.configure}
|
|
40
42
|
# @!method save_path
|
|
41
43
|
# See {Capybara.configure}
|
|
42
44
|
# @!method asset_host
|
|
@@ -13,14 +13,14 @@ module Capybara
|
|
|
13
13
|
# @param string [String] The string that the current 'path' should equal
|
|
14
14
|
# @overload $0(regexp, **options)
|
|
15
15
|
# @param regexp [Regexp] The regexp that the current 'path' should match to
|
|
16
|
-
# @option options [Boolean] :url (true if `string`
|
|
16
|
+
# @option options [Boolean] :url (true if `string` is a full url, otherwise false) Whether the comparison should be done against the full current url or just the path
|
|
17
17
|
# @option options [Boolean] :ignore_query (false) Whether the query portion of the current url/path should be ignored
|
|
18
18
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for the current url/path to eq/match given string/regexp argument
|
|
19
19
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
20
20
|
# @return [true]
|
|
21
21
|
#
|
|
22
|
-
def assert_current_path(path, **options)
|
|
23
|
-
_verify_current_path(path, **options) do |query|
|
|
22
|
+
def assert_current_path(path, **options, &optional_filter_block)
|
|
23
|
+
_verify_current_path(path, optional_filter_block, **options) do |query|
|
|
24
24
|
raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -35,8 +35,8 @@ module Capybara
|
|
|
35
35
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
36
36
|
# @return [true]
|
|
37
37
|
#
|
|
38
|
-
def assert_no_current_path(path, **options)
|
|
39
|
-
_verify_current_path(path, **options) do |query|
|
|
38
|
+
def assert_no_current_path(path, **options, &optional_filter_block)
|
|
39
|
+
_verify_current_path(path, optional_filter_block, **options) do |query|
|
|
40
40
|
raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)
|
|
41
41
|
end
|
|
42
42
|
end
|
|
@@ -50,8 +50,8 @@ module Capybara
|
|
|
50
50
|
# @macro current_path_query_params
|
|
51
51
|
# @return [Boolean]
|
|
52
52
|
#
|
|
53
|
-
def has_current_path?(path, **options)
|
|
54
|
-
make_predicate(options) { assert_current_path(path, **options) }
|
|
53
|
+
def has_current_path?(path, **options, &optional_filter_block)
|
|
54
|
+
make_predicate(options) { assert_current_path(path, **options, &optional_filter_block) }
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
##
|
|
@@ -63,14 +63,14 @@ module Capybara
|
|
|
63
63
|
# @macro current_path_query_params
|
|
64
64
|
# @return [Boolean]
|
|
65
65
|
#
|
|
66
|
-
def has_no_current_path?(path, **options)
|
|
67
|
-
make_predicate(options) { assert_no_current_path(path, **options) }
|
|
66
|
+
def has_no_current_path?(path, **options, &optional_filter_block)
|
|
67
|
+
make_predicate(options) { assert_no_current_path(path, **options, &optional_filter_block) }
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
private
|
|
71
71
|
|
|
72
|
-
def _verify_current_path(path, **options)
|
|
73
|
-
query = Capybara::Queries::CurrentPathQuery.new(path, **options)
|
|
72
|
+
def _verify_current_path(path, filter_block, **options)
|
|
73
|
+
query = Capybara::Queries::CurrentPathQuery.new(path, **options, &filter_block)
|
|
74
74
|
document.synchronize(query.wait) do
|
|
75
75
|
yield(query)
|
|
76
76
|
end
|