capybara 3.23.0 → 3.35.3
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 +264 -11
- data/README.md +10 -6
- data/lib/capybara.rb +20 -8
- data/lib/capybara/config.rb +10 -8
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/driver/node.rb +4 -0
- data/lib/capybara/dsl.rb +10 -2
- data/lib/capybara/helpers.rb +28 -2
- data/lib/capybara/minitest.rb +232 -144
- data/lib/capybara/minitest/spec.rb +156 -97
- data/lib/capybara/node/actions.rb +36 -36
- data/lib/capybara/node/base.rb +6 -6
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +77 -33
- data/lib/capybara/node/finders.rb +24 -17
- data/lib/capybara/node/matchers.rb +79 -64
- data/lib/capybara/node/simple.rb +11 -4
- data/lib/capybara/queries/ancestor_query.rb +6 -10
- data/lib/capybara/queries/base_query.rb +2 -1
- data/lib/capybara/queries/current_path_query.rb +14 -4
- data/lib/capybara/queries/selector_query.rb +259 -23
- data/lib/capybara/queries/sibling_query.rb +5 -11
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +13 -1
- data/lib/capybara/rack_test/browser.rb +13 -4
- data/lib/capybara/rack_test/driver.rb +2 -1
- data/lib/capybara/rack_test/form.rb +2 -2
- data/lib/capybara/rack_test/node.rb +42 -6
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/drivers.rb +18 -12
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +9 -2
- data/lib/capybara/result.rb +39 -19
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/rspec/matcher_proxies.rb +5 -5
- data/lib/capybara/rspec/matchers.rb +97 -74
- data/lib/capybara/rspec/matchers/base.rb +19 -6
- data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
- data/lib/capybara/rspec/matchers/have_ancestor.rb +5 -7
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +15 -10
- data/lib/capybara/rspec/matchers/have_sibling.rb +4 -7
- data/lib/capybara/rspec/matchers/have_text.rb +4 -7
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +7 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/selector.rb +46 -19
- data/lib/capybara/selector/builders/css_builder.rb +10 -6
- data/lib/capybara/selector/builders/xpath_builder.rb +4 -2
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition.rb +13 -11
- data/lib/capybara/selector/definition/button.rb +32 -15
- data/lib/capybara/selector/definition/checkbox.rb +2 -2
- data/lib/capybara/selector/definition/css.rb +3 -1
- data/lib/capybara/selector/definition/datalist_input.rb +2 -2
- data/lib/capybara/selector/definition/datalist_option.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +3 -2
- data/lib/capybara/selector/definition/field.rb +1 -1
- data/lib/capybara/selector/definition/file_field.rb +1 -1
- data/lib/capybara/selector/definition/fillable_field.rb +2 -2
- data/lib/capybara/selector/definition/label.rb +5 -3
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/option.rb +1 -1
- data/lib/capybara/selector/definition/radio_button.rb +2 -2
- data/lib/capybara/selector/definition/select.rb +33 -14
- data/lib/capybara/selector/definition/table.rb +6 -3
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector/filter_set.rb +13 -11
- data/lib/capybara/selector/filters/base.rb +6 -1
- data/lib/capybara/selector/filters/locator_filter.rb +1 -1
- data/lib/capybara/selector/regexp_disassembler.rb +7 -0
- data/lib/capybara/selector/selector.rb +13 -3
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -1
- data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +10 -10
- data/lib/capybara/selenium/driver.rb +86 -24
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +24 -21
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +21 -19
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +17 -1
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +0 -4
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +37 -26
- data/lib/capybara/selenium/extensions/html5_drag.rb +55 -11
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/logger_suppressor.rb +8 -2
- data/lib/capybara/selenium/node.rb +160 -40
- data/lib/capybara/selenium/nodes/chrome_node.rb +72 -12
- data/lib/capybara/selenium/nodes/edge_node.rb +32 -14
- data/lib/capybara/selenium/nodes/firefox_node.rb +28 -32
- data/lib/capybara/selenium/nodes/safari_node.rb +5 -29
- data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +32 -7
- data/lib/capybara/server.rb +19 -3
- data/lib/capybara/server/animation_disabler.rb +8 -3
- data/lib/capybara/server/checker.rb +1 -1
- data/lib/capybara/server/middleware.rb +22 -10
- data/lib/capybara/session.rb +66 -40
- data/lib/capybara/session/config.rb +11 -3
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +75 -7
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/all_spec.rb +60 -5
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
- data/lib/capybara/spec/session/check_spec.rb +6 -0
- data/lib/capybara/spec/session/click_button_spec.rb +16 -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/fill_in_spec.rb +29 -0
- data/lib/capybara/spec/session/find_spec.rb +55 -0
- data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -0
- data/lib/capybara/spec/session/has_button_spec.rb +51 -0
- data/lib/capybara/spec/session/has_css_spec.rb +26 -4
- data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
- data/lib/capybara/spec/session/has_field_spec.rb +34 -0
- data/lib/capybara/spec/session/has_select_spec.rb +32 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
- data/lib/capybara/spec/session/has_table_spec.rb +51 -5
- data/lib/capybara/spec/session/has_text_spec.rb +30 -0
- 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 +394 -9
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -15
- data/lib/capybara/spec/session/selectors_spec.rb +16 -3
- 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 +8 -8
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +14 -14
- data/lib/capybara/spec/test_app.rb +27 -21
- data/lib/capybara/spec/views/form.erb +47 -4
- data/lib/capybara/spec/views/offset.erb +32 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/with_animation.erb +37 -1
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_html.erb +24 -2
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +4 -1
- data/lib/capybara/spec/views/with_jstree.erb +26 -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 +15 -14
- data/spec/capybara_spec.rb +28 -28
- data/spec/dsl_spec.rb +16 -3
- data/spec/filter_set_spec.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +3 -2
- data/spec/minitest_spec_spec.rb +46 -46
- data/spec/rack_test_spec.rb +38 -15
- data/spec/regexp_dissassembler_spec.rb +52 -38
- data/spec/result_spec.rb +43 -32
- data/spec/rspec/features_spec.rb +4 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +68 -56
- data/spec/rspec_spec.rb +9 -5
- data/spec/selector_spec.rb +32 -17
- data/spec/selenium_spec_chrome.rb +78 -11
- data/spec/selenium_spec_chrome_remote.rb +23 -6
- data/spec/selenium_spec_edge.rb +15 -12
- data/spec/selenium_spec_firefox.rb +24 -19
- data/spec/selenium_spec_firefox_remote.rb +0 -8
- data/spec/selenium_spec_ie.rb +1 -6
- data/spec/server_spec.rb +106 -44
- data/spec/session_spec.rb +5 -5
- data/spec/shared_selenium_node.rb +56 -2
- data/spec/shared_selenium_session.rb +122 -15
- data/spec/spec_helper.rb +2 -2
- metadata +63 -17
- data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -18,14 +18,16 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
|
|
18
18
|
# In Chrome 75+ files are appended (due to WebDriver spec - why?) so we have to clear here if its multiple and already set
|
19
19
|
if chrome_edge?
|
20
20
|
driver.execute_script(<<~JS, self)
|
21
|
-
if (arguments[0].multiple &&
|
21
|
+
if (arguments[0].multiple && arguments[0].files.length){
|
22
22
|
arguments[0].value = null;
|
23
23
|
}
|
24
24
|
JS
|
25
25
|
end
|
26
26
|
super
|
27
27
|
rescue *file_errors => e
|
28
|
-
|
28
|
+
if e.message.match?(/File not found : .+\n.+/m)
|
29
|
+
raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
|
30
|
+
end
|
29
31
|
|
30
32
|
raise
|
31
33
|
end
|
@@ -36,14 +38,16 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
|
|
36
38
|
html5_drop(*args)
|
37
39
|
end
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
def click(*)
|
42
|
+
super
|
43
|
+
rescue Selenium::WebDriver::Error::InvalidArgumentError => e
|
44
|
+
tag_name, type = attrs(:tagName, :type).map { |val| val&.downcase }
|
45
|
+
if tag_name == 'input' && type == 'file'
|
46
|
+
raise Selenium::WebDriver::Error::InvalidArgumentError, "EdgeChrome can't click on file inputs.\n#{e.message}"
|
47
|
+
end
|
48
|
+
|
49
|
+
raise
|
50
|
+
end
|
47
51
|
|
48
52
|
def disabled?
|
49
53
|
return super unless chrome_edge?
|
@@ -61,6 +65,18 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
|
|
61
65
|
click unless selected_or_disabled
|
62
66
|
end
|
63
67
|
|
68
|
+
def visible?
|
69
|
+
return super unless chrome_edge? && native_displayed?
|
70
|
+
|
71
|
+
begin
|
72
|
+
bridge.send(:execute, :is_element_displayed, id: native.ref)
|
73
|
+
rescue Selenium::WebDriver::Error::UnknownCommandError
|
74
|
+
# If the is_element_displayed command is unknown, no point in trying again
|
75
|
+
driver.options[:native_displayed] = false
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
64
80
|
private
|
65
81
|
|
66
82
|
def file_errors
|
@@ -69,10 +85,6 @@ private
|
|
69
85
|
end
|
70
86
|
end
|
71
87
|
|
72
|
-
def bridge
|
73
|
-
driver.browser.send(:bridge)
|
74
|
-
end
|
75
|
-
|
76
88
|
def browser_version
|
77
89
|
@browser_version ||= begin
|
78
90
|
caps = driver.browser.capabilities
|
@@ -83,4 +95,10 @@ private
|
|
83
95
|
def chrome_edge?
|
84
96
|
browser_version >= 75
|
85
97
|
end
|
98
|
+
|
99
|
+
def native_displayed?
|
100
|
+
(driver.options[:native_displayed] != false) &&
|
101
|
+
# chromedriver_supports_displayed_endpoint? &&
|
102
|
+
(!ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS'])
|
103
|
+
end
|
86
104
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'capybara/selenium/extensions/html5_drag'
|
4
|
+
require 'capybara/selenium/extensions/file_input_click_emulation'
|
4
5
|
|
5
6
|
class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
6
7
|
include Html5Drag
|
8
|
+
include FileInputClickEmulation
|
7
9
|
|
8
10
|
def click(keys = [], **options)
|
9
11
|
super
|
@@ -12,7 +14,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
12
14
|
warn 'You are attempting to click a table row which has issues in geckodriver/marionette - '\
|
13
15
|
'see https://github.com/mozilla/geckodriver/issues/1228. Your test should probably be '\
|
14
16
|
'clicking on a table cell like a user would. Clicking the first cell in the row instead.'
|
15
|
-
return find_css('th:first-child,td:first-child')[0].click(keys, options)
|
17
|
+
return find_css('th:first-child,td:first-child')[0].click(keys, **options)
|
16
18
|
end
|
17
19
|
raise
|
18
20
|
end
|
@@ -24,7 +26,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
24
26
|
def set_file(value) # rubocop:disable Naming/AccessorMethodName
|
25
27
|
# By default files are appended so we have to clear here if its multiple and already set
|
26
28
|
driver.execute_script(<<~JS, self)
|
27
|
-
if (arguments[0].multiple &&
|
29
|
+
if (arguments[0].multiple && arguments[0].files.length){
|
28
30
|
arguments[0].value = null;
|
29
31
|
}
|
30
32
|
JS
|
@@ -38,11 +40,16 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
38
40
|
path_names.each { |path| native.send_keys(path) }
|
39
41
|
end
|
40
42
|
|
43
|
+
def focused?
|
44
|
+
driver.evaluate_script('arguments[0] == document.activeElement', self)
|
45
|
+
end
|
46
|
+
|
41
47
|
def send_keys(*args)
|
42
48
|
# https://github.com/mozilla/geckodriver/issues/846
|
43
|
-
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?
|
44
52
|
|
45
|
-
native.click
|
46
53
|
_send_keys(args).perform
|
47
54
|
end
|
48
55
|
|
@@ -65,9 +72,25 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
65
72
|
click unless selected_or_disabled
|
66
73
|
end
|
67
74
|
|
75
|
+
def visible?
|
76
|
+
return super unless native_displayed?
|
77
|
+
|
78
|
+
begin
|
79
|
+
bridge.send(:execute, :is_element_displayed, id: native.ref)
|
80
|
+
rescue Selenium::WebDriver::Error::UnknownCommandError
|
81
|
+
# If the is_element_displayed command is unknown, no point in trying again
|
82
|
+
driver.options[:native_displayed] = false
|
83
|
+
super
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
68
87
|
private
|
69
88
|
|
70
|
-
def
|
89
|
+
def native_displayed?
|
90
|
+
(driver.options[:native_displayed] != false) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']
|
91
|
+
end
|
92
|
+
|
93
|
+
def perform_with_options(click_options)
|
71
94
|
# Firefox/marionette has an issue clicking with offset near viewport edge
|
72
95
|
# scroll element to middle just in case
|
73
96
|
scroll_to_center if click_options.coords?
|
@@ -99,10 +122,6 @@ private
|
|
99
122
|
actions
|
100
123
|
end
|
101
124
|
|
102
|
-
def bridge
|
103
|
-
driver.browser.send(:bridge)
|
104
|
-
end
|
105
|
-
|
106
125
|
def upload(local_file)
|
107
126
|
return nil unless local_file
|
108
127
|
raise ArgumentError, "You may only upload files: #{local_file.inspect}" unless File.file?(local_file)
|
@@ -114,27 +133,4 @@ private
|
|
114
133
|
def browser_version
|
115
134
|
driver.browser.capabilities[:browser_version].to_f
|
116
135
|
end
|
117
|
-
|
118
|
-
class ModifierKeysStack
|
119
|
-
def initialize
|
120
|
-
@stack = []
|
121
|
-
end
|
122
|
-
|
123
|
-
def include?(key)
|
124
|
-
@stack.flatten.include?(key)
|
125
|
-
end
|
126
|
-
|
127
|
-
def press(key)
|
128
|
-
@stack.last.push(key)
|
129
|
-
end
|
130
|
-
|
131
|
-
def push
|
132
|
-
@stack.push []
|
133
|
-
end
|
134
|
-
|
135
|
-
def pop
|
136
|
-
@stack.pop
|
137
|
-
end
|
138
|
-
end
|
139
|
-
private_constant :ModifierKeysStack
|
140
136
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# require 'capybara/selenium/extensions/html5_drag'
|
4
|
+
require 'capybara/selenium/extensions/modifier_keys_stack'
|
4
5
|
|
5
6
|
class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
|
6
7
|
# include Html5Drag
|
@@ -16,7 +17,9 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
|
|
16
17
|
return find_css('th:first-child,td:first-child')[0].click(keys, options)
|
17
18
|
end
|
18
19
|
raise
|
19
|
-
rescue ::Selenium::WebDriver::Error::WebDriverError
|
20
|
+
rescue ::Selenium::WebDriver::Error::WebDriverError => e
|
21
|
+
raise unless e.instance_of? ::Selenium::WebDriver::Error::WebDriverError
|
22
|
+
|
20
23
|
# Safari doesn't return a specific error here - assume it's an ElementNotInteractableError
|
21
24
|
raise ::Selenium::WebDriver::Error::ElementNotInteractableError,
|
22
25
|
'Non distinct error raised in #click, translated to ElementNotInteractableError for retry'
|
@@ -40,7 +43,7 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
|
|
40
43
|
return '' unless visible?
|
41
44
|
|
42
45
|
vis_text = driver.execute_script('return arguments[0].innerText', self)
|
43
|
-
vis_text.
|
46
|
+
vis_text.squeeze(' ')
|
44
47
|
.gsub(/[\ \n]*\n[\ \n]*/, "\n")
|
45
48
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
|
46
49
|
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
|
@@ -87,10 +90,6 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
|
|
87
90
|
|
88
91
|
private
|
89
92
|
|
90
|
-
def bridge
|
91
|
-
driver.browser.send(:bridge)
|
92
|
-
end
|
93
|
-
|
94
93
|
def _send_keys(keys, actions = browser_action, down_keys = ModifierKeysStack.new)
|
95
94
|
case keys
|
96
95
|
when *MODIFIER_KEYS
|
@@ -116,27 +115,4 @@ private
|
|
116
115
|
shift left_shift right_shift
|
117
116
|
meta left_meta right_meta
|
118
117
|
command].freeze
|
119
|
-
|
120
|
-
class ModifierKeysStack
|
121
|
-
def initialize
|
122
|
-
@stack = []
|
123
|
-
end
|
124
|
-
|
125
|
-
def include?(key)
|
126
|
-
@stack.flatten.include?(key)
|
127
|
-
end
|
128
|
-
|
129
|
-
def press(key)
|
130
|
-
@stack.last.push(key)
|
131
|
-
end
|
132
|
-
|
133
|
-
def push
|
134
|
-
@stack.push []
|
135
|
-
end
|
136
|
-
|
137
|
-
def pop
|
138
|
-
@stack.pop
|
139
|
-
end
|
140
|
-
end
|
141
|
-
private_constant :ModifierKeysStack
|
142
118
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionPauser
|
4
|
+
def initialize(mouse, keyboard)
|
5
|
+
super
|
6
|
+
@devices[:pauser] = Pauser.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def pause(duration)
|
10
|
+
@actions << [:pauser, :pause, [duration]]
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
class Pauser
|
15
|
+
def pause(duration)
|
16
|
+
sleep duration
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private_constant :Pauser
|
21
|
+
end
|
22
|
+
|
23
|
+
if defined?(::Selenium::WebDriver::VERSION) && (::Selenium::WebDriver::VERSION.to_f < 4) &&
|
24
|
+
defined?(::Selenium::WebDriver::ActionBuilder)
|
25
|
+
::Selenium::WebDriver::ActionBuilder.prepend(ActionPauser)
|
26
|
+
end
|
@@ -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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module Selenium
|
5
|
+
module IsDisplayed
|
6
|
+
def commands(command)
|
7
|
+
case command
|
8
|
+
when :is_element_displayed
|
9
|
+
[:get, 'session/:session_id/element/:id/displayed']
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -4,16 +4,41 @@ module Capybara
|
|
4
4
|
module Selenium
|
5
5
|
module ChromeLogs
|
6
6
|
LOG_MSG = <<~MSG
|
7
|
-
Chromedriver 75+ defaults to W3C mode.
|
8
|
-
|
9
|
-
It is unknown how long non-W3C mode will be supported by chromedriver (it won't be supported by selenium-webdriver 4+) \
|
10
|
-
so you may need to consider other solutions in the near future.
|
7
|
+
Chromedriver 75+ defaults to W3C mode. Please upgrade to chromedriver >= \
|
8
|
+
75.0.3770.90 if you need to access logs while in W3C compliant mode.
|
11
9
|
MSG
|
12
10
|
|
13
|
-
|
14
|
-
|
11
|
+
COMMANDS = {
|
12
|
+
get_available_log_types: [:get, 'session/:session_id/se/log/types'],
|
13
|
+
get_log: [:post, 'session/:session_id/se/log'],
|
14
|
+
get_log_legacy: [:post, 'session/:session_id/log']
|
15
|
+
}.freeze
|
15
16
|
|
16
|
-
|
17
|
+
def commands(command)
|
18
|
+
COMMANDS[command] || super
|
19
|
+
end
|
20
|
+
|
21
|
+
def available_log_types
|
22
|
+
types = execute :get_available_log_types
|
23
|
+
Array(types).map(&:to_sym)
|
24
|
+
rescue ::Selenium::WebDriver::Error::UnknownCommandError
|
25
|
+
raise NotImplementedError, LOG_MSG
|
26
|
+
end
|
27
|
+
|
28
|
+
def log(type)
|
29
|
+
data = begin
|
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
|
+
|
35
|
+
Array(data).map do |l|
|
36
|
+
::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
|
37
|
+
rescue KeyError
|
38
|
+
next
|
39
|
+
end
|
40
|
+
rescue ::Selenium::WebDriver::Error::UnknownCommandError
|
41
|
+
raise NotImplementedError, LOG_MSG
|
17
42
|
end
|
18
43
|
end
|
19
44
|
end
|
data/lib/capybara/server.rb
CHANGED
@@ -24,7 +24,9 @@ module Capybara
|
|
24
24
|
host: Capybara.server_host,
|
25
25
|
reportable_errors: Capybara.server_errors,
|
26
26
|
extra_middleware: [])
|
27
|
-
|
27
|
+
unless deprecated_options.empty?
|
28
|
+
warn 'Positional arguments, other than the application, to Server#new are deprecated, please use keyword arguments'
|
29
|
+
end
|
28
30
|
@app = app
|
29
31
|
@extra_middleware = extra_middleware
|
30
32
|
@server_thread = nil # suppress warnings
|
@@ -61,7 +63,7 @@ module Capybara
|
|
61
63
|
def wait_for_pending_requests
|
62
64
|
timer = Capybara::Helpers.timer(expire_in: 60)
|
63
65
|
while pending_requests?
|
64
|
-
raise
|
66
|
+
raise "Requests did not finish in 60 seconds: #{middleware.pending_requests}" if timer.expired?
|
65
67
|
|
66
68
|
sleep 0.01
|
67
69
|
end
|
@@ -86,6 +88,10 @@ module Capybara
|
|
86
88
|
self
|
87
89
|
end
|
88
90
|
|
91
|
+
def base_url
|
92
|
+
"http#{'s' if using_ssl?}://#{host}:#{port}"
|
93
|
+
end
|
94
|
+
|
89
95
|
private
|
90
96
|
|
91
97
|
def middleware
|
@@ -102,7 +108,17 @@ module Capybara
|
|
102
108
|
|
103
109
|
def find_available_port(host)
|
104
110
|
server = TCPServer.new(host, 0)
|
105
|
-
server.addr[1]
|
111
|
+
port = server.addr[1]
|
112
|
+
server.close
|
113
|
+
|
114
|
+
# Workaround issue where some platforms (mac, ???) when passed a host
|
115
|
+
# of '0.0.0.0' will return a port that is only available on one of the
|
116
|
+
# ip addresses that resolves to, but the next binding to that port requires
|
117
|
+
# that port to be available on all ips
|
118
|
+
server = TCPServer.new(host, port)
|
119
|
+
port
|
120
|
+
rescue Errno::EADDRINUSE
|
121
|
+
retry
|
106
122
|
ensure
|
107
123
|
server&.close
|
108
124
|
end
|
@@ -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
|