selenium-webdriver 4.1.0 → 4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +221 -1
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/bin/linux/selenium-manager +0 -0
- data/bin/macos/selenium-manager +0 -0
- data/bin/windows/selenium-manager.exe +0 -0
- data/lib/selenium/server.rb +35 -26
- data/lib/selenium/webdriver/atoms/findElements.js +0 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
- data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
- data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
- data/lib/selenium/webdriver/atoms.rb +2 -3
- data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
- data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
- data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
- data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
- data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
- data/lib/selenium/webdriver/bidi/session.rb +51 -0
- data/lib/selenium/webdriver/bidi.rb +56 -0
- data/lib/selenium/webdriver/chrome/driver.rb +9 -29
- data/lib/selenium/webdriver/chrome/features.rb +6 -68
- data/lib/selenium/webdriver/chrome/options.rb +3 -223
- data/lib/selenium/webdriver/chrome/profile.rb +3 -83
- data/lib/selenium/webdriver/chrome/service.rb +3 -23
- data/lib/selenium/webdriver/chrome.rb +0 -14
- data/lib/selenium/webdriver/chromium/driver.rb +61 -0
- data/lib/selenium/webdriver/chromium/features.rb +103 -0
- data/lib/selenium/webdriver/chromium/options.rb +261 -0
- data/lib/selenium/webdriver/chromium/profile.rb +113 -0
- data/lib/selenium/webdriver/chromium/service.rb +42 -0
- data/lib/selenium/webdriver/chromium.rb +32 -0
- data/lib/selenium/webdriver/common/action_builder.rb +72 -22
- data/lib/selenium/webdriver/common/child_process.rb +124 -0
- data/lib/selenium/webdriver/common/driver.rb +36 -74
- data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +10 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -69
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
- data/lib/selenium/webdriver/common/driver_finder.rb +43 -0
- data/lib/selenium/webdriver/common/element.rb +8 -8
- data/lib/selenium/webdriver/common/error.rb +1 -3
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
- data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
- data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
- data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
- data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
- data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
- data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
- data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
- data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
- data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
- data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
- data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
- data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
- data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
- data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
- data/lib/selenium/webdriver/common/keys.rb +1 -0
- data/lib/selenium/webdriver/common/local_driver.rb +55 -0
- data/lib/selenium/webdriver/common/logger.rb +10 -2
- data/lib/selenium/webdriver/common/manager.rb +0 -27
- data/lib/selenium/webdriver/common/options.rb +32 -17
- data/lib/selenium/webdriver/common/platform.rb +8 -5
- data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
- data/lib/selenium/webdriver/common/proxy.rb +1 -1
- data/lib/selenium/webdriver/common/search_context.rb +0 -6
- data/lib/selenium/webdriver/common/selenium_manager.rb +108 -0
- data/lib/selenium/webdriver/common/service.rb +11 -22
- data/lib/selenium/webdriver/common/service_manager.rb +5 -14
- data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
- data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
- data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
- data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
- data/lib/selenium/webdriver/common/target_locator.rb +2 -3
- data/lib/selenium/webdriver/common/timeouts.rb +2 -2
- data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
- data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
- data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
- data/lib/selenium/webdriver/common/websocket_connection.rb +164 -0
- data/lib/selenium/webdriver/common/window.rb +6 -6
- data/lib/selenium/webdriver/common/zipper.rb +1 -1
- data/lib/selenium/webdriver/common.rb +21 -3
- data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
- data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
- data/lib/selenium/webdriver/devtools/request.rb +1 -3
- data/lib/selenium/webdriver/devtools/response.rb +1 -3
- data/lib/selenium/webdriver/devtools.rb +17 -114
- data/lib/selenium/webdriver/edge/driver.rb +9 -3
- data/lib/selenium/webdriver/edge/features.rb +4 -4
- data/lib/selenium/webdriver/edge/options.rb +3 -5
- data/lib/selenium/webdriver/edge/profile.rb +2 -2
- data/lib/selenium/webdriver/edge/service.rb +2 -6
- data/lib/selenium/webdriver/firefox/driver.rb +9 -2
- data/lib/selenium/webdriver/firefox/features.rb +6 -6
- data/lib/selenium/webdriver/firefox/options.rb +9 -3
- data/lib/selenium/webdriver/firefox/profile.rb +7 -11
- data/lib/selenium/webdriver/firefox/service.rb +0 -6
- data/lib/selenium/webdriver/firefox/util.rb +46 -0
- data/lib/selenium/webdriver/firefox.rb +1 -14
- data/lib/selenium/webdriver/ie/driver.rb +7 -1
- data/lib/selenium/webdriver/ie/service.rb +1 -7
- data/lib/selenium/webdriver/ie.rb +0 -14
- data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +15 -8
- data/lib/selenium/webdriver/remote/bridge.rb +59 -30
- data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
- data/lib/selenium/webdriver/remote/driver.rb +19 -14
- data/lib/selenium/webdriver/remote/http/curb.rb +0 -2
- data/lib/selenium/webdriver/remote/http/default.rb +7 -12
- data/lib/selenium/webdriver/remote/response.rb +2 -3
- data/lib/selenium/webdriver/remote.rb +0 -1
- data/lib/selenium/webdriver/safari/driver.rb +7 -1
- data/lib/selenium/webdriver/safari/features.rb +0 -2
- data/lib/selenium/webdriver/safari/options.rb +5 -1
- data/lib/selenium/webdriver/safari/service.rb +0 -4
- data/lib/selenium/webdriver/safari.rb +1 -15
- data/lib/selenium/webdriver/support/color.rb +20 -20
- data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
- data/lib/selenium/webdriver/support/guards.rb +1 -1
- data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
- data/lib/selenium/webdriver/support/select.rb +3 -1
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +4 -4
- data/selenium-webdriver.gemspec +13 -11
- metadata +70 -59
- data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module WheelActions
|
23
|
+
class ScrollOrigin
|
24
|
+
class << self
|
25
|
+
def element(element, x_offset = 0, y_offset = 0)
|
26
|
+
new(element, x_offset, y_offset)
|
27
|
+
end
|
28
|
+
|
29
|
+
def viewport(x_offset = 0, y_offset = 0)
|
30
|
+
new(:viewport, x_offset, y_offset)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :origin, :x_offset, :y_offset
|
35
|
+
|
36
|
+
#
|
37
|
+
# Use a static method to access
|
38
|
+
# @api private
|
39
|
+
#
|
40
|
+
def initialize(origin, x_offset, y_offset)
|
41
|
+
@origin = origin
|
42
|
+
@x_offset = x_offset
|
43
|
+
@y_offset = y_offset
|
44
|
+
end
|
45
|
+
end # ScrollOrigin
|
46
|
+
end # WheelActions
|
47
|
+
end # WebDriver
|
48
|
+
end # Selenium
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module Interactions
|
23
|
+
#
|
24
|
+
# Actions related to pressing keys.
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
29
|
+
class TypingInteraction < Interaction
|
30
|
+
attr_reader :type
|
31
|
+
|
32
|
+
def initialize(source, type, key)
|
33
|
+
super(source)
|
34
|
+
@type = assert_type(type)
|
35
|
+
@key = Keys.encode_key(key)
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_source(source)
|
39
|
+
raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? KeyInput
|
40
|
+
end
|
41
|
+
|
42
|
+
def assert_type(type)
|
43
|
+
raise TypeError, "#{type.inspect} is not a valid key subtype" unless KeyInput::SUBTYPES.key? type
|
44
|
+
|
45
|
+
KeyInput::SUBTYPES[type]
|
46
|
+
end
|
47
|
+
|
48
|
+
def encode
|
49
|
+
{type: @type, value: @key}
|
50
|
+
end
|
51
|
+
end # TypingInteraction
|
52
|
+
end # Interactions
|
53
|
+
end # WebDriver
|
54
|
+
end # Selenium
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module WheelActions
|
23
|
+
attr_writer :default_scroll_duration
|
24
|
+
|
25
|
+
#
|
26
|
+
# By default this is set to 250ms in the ActionBuilder constructor
|
27
|
+
# It can be overridden with default_scroll_duration=
|
28
|
+
#
|
29
|
+
|
30
|
+
def default_scroll_duration
|
31
|
+
@default_scroll_duration ||= @duration / 1000.0 # convert ms to seconds
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# If the element is outside the viewport, scrolls the bottom of the element to the bottom of the viewport.
|
36
|
+
#
|
37
|
+
# @example Scroll to element
|
38
|
+
# el = driver.find_element(id: "some_id")
|
39
|
+
# driver.action.scroll_to(element).perform
|
40
|
+
#
|
41
|
+
# @param [Object] Which element to scroll into the viewport.
|
42
|
+
# @return [Selenium::WebDriver::WheelActions] A self reference.
|
43
|
+
def scroll_to(element, device: nil)
|
44
|
+
scroll(origin: element, device: device)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Scrolls by provided amounts with the origin in the top left corner of the viewport.
|
49
|
+
#
|
50
|
+
# @example Scroll viewport by a specified amount
|
51
|
+
# el = driver.find_element(id: "some_id")
|
52
|
+
# driver.action.scroll_by(100, 200).perform
|
53
|
+
#
|
54
|
+
# @param [Integer] delta_x Distance along X axis to scroll using the wheel. A negative value scrolls left.
|
55
|
+
# @param [Integer] delta_y Distance along Y axis to scroll using the wheel. A negative value scrolls up.
|
56
|
+
# @return [Selenium::WebDriver::WheelActions] A self reference.
|
57
|
+
def scroll_by(delta_x, delta_y, device: nil)
|
58
|
+
scroll(delta_x: delta_x, delta_y: delta_y, device: device)
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Scrolls by provided amount based on a provided origin.
|
63
|
+
#
|
64
|
+
# The scroll origin is either the center of an element or the upper left of the viewport plus any offsets.
|
65
|
+
# If the origin is an element, and the element is not in the viewport, the bottom of the element will first
|
66
|
+
# be scrolled to the bottom of the viewport.
|
67
|
+
#
|
68
|
+
# @example Scroll from element by a specified amount
|
69
|
+
# el = driver.find_element(id: "some_id")
|
70
|
+
# origin = WheelActions::ScrollOrigin.element(el)
|
71
|
+
# driver.action.scroll_from(origin, 0, 200).perform
|
72
|
+
#
|
73
|
+
# @example Scroll from element by a specified amount with an offset
|
74
|
+
# el = driver.find_element(id: "some_id")
|
75
|
+
# origin = WheelActions::ScrollOrigin.element(el, 10, 10)
|
76
|
+
# driver.action.scroll_from(origin, 100, 200).perform
|
77
|
+
#
|
78
|
+
# @example Scroll viewport by a specified amount with an offset
|
79
|
+
# origin = WheelActions::ScrollOrigin.viewport(10, 10)
|
80
|
+
# driver.action.scroll_from(origin, 0, 200).perform
|
81
|
+
#
|
82
|
+
# @param [ScrollOrigin] scroll_origin Where scroll originates (viewport or element center) plus provided offsets.
|
83
|
+
# @param [Integer] delta_x Distance along X axis to scroll using the wheel. A negative value scrolls left.
|
84
|
+
# @param [Integer] delta_y Distance along Y axis to scroll using the wheel. A negative value scrolls up.
|
85
|
+
# @return [Selenium::WebDriver::WheelActions] A self reference.
|
86
|
+
# @raise [Error::MoveTargetOutOfBoundsError] If the origin with offset is outside the viewport.
|
87
|
+
def scroll_from(scroll_origin, delta_x, delta_y, device: nil)
|
88
|
+
raise TypeError, "#{scroll_origin.inspect} isn't a valid ScrollOrigin" unless scroll_origin.is_a?(ScrollOrigin)
|
89
|
+
|
90
|
+
scroll(x: scroll_origin.x_offset,
|
91
|
+
y: scroll_origin.y_offset,
|
92
|
+
delta_x: delta_x,
|
93
|
+
delta_y: delta_y,
|
94
|
+
origin: scroll_origin.origin,
|
95
|
+
device: device)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def scroll(**opts)
|
101
|
+
opts[:duration] = default_scroll_duration
|
102
|
+
wheel = wheel_input(opts.delete(:device))
|
103
|
+
wheel.create_scroll(**opts)
|
104
|
+
tick(wheel)
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def wheel_input(name = nil)
|
109
|
+
device(name: name, type: Interactions::WHEEL) || add_wheel_input('wheel')
|
110
|
+
end
|
111
|
+
end # WheelActions
|
112
|
+
end # WebDriver
|
113
|
+
end # Selenium
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module Interactions
|
23
|
+
#
|
24
|
+
# Creates actions specific to Pointer Input devices
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
29
|
+
class WheelInput < InputDevice
|
30
|
+
def initialize(name = nil)
|
31
|
+
super(name)
|
32
|
+
@type = Interactions::WHEEL
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_scroll(**opts)
|
36
|
+
opts[:source] = self
|
37
|
+
add_action(Scroll.new(**opts))
|
38
|
+
end
|
39
|
+
end # PointerInput
|
40
|
+
end # Interactions
|
41
|
+
end # WebDriver
|
42
|
+
end # Selenium
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
module Selenium
|
21
|
+
module WebDriver
|
22
|
+
module LocalDriver
|
23
|
+
def initialize_local_driver(capabilities, options, service, url)
|
24
|
+
raise ArgumentError, "Can't initialize #{self.class} with :url" if url
|
25
|
+
|
26
|
+
service ||= Service.send(browser)
|
27
|
+
caps = process_options(options, capabilities, service)
|
28
|
+
url = service_url(service)
|
29
|
+
|
30
|
+
[caps, url]
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_options(options, capabilities, service)
|
34
|
+
default_options = Options.send(browser)
|
35
|
+
|
36
|
+
if options && capabilities
|
37
|
+
msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
|
38
|
+
raise ArgumentError, msg
|
39
|
+
elsif options && !options.is_a?(default_options.class)
|
40
|
+
raise ArgumentError, ":options must be an instance of #{default_options.class}"
|
41
|
+
elsif capabilities
|
42
|
+
WebDriver.logger.deprecate("The :capabilities parameter for #{self.class}",
|
43
|
+
":options argument with an instance of #{self.class}",
|
44
|
+
id: :capabilities)
|
45
|
+
service.executable_path ||= WebDriver::DriverFinder.path(capabilities, service.class)
|
46
|
+
generate_capabilities(capabilities)
|
47
|
+
else
|
48
|
+
options ||= default_options
|
49
|
+
service.executable_path ||= WebDriver::DriverFinder.path(options, service.class)
|
50
|
+
options.as_json
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -48,9 +48,10 @@ module Selenium
|
|
48
48
|
#
|
49
49
|
# @param [String] progname Allow child projects to use Selenium's Logger pattern
|
50
50
|
#
|
51
|
-
def initialize(progname = 'Selenium')
|
51
|
+
def initialize(progname = 'Selenium', ignored: nil)
|
52
52
|
@logger = create_logger(progname)
|
53
|
-
@ignored =
|
53
|
+
@ignored = Array(ignored)
|
54
|
+
@first_warning = false
|
54
55
|
end
|
55
56
|
|
56
57
|
#
|
@@ -94,6 +95,13 @@ module Selenium
|
|
94
95
|
# @yield see #deprecate
|
95
96
|
#
|
96
97
|
def warn(message, id: [])
|
98
|
+
unless @first_warning
|
99
|
+
@first_warning = true
|
100
|
+
warn("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
|
101
|
+
"https://selenium.dev/documentation/webdriver/troubleshooting/logging#ruby\n"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
97
105
|
id = Array(id)
|
98
106
|
return if (@ignored & id).any?
|
99
107
|
|
@@ -104,33 +104,6 @@ module Selenium
|
|
104
104
|
@timeouts ||= Timeouts.new(@bridge)
|
105
105
|
end
|
106
106
|
|
107
|
-
def logs
|
108
|
-
WebDriver.logger.deprecate('Manager#logs', 'Chrome::Driver#logs')
|
109
|
-
@logs ||= Logs.new(@bridge)
|
110
|
-
end
|
111
|
-
|
112
|
-
#
|
113
|
-
# @param type [Symbol] Supports two values: :tab and :window.
|
114
|
-
# @return [String] The value of the window handle
|
115
|
-
#
|
116
|
-
def new_window(type = :tab)
|
117
|
-
WebDriver.logger.deprecate('Manager#new_window', 'TargetLocator#new_window', id: :new_window) do
|
118
|
-
'e.g., `driver.switch_to.new_window(:tab)`'
|
119
|
-
end
|
120
|
-
case type
|
121
|
-
when :tab, :window
|
122
|
-
result = @bridge.new_window(type)
|
123
|
-
unless result.key?('handle')
|
124
|
-
raise UnknownError, "the driver did not return a handle. " \
|
125
|
-
"The returned result: #{result.inspect}"
|
126
|
-
end
|
127
|
-
result['handle']
|
128
|
-
else
|
129
|
-
raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
|
130
|
-
"Try :tab or :window"
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
107
|
def window
|
135
108
|
@window ||= Window.new(@bridge)
|
136
109
|
end
|
@@ -38,12 +38,12 @@ module Selenium
|
|
38
38
|
def ie(**opts)
|
39
39
|
IE::Options.new(**opts)
|
40
40
|
end
|
41
|
-
|
41
|
+
alias internet_explorer ie
|
42
42
|
|
43
43
|
def edge(**opts)
|
44
44
|
Edge::Options.new(**opts)
|
45
45
|
end
|
46
|
-
|
46
|
+
alias microsoftedge edge
|
47
47
|
|
48
48
|
def safari(**opts)
|
49
49
|
Safari::Options.new(**opts)
|
@@ -66,17 +66,10 @@ module Selenium
|
|
66
66
|
|
67
67
|
attr_accessor :options
|
68
68
|
|
69
|
-
def initialize(
|
69
|
+
def initialize(**opts)
|
70
70
|
self.class.set_capabilities
|
71
71
|
|
72
|
-
@options =
|
73
|
-
WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
|
74
|
-
"custom values directly in #new constructor",
|
75
|
-
id: :options_options)
|
76
|
-
opts.merge(options)
|
77
|
-
else
|
78
|
-
opts
|
79
|
-
end
|
72
|
+
@options = opts
|
80
73
|
@options[:browser_name] = self.class::BROWSER
|
81
74
|
end
|
82
75
|
|
@@ -92,7 +85,13 @@ module Selenium
|
|
92
85
|
#
|
93
86
|
|
94
87
|
def add_option(name, value = nil)
|
95
|
-
|
88
|
+
name, value = name.first if value.nil? && name.is_a?(Hash)
|
89
|
+
|
90
|
+
unless name.to_s.include?(':')
|
91
|
+
WebDriver.logger.deprecate('Options#add_option for w3c or browser specific capabilities',
|
92
|
+
'applicable attribute accessors or pass into constructor',
|
93
|
+
id: :add_option)
|
94
|
+
end
|
96
95
|
@options[name] = value
|
97
96
|
end
|
98
97
|
|
@@ -102,7 +101,7 @@ module Selenium
|
|
102
101
|
as_json == other.as_json
|
103
102
|
end
|
104
103
|
|
105
|
-
|
104
|
+
alias eql? ==
|
106
105
|
|
107
106
|
#
|
108
107
|
# @api private
|
@@ -113,11 +112,27 @@ module Selenium
|
|
113
112
|
|
114
113
|
w3c_options = process_w3c_options(options)
|
115
114
|
|
116
|
-
self.class::CAPABILITIES.
|
117
|
-
|
118
|
-
|
115
|
+
browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
|
116
|
+
from_name = options.delete(capability_name)
|
117
|
+
from_alias = options.delete(capability_alias)
|
118
|
+
capability_value = if !from_name.nil? && capability_alias != capability_name
|
119
|
+
WebDriver.logger.deprecate("#{capability_name} as option",
|
120
|
+
capability_alias.to_s, id: :option_symbols)
|
121
|
+
from_name
|
122
|
+
elsif !from_alias.nil?
|
123
|
+
from_alias
|
124
|
+
end
|
125
|
+
|
126
|
+
hash[capability_name] = capability_value unless capability_value.nil?
|
119
127
|
end
|
120
|
-
|
128
|
+
|
129
|
+
unless options.empty?
|
130
|
+
msg = 'These options are not w3c compliant and will result in failures in a future release'
|
131
|
+
WebDriver.logger.warn("#{msg}: #{options}")
|
132
|
+
browser_options.merge!(options)
|
133
|
+
end
|
134
|
+
|
135
|
+
browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
|
121
136
|
|
122
137
|
process_browser_options(browser_options)
|
123
138
|
generate_as_json(w3c_options.merge(browser_options))
|
@@ -78,6 +78,10 @@ module Selenium
|
|
78
78
|
engine == :jruby
|
79
79
|
end
|
80
80
|
|
81
|
+
def truffleruby?
|
82
|
+
engine == :truffleruby
|
83
|
+
end
|
84
|
+
|
81
85
|
def ruby_version
|
82
86
|
RUBY_VERSION
|
83
87
|
end
|
@@ -104,8 +108,7 @@ module Selenium
|
|
104
108
|
end
|
105
109
|
|
106
110
|
def cygwin?
|
107
|
-
RUBY_PLATFORM
|
108
|
-
!Regexp.last_match.nil?
|
111
|
+
RUBY_PLATFORM.include?('cygwin')
|
109
112
|
end
|
110
113
|
|
111
114
|
def null_device
|
@@ -177,9 +180,9 @@ module Selenium
|
|
177
180
|
|
178
181
|
def find_in_program_files(*binary_names)
|
179
182
|
paths = [
|
180
|
-
ENV
|
181
|
-
ENV
|
182
|
-
ENV
|
183
|
+
ENV.fetch('PROGRAMFILES', '\\Program Files'),
|
184
|
+
ENV.fetch('ProgramFiles(x86)', '\\Program Files (x86)'),
|
185
|
+
ENV.fetch('ProgramW6432', '\\Program Files')
|
183
186
|
]
|
184
187
|
|
185
188
|
paths.each do |root|
|
@@ -61,9 +61,6 @@ module Selenium
|
|
61
61
|
raise ArgumentError, "cannot find element by #{how.inspect}" unless by
|
62
62
|
|
63
63
|
bridge.find_element_by by, what, ref
|
64
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
65
|
-
# Implicit Wait times out in Edge
|
66
|
-
raise Selenium::WebDriver::Error::NoSuchElementError
|
67
64
|
end
|
68
65
|
|
69
66
|
#
|
@@ -79,9 +76,6 @@ module Selenium
|
|
79
76
|
raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
|
80
77
|
|
81
78
|
bridge.find_elements_by by, what, ref
|
82
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
83
|
-
# Implicit Wait times out in Edge
|
84
|
-
[]
|
85
79
|
end
|
86
80
|
|
87
81
|
private
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
5
|
+
# distributed with this work for additional information
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance
|
9
|
+
# with the License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
14
|
+
# software distributed under the License is distributed on an
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16
|
+
# KIND, either express or implied. See the License for the
|
17
|
+
# specific language governing permissions and limitations
|
18
|
+
# under the License.
|
19
|
+
|
20
|
+
require 'open3'
|
21
|
+
|
22
|
+
module Selenium
|
23
|
+
module WebDriver
|
24
|
+
#
|
25
|
+
# Wrapper for getting information from the Selenium Manager binaries.
|
26
|
+
# This implementation is still in beta, and may change.
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
class SeleniumManager
|
30
|
+
BIN_PATH = '../../../../../bin'
|
31
|
+
|
32
|
+
class << self
|
33
|
+
# @param [Options] options browser options.
|
34
|
+
# @return [String] the path to the correct driver.
|
35
|
+
def driver_path(options)
|
36
|
+
message = 'applicable driver not found; attempting to install with Selenium Manager'
|
37
|
+
WebDriver.logger.warn(message)
|
38
|
+
|
39
|
+
unless options.is_a?(Options)
|
40
|
+
raise ArgumentError, "SeleniumManager requires a WebDriver::Options instance, not #{options.inspect}"
|
41
|
+
end
|
42
|
+
|
43
|
+
command = [binary, '--browser', options.browser_name, '--output', 'json']
|
44
|
+
if options.browser_version
|
45
|
+
command << '--browser-version'
|
46
|
+
command << options.browser_version
|
47
|
+
end
|
48
|
+
if options.respond_to?(:binary) && !options.binary.nil?
|
49
|
+
command << '--browser-path'
|
50
|
+
command << options.binary.gsub('\\', '\\\\\\')
|
51
|
+
end
|
52
|
+
command << '--debug' if WebDriver.logger.debug?
|
53
|
+
|
54
|
+
location = run(*command)
|
55
|
+
WebDriver.logger.debug("Driver found at #{location}")
|
56
|
+
Platform.assert_executable location
|
57
|
+
|
58
|
+
location
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# @return [String] the path to the correct selenium manager
|
64
|
+
def binary
|
65
|
+
@binary ||= begin
|
66
|
+
path = File.expand_path(BIN_PATH, __FILE__)
|
67
|
+
path << if Platform.windows?
|
68
|
+
'/windows/selenium-manager.exe'
|
69
|
+
elsif Platform.mac?
|
70
|
+
'/macos/selenium-manager'
|
71
|
+
elsif Platform.linux?
|
72
|
+
'/linux/selenium-manager'
|
73
|
+
end
|
74
|
+
location = File.expand_path(path, __FILE__)
|
75
|
+
unless location.is_a?(String) && File.exist?(location) && File.executable?(location)
|
76
|
+
raise Error::WebDriverError, 'Unable to obtain Selenium Manager'
|
77
|
+
end
|
78
|
+
|
79
|
+
WebDriver.logger.debug("Selenium Manager found at #{location}")
|
80
|
+
location
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def run(*command)
|
85
|
+
WebDriver.logger.debug("Executing Process #{command}")
|
86
|
+
|
87
|
+
begin
|
88
|
+
stdout, stderr, status = Open3.capture3(*command)
|
89
|
+
json_output = stdout.empty? ? nil : JSON.parse(stdout)
|
90
|
+
result = json_output&.dig('result', 'message')
|
91
|
+
rescue StandardError => e
|
92
|
+
raise Error::WebDriverError, "Unsuccessful command executed: #{command}", e.message
|
93
|
+
end
|
94
|
+
|
95
|
+
if status.exitstatus.positive?
|
96
|
+
raise Error::WebDriverError, "Unsuccessful command executed: #{command}\n#{result}#{stderr}"
|
97
|
+
end
|
98
|
+
|
99
|
+
json_output['logs'].each do |log|
|
100
|
+
WebDriver.logger.send(log['level'].downcase, log['message'])
|
101
|
+
end
|
102
|
+
|
103
|
+
result
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end # SeleniumManager
|
107
|
+
end # WebDriver
|
108
|
+
end # Selenium
|