selenium-webdriver 4.1.0 → 4.28.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 +4 -4
- data/CHANGES +446 -1
- data/Gemfile +4 -0
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +3 -3
- 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 +41 -43
- data/lib/selenium/webdriver/atoms/findElements.js +52 -50
- data/lib/selenium/webdriver/atoms/getAttribute.js +6 -100
- data/lib/selenium/webdriver/atoms/isDisplayed.js +24 -96
- data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
- data/lib/selenium/webdriver/atoms.rb +5 -3
- data/lib/selenium/webdriver/bidi/browsing_context.rb +100 -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/{common/driver_extensions/has_location.rb → bidi/log/filter_by.rb} +14 -11
- 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_handler.rb +65 -0
- data/lib/selenium/webdriver/bidi/log_inspector.rb +147 -0
- data/lib/selenium/webdriver/bidi/network.rb +82 -0
- data/lib/selenium/webdriver/bidi/session.rb +51 -0
- data/lib/selenium/webdriver/bidi/struct.rb +42 -0
- data/lib/selenium/webdriver/bidi.rb +67 -0
- data/lib/selenium/webdriver/chrome/driver.rb +9 -29
- data/lib/selenium/webdriver/chrome/features.rb +9 -67
- 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 +5 -19
- data/lib/selenium/webdriver/chrome.rb +0 -16
- data/lib/selenium/webdriver/chromium/driver.rb +61 -0
- data/lib/selenium/webdriver/chromium/features.rb +99 -0
- data/lib/selenium/webdriver/chromium/options.rb +243 -0
- data/lib/selenium/webdriver/chromium/profile.rb +113 -0
- data/lib/selenium/webdriver/chromium.rb +29 -0
- data/lib/selenium/webdriver/common/action_builder.rb +60 -22
- data/lib/selenium/webdriver/common/child_process.rb +136 -0
- data/lib/selenium/webdriver/common/driver.rb +54 -89
- 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_fedcm_dialog.rb +55 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb +65 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +9 -3
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +8 -68
- 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 +97 -0
- data/lib/selenium/webdriver/common/element.rb +8 -8
- data/lib/selenium/webdriver/common/error.rb +29 -4
- data/lib/selenium/webdriver/common/fedcm/account.rb +49 -0
- data/lib/selenium/webdriver/common/fedcm/dialog.rb +74 -0
- data/lib/selenium/webdriver/common/fedcm.rb +27 -0
- 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 -71
- data/lib/selenium/webdriver/common/{driver_extensions/has_network_connection.rb → interactions/pointer_cancel.rb} +19 -11
- 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 +114 -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 +53 -0
- data/lib/selenium/webdriver/common/logger.rb +93 -28
- data/lib/selenium/webdriver/common/manager.rb +2 -29
- data/lib/selenium/webdriver/common/network.rb +64 -0
- data/lib/selenium/webdriver/common/options.rb +19 -19
- data/lib/selenium/webdriver/common/platform.rb +12 -52
- data/lib/selenium/webdriver/common/port_prober.rb +1 -1
- data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
- data/lib/selenium/webdriver/common/proxy.rb +4 -4
- data/lib/selenium/webdriver/common/script.rb +45 -0
- data/lib/selenium/webdriver/common/search_context.rb +10 -8
- data/lib/selenium/webdriver/common/selenium_manager.rb +104 -0
- data/lib/selenium/webdriver/common/service.rb +24 -26
- data/lib/selenium/webdriver/common/service_manager.rb +9 -15
- data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
- data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
- data/lib/selenium/webdriver/common/socket_poller.rb +3 -3
- data/lib/selenium/webdriver/common/takes_screenshot.rb +6 -5
- data/lib/selenium/webdriver/common/target_locator.rb +5 -5
- 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/wait.rb +1 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +176 -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 +27 -5
- 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 +8 -4
- data/lib/selenium/webdriver/edge/options.rb +17 -5
- data/lib/selenium/webdriver/edge/profile.rb +2 -2
- data/lib/selenium/webdriver/edge/service.rb +8 -7
- data/lib/selenium/webdriver/edge.rb +0 -2
- data/lib/selenium/webdriver/firefox/driver.rb +9 -2
- data/lib/selenium/webdriver/firefox/features.rb +11 -7
- data/lib/selenium/webdriver/firefox/options.rb +10 -16
- data/lib/selenium/webdriver/firefox/profile.rb +21 -17
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +1 -1
- data/lib/selenium/webdriver/firefox/service.rb +1 -18
- 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/features.rb +34 -0
- data/lib/selenium/webdriver/ie/options.rb +6 -4
- data/lib/selenium/webdriver/ie/service.rb +1 -22
- data/lib/selenium/webdriver/ie.rb +4 -17
- data/lib/selenium/webdriver/remote/bidi_bridge.rb +66 -0
- data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +22 -9
- data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
- data/lib/selenium/webdriver/remote/bridge.rb +158 -100
- data/lib/selenium/webdriver/remote/capabilities.rb +5 -55
- data/lib/selenium/webdriver/remote/driver.rb +35 -14
- data/lib/selenium/webdriver/remote/features.rb +75 -0
- data/lib/selenium/webdriver/remote/http/common.rb +26 -6
- data/lib/selenium/webdriver/remote/http/curb.rb +10 -6
- data/lib/selenium/webdriver/remote/http/default.rb +8 -14
- data/lib/selenium/webdriver/remote/response.rb +14 -22
- data/lib/selenium/webdriver/remote/server_error.rb +2 -2
- data/lib/selenium/webdriver/remote.rb +3 -2
- data/lib/selenium/webdriver/safari/driver.rb +7 -1
- data/lib/selenium/webdriver/safari/features.rb +5 -3
- data/lib/selenium/webdriver/safari/options.rb +5 -1
- data/lib/selenium/webdriver/safari/service.rb +10 -4
- data/lib/selenium/webdriver/safari.rb +1 -15
- data/lib/selenium/webdriver/support/color.rb +22 -22
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +14 -14
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
- data/lib/selenium/webdriver/support/guards.rb +4 -4
- 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 +7 -5
- data/selenium-webdriver.gemspec +22 -16
- metadata +137 -47
- 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
@@ -20,17 +20,18 @@
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
22
|
module Interactions
|
23
|
+
#
|
24
|
+
# Creates actions specific to Key Input devices
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
23
29
|
class KeyInput < InputDevice
|
24
30
|
SUBTYPES = {down: :keyDown, up: :keyUp, pause: :pause}.freeze
|
25
31
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def encode
|
31
|
-
return nil if no_actions?
|
32
|
-
|
33
|
-
{type: type, id: name, actions: @actions.map(&:encode)}
|
32
|
+
def initialize(name = nil)
|
33
|
+
super
|
34
|
+
@type = Interactions::KEY
|
34
35
|
end
|
35
36
|
|
36
37
|
def create_key_down(key)
|
@@ -41,25 +42,8 @@ module Selenium
|
|
41
42
|
add_action(TypingInteraction.new(self, :up, key))
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def initialize(source, type, key)
|
48
|
-
super(source)
|
49
|
-
@type = assert_type(type)
|
50
|
-
@key = Keys.encode_key(key)
|
51
|
-
end
|
52
|
-
|
53
|
-
def assert_type(type)
|
54
|
-
raise TypeError, "#{type.inspect} is not a valid key subtype" unless KeyInput::SUBTYPES.key? type
|
55
|
-
|
56
|
-
KeyInput::SUBTYPES[type]
|
57
|
-
end
|
58
|
-
|
59
|
-
def encode
|
60
|
-
{type: @type, value: @key}
|
61
|
-
end
|
62
|
-
end # TypingInteraction
|
45
|
+
# Backward compatibility in case anyone called this directly
|
46
|
+
class TypingInteraction < Interactions::TypingInteraction; end
|
63
47
|
end # KeyInput
|
64
48
|
end # Interactions
|
65
49
|
end # WebDriver
|
@@ -20,15 +20,17 @@
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
22
|
module Interactions
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
#
|
24
|
+
# Creates actions specific to null input source
|
25
|
+
# This is primarily used for adding pauses
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
class NoneInput < InputDevice
|
31
|
+
def initialize(name = nil)
|
32
|
+
super
|
33
|
+
@type = Interactions::NONE
|
32
34
|
end
|
33
35
|
end # NoneInput
|
34
36
|
end # Interactions
|
@@ -0,0 +1,49 @@
|
|
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
|
+
# Action to create a waiting period between actions
|
25
|
+
# Also used for synchronizing actions across devices
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
|
30
|
+
class Pause < Interaction
|
31
|
+
def initialize(source, duration = nil)
|
32
|
+
super(source)
|
33
|
+
@duration = duration
|
34
|
+
@type = :pause
|
35
|
+
end
|
36
|
+
|
37
|
+
def assert_source(source)
|
38
|
+
raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? InputDevice
|
39
|
+
end
|
40
|
+
|
41
|
+
def encode
|
42
|
+
output = {type: type}
|
43
|
+
output[:duration] = (@duration * 1000).to_i if @duration
|
44
|
+
output
|
45
|
+
end
|
46
|
+
end # Pause
|
47
|
+
end # Interactions
|
48
|
+
end # WebDriver
|
49
|
+
end # Selenium
|
@@ -23,11 +23,12 @@ module Selenium
|
|
23
23
|
attr_writer :default_move_duration
|
24
24
|
|
25
25
|
#
|
26
|
-
#
|
26
|
+
# By default this is set to 250ms in the ActionBuilder constructor
|
27
|
+
# It can be overridden with default_move_duration=
|
27
28
|
#
|
28
29
|
|
29
30
|
def default_move_duration
|
30
|
-
@default_move_duration ||= 0
|
31
|
+
@default_move_duration ||= @duration / 1000.0 # convert ms to seconds
|
31
32
|
end
|
32
33
|
|
33
34
|
#
|
@@ -45,8 +46,8 @@ module Selenium
|
|
45
46
|
# @return [ActionBuilder] A self reference.
|
46
47
|
#
|
47
48
|
|
48
|
-
def pointer_down(button, device: nil)
|
49
|
-
button_action(button,
|
49
|
+
def pointer_down(button = :left, device: nil, **opts)
|
50
|
+
button_action(button, :create_pointer_down, device: device, **opts)
|
50
51
|
end
|
51
52
|
|
52
53
|
#
|
@@ -62,21 +63,20 @@ module Selenium
|
|
62
63
|
# @return [ActionBuilder] A self reference.
|
63
64
|
#
|
64
65
|
|
65
|
-
def pointer_up(button, device: nil)
|
66
|
-
button_action(button,
|
66
|
+
def pointer_up(button = :left, device: nil, **opts)
|
67
|
+
button_action(button, :create_pointer_up, device: device, **opts)
|
67
68
|
end
|
68
69
|
|
69
70
|
#
|
70
|
-
# Moves the
|
71
|
-
#
|
72
|
-
# mouse is moved to optional offset coordinates from the element.
|
71
|
+
# Moves the pointer to the in-view center point of the given element.
|
72
|
+
# Then the pointer is moved to optional offset coordinates.
|
73
73
|
#
|
74
|
-
#
|
75
|
-
#
|
74
|
+
# The element is not scrolled into view.
|
75
|
+
# MoveTargetOutOfBoundsError will be raised if element with offset is outside the viewport
|
76
76
|
#
|
77
|
-
#
|
77
|
+
# When using offsets, both coordinates need to be passed.
|
78
78
|
#
|
79
|
-
# @example
|
79
|
+
# @example Move the pointer to element
|
80
80
|
#
|
81
81
|
# el = driver.find_element(id: "some_id")
|
82
82
|
# driver.action.move_to(el).perform
|
@@ -87,69 +87,59 @@ module Selenium
|
|
87
87
|
# driver.action.move_to(el, 100, 100).perform
|
88
88
|
#
|
89
89
|
# @param [Selenium::WebDriver::Element] element to move to.
|
90
|
-
# @param [Integer] right_by Optional offset from the
|
91
|
-
# coordinates to the left of the
|
92
|
-
# @param [Integer] down_by Optional offset from the
|
93
|
-
# coordinates
|
94
|
-
# @param [Symbol || String] device optional name of the PointerInput device to move.
|
90
|
+
# @param [Integer] right_by Optional offset from the in-view center of the
|
91
|
+
# element. A negative value means coordinates to the left of the center.
|
92
|
+
# @param [Integer] down_by Optional offset from the in-view center of the
|
93
|
+
# element. A negative value means coordinates to the top of the center.
|
95
94
|
# @return [ActionBuilder] A self reference.
|
96
95
|
#
|
97
96
|
|
98
|
-
def move_to(element, right_by = nil, down_by = nil,
|
99
|
-
pointer =
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
left = -left_offset + (right_by || 0)
|
106
|
-
top = -top_offset + (down_by || 0)
|
107
|
-
else
|
108
|
-
left = 0
|
109
|
-
top = 0
|
110
|
-
end
|
111
|
-
pointer.create_pointer_move(duration: default_move_duration,
|
112
|
-
x: left,
|
113
|
-
y: top,
|
114
|
-
element: element)
|
97
|
+
def move_to(element, right_by = nil, down_by = nil, **opts)
|
98
|
+
pointer = pointer_input(opts.delete(:device))
|
99
|
+
pointer.create_pointer_move(duration: opts.delete(:duration) || default_move_duration,
|
100
|
+
x: right_by || 0,
|
101
|
+
y: down_by || 0,
|
102
|
+
origin: element,
|
103
|
+
**opts)
|
115
104
|
tick(pointer)
|
116
105
|
self
|
117
106
|
end
|
118
107
|
|
119
108
|
#
|
120
|
-
# Moves the
|
121
|
-
# If the coordinates provided are outside the viewport (the mouse will
|
122
|
-
# end up outside the browser window) then the viewport is scrolled to
|
123
|
-
# match.
|
109
|
+
# Moves the pointer from its current position by the given offset.
|
124
110
|
#
|
125
|
-
#
|
111
|
+
# The viewport is not scrolled if the coordinates provided are outside the viewport.
|
112
|
+
# MoveTargetOutOfBoundsError will be raised if the offsets are outside the viewport
|
113
|
+
#
|
114
|
+
# @example Move the pointer to a certain offset from its current position
|
126
115
|
#
|
127
116
|
# driver.action.move_by(100, 100).perform
|
128
117
|
#
|
129
|
-
# @param [Integer] right_by horizontal offset. A negative value means moving the
|
130
|
-
# @param [Integer] down_by vertical offset. A negative value means moving the
|
118
|
+
# @param [Integer] right_by horizontal offset. A negative value means moving the pointer left.
|
119
|
+
# @param [Integer] down_by vertical offset. A negative value means moving the pointer up.
|
131
120
|
# @param [Symbol || String] device optional name of the PointerInput device to move
|
132
121
|
# @return [ActionBuilder] A self reference.
|
133
122
|
# @raise [MoveTargetOutOfBoundsError] if the provided offset is outside the document's boundaries.
|
134
123
|
#
|
135
124
|
|
136
|
-
def move_by(right_by, down_by, device: nil)
|
137
|
-
pointer =
|
138
|
-
pointer.create_pointer_move(duration:
|
125
|
+
def move_by(right_by, down_by, device: nil, duration: default_move_duration, **opts)
|
126
|
+
pointer = pointer_input(device)
|
127
|
+
pointer.create_pointer_move(duration: duration,
|
139
128
|
x: Integer(right_by),
|
140
129
|
y: Integer(down_by),
|
141
|
-
origin: Interactions::PointerMove::POINTER
|
130
|
+
origin: Interactions::PointerMove::POINTER,
|
131
|
+
**opts)
|
142
132
|
tick(pointer)
|
143
133
|
self
|
144
134
|
end
|
145
135
|
|
146
136
|
#
|
147
|
-
# Moves the
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
137
|
+
# Moves the pointer to a given location in the viewport.
|
138
|
+
#
|
139
|
+
# The viewport is not scrolled if the coordinates provided are outside the viewport.
|
140
|
+
# MoveTargetOutOfBoundsError will be raised if the offsets are outside the viewport
|
151
141
|
#
|
152
|
-
# @example Move the
|
142
|
+
# @example Move the pointer to a certain position in the viewport
|
153
143
|
#
|
154
144
|
# driver.action.move_to_location(100, 100).perform
|
155
145
|
#
|
@@ -160,12 +150,13 @@ module Selenium
|
|
160
150
|
# @raise [MoveTargetOutOfBoundsError] if the provided x or y value is outside the document's boundaries.
|
161
151
|
#
|
162
152
|
|
163
|
-
def move_to_location(x, y, device: nil)
|
164
|
-
pointer =
|
165
|
-
pointer.create_pointer_move(duration:
|
153
|
+
def move_to_location(x, y, device: nil, duration: default_move_duration, **opts)
|
154
|
+
pointer = pointer_input(device)
|
155
|
+
pointer.create_pointer_move(duration: duration,
|
166
156
|
x: Integer(x),
|
167
157
|
y: Integer(y),
|
168
|
-
origin: Interactions::PointerMove::VIEWPORT
|
158
|
+
origin: Interactions::PointerMove::VIEWPORT,
|
159
|
+
**opts)
|
169
160
|
tick(pointer)
|
170
161
|
self
|
171
162
|
end
|
@@ -186,9 +177,9 @@ module Selenium
|
|
186
177
|
# @return [ActionBuilder] A self reference.
|
187
178
|
#
|
188
179
|
|
189
|
-
def click_and_hold(element = nil, device: nil)
|
180
|
+
def click_and_hold(element = nil, button: nil, device: nil)
|
190
181
|
move_to(element, device: device) if element
|
191
|
-
pointer_down(:left, device: device)
|
182
|
+
pointer_down(button || :left, device: device)
|
192
183
|
self
|
193
184
|
end
|
194
185
|
|
@@ -205,8 +196,8 @@ module Selenium
|
|
205
196
|
# @return [ActionBuilder] A self reference.
|
206
197
|
#
|
207
198
|
|
208
|
-
def release(device: nil)
|
209
|
-
pointer_up(:left, device: device)
|
199
|
+
def release(button: nil, device: nil)
|
200
|
+
pointer_up(button || :left, device: device)
|
210
201
|
self
|
211
202
|
end
|
212
203
|
|
@@ -232,10 +223,10 @@ module Selenium
|
|
232
223
|
# @return [ActionBuilder] A self reference.
|
233
224
|
#
|
234
225
|
|
235
|
-
def click(element = nil, device: nil)
|
226
|
+
def click(element = nil, button: nil, device: nil)
|
236
227
|
move_to(element, device: device) if element
|
237
|
-
pointer_down(:left, device: device)
|
238
|
-
pointer_up(:left, device: device)
|
228
|
+
pointer_down(button || :left, device: device)
|
229
|
+
pointer_up(button || :left, device: device)
|
239
230
|
self
|
240
231
|
end
|
241
232
|
|
@@ -290,10 +281,7 @@ module Selenium
|
|
290
281
|
#
|
291
282
|
|
292
283
|
def context_click(element = nil, device: nil)
|
293
|
-
|
294
|
-
pointer_down(:right, device: device)
|
295
|
-
pointer_up(:right, device: device)
|
296
|
-
self
|
284
|
+
click(element, button: :right, device: device)
|
297
285
|
end
|
298
286
|
|
299
287
|
#
|
@@ -348,15 +336,15 @@ module Selenium
|
|
348
336
|
|
349
337
|
private
|
350
338
|
|
351
|
-
def button_action(button, action
|
352
|
-
pointer =
|
353
|
-
pointer.send(action, button)
|
339
|
+
def button_action(button, action, device: nil, **opts)
|
340
|
+
pointer = pointer_input(device)
|
341
|
+
pointer.send(action, button, **opts)
|
354
342
|
tick(pointer)
|
355
343
|
self
|
356
344
|
end
|
357
345
|
|
358
|
-
def
|
359
|
-
|
346
|
+
def pointer_input(name = nil)
|
347
|
+
device(name: name, type: Interactions::POINTER) || add_pointer_input(:mouse, 'mouse')
|
360
348
|
end
|
361
349
|
end # PointerActions
|
362
350
|
end # WebDriver
|
@@ -17,21 +17,29 @@
|
|
17
17
|
# specific language governing permissions and limitations
|
18
18
|
# under the License.
|
19
19
|
|
20
|
-
# TODO: Deprecated; Delete after 4.0 release
|
21
20
|
module Selenium
|
22
21
|
module WebDriver
|
23
|
-
module
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
module Interactions
|
23
|
+
#
|
24
|
+
# Action to cancel any other Pointer Action.
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
29
|
+
class PointerCancel < Interaction
|
30
|
+
def initialize(source)
|
31
|
+
super
|
32
|
+
@type = :pointerCancel
|
33
|
+
end
|
34
|
+
|
35
|
+
def assert_source(source)
|
36
|
+
raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? PointerInput
|
28
37
|
end
|
29
38
|
|
30
|
-
def
|
31
|
-
|
32
|
-
'The W3C standard does not currently support setting network connection'
|
39
|
+
def encode
|
40
|
+
{type: type}
|
33
41
|
end
|
34
|
-
end #
|
35
|
-
end #
|
42
|
+
end # PointerCancel
|
43
|
+
end # Interactions
|
36
44
|
end # WebDriver
|
37
45
|
end # Selenium
|
@@ -0,0 +1,63 @@
|
|
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
|
+
module PointerEventProperties
|
24
|
+
VALID = {width: {'width' => {min: 0.0}},
|
25
|
+
height: {'height' => {min: 0.0}},
|
26
|
+
pressure: {'pressure' => {min: 0.0, max: 1.0}},
|
27
|
+
tangential_pressure: {'tangentialPressure' => {min: -1.0, max: 1.0}},
|
28
|
+
tilt_x: {'tiltX' => {min: -90, max: 90}},
|
29
|
+
tilt_y: {'tiltY' => {min: -90, max: 90}},
|
30
|
+
twist: {'twist' => {min: 0, max: 359}},
|
31
|
+
altitude_angle: {'altitudeAngle' => {min: 0.0, max: (Math::PI / 2)}},
|
32
|
+
azimuth_angle: {'azimuthAngle' => {min: 0.0, max: (Math::PI * 2)}}}.freeze
|
33
|
+
|
34
|
+
def process_opts
|
35
|
+
raise ArgumentError, "Unknown options found: #{@opts.inspect}" unless (@opts.keys - VALID.keys).empty?
|
36
|
+
|
37
|
+
VALID.each_with_object({}) do |(key, val), hash|
|
38
|
+
next unless @opts.key?(key)
|
39
|
+
|
40
|
+
name = val.keys.first
|
41
|
+
values = val.values.first
|
42
|
+
hash[name] = assert_number(@opts[key], values[:min], values[:max])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def assert_number(num, min, max = nil)
|
49
|
+
return if num.nil?
|
50
|
+
|
51
|
+
klass = min.is_a?(Integer) ? Integer : Numeric
|
52
|
+
raise TypeError, "#{num} is not a #{klass}" unless num.is_a?(klass)
|
53
|
+
|
54
|
+
raise ArgumentError, "#{num} is not greater than or equal to #{min}" if num < min
|
55
|
+
|
56
|
+
raise ArgumentError, "#{num} is not less than or equal to #{max}" if max && num > max
|
57
|
+
|
58
|
+
num
|
59
|
+
end
|
60
|
+
end # PointerEventProperties
|
61
|
+
end # Interactions
|
62
|
+
end # WebDriver
|
63
|
+
end # Selenium
|
@@ -20,6 +20,12 @@
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
22
|
module Interactions
|
23
|
+
#
|
24
|
+
# Creates actions specific to Pointer Input devices
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
23
29
|
class PointerInput < InputDevice
|
24
30
|
KIND = {mouse: :mouse, pen: :pen, touch: :touch}.freeze
|
25
31
|
|
@@ -28,17 +34,12 @@ module Selenium
|
|
28
34
|
def initialize(kind, name: nil)
|
29
35
|
super(name)
|
30
36
|
@kind = assert_kind(kind)
|
31
|
-
|
32
|
-
|
33
|
-
def type
|
34
|
-
Interactions::POINTER
|
37
|
+
@type = Interactions::POINTER
|
35
38
|
end
|
36
39
|
|
37
40
|
def encode
|
38
|
-
|
39
|
-
|
40
|
-
output = {type: type, id: name, actions: @actions.map(&:encode)}
|
41
|
-
output[:parameters] = {pointerType: kind}
|
41
|
+
output = super
|
42
|
+
output[:parameters] = {pointerType: kind} if output
|
42
43
|
output
|
43
44
|
end
|
44
45
|
|
@@ -48,92 +49,22 @@ module Selenium
|
|
48
49
|
KIND[pointer]
|
49
50
|
end
|
50
51
|
|
51
|
-
def create_pointer_move(duration: 0, x: 0, y: 0,
|
52
|
-
add_action(PointerMove.new(self, duration, x, y,
|
52
|
+
def create_pointer_move(duration: 0, x: 0, y: 0, origin: nil, **opts)
|
53
|
+
add_action(PointerMove.new(self, duration, x, y, origin: origin, **opts))
|
53
54
|
end
|
54
55
|
|
55
|
-
def create_pointer_down(button)
|
56
|
-
add_action(PointerPress.new(self, :down, button))
|
56
|
+
def create_pointer_down(button, **opts)
|
57
|
+
add_action(PointerPress.new(self, :down, button, **opts))
|
57
58
|
end
|
58
59
|
|
59
|
-
def create_pointer_up(button)
|
60
|
-
add_action(PointerPress.new(self, :up, button))
|
60
|
+
def create_pointer_up(button, **opts)
|
61
|
+
add_action(PointerPress.new(self, :up, button, **opts))
|
61
62
|
end
|
62
63
|
|
63
64
|
def create_pointer_cancel
|
64
65
|
add_action(PointerCancel.new(self))
|
65
66
|
end
|
66
67
|
end # PointerInput
|
67
|
-
|
68
|
-
class PointerPress < Interaction
|
69
|
-
BUTTONS = {left: 0, middle: 1, right: 2}.freeze
|
70
|
-
DIRECTIONS = {down: :pointerDown, up: :pointerUp}.freeze
|
71
|
-
|
72
|
-
def initialize(source, direction, button)
|
73
|
-
super(source)
|
74
|
-
@direction = assert_direction(direction)
|
75
|
-
@button = assert_button(button)
|
76
|
-
end
|
77
|
-
|
78
|
-
def type
|
79
|
-
@direction
|
80
|
-
end
|
81
|
-
|
82
|
-
def assert_button(button)
|
83
|
-
if button.is_a? Symbol
|
84
|
-
raise TypeError, "#{button.inspect} is not a valid button!" unless BUTTONS.key? button
|
85
|
-
|
86
|
-
button = BUTTONS[button]
|
87
|
-
end
|
88
|
-
raise ArgumentError, 'Button number cannot be negative!' unless button >= 0
|
89
|
-
|
90
|
-
button
|
91
|
-
end
|
92
|
-
|
93
|
-
def assert_direction(direction)
|
94
|
-
raise TypeError, "#{direction.inspect} is not a valid button direction" unless DIRECTIONS.key? direction
|
95
|
-
|
96
|
-
DIRECTIONS[direction]
|
97
|
-
end
|
98
|
-
|
99
|
-
def encode
|
100
|
-
{type: type, button: @button}
|
101
|
-
end
|
102
|
-
end # PointerPress
|
103
|
-
|
104
|
-
class PointerMove < Interaction
|
105
|
-
VIEWPORT = :viewport
|
106
|
-
POINTER = :pointer
|
107
|
-
ORIGINS = [VIEWPORT, POINTER].freeze
|
108
|
-
|
109
|
-
def initialize(source, duration, x, y, element: nil, origin: nil)
|
110
|
-
super(source)
|
111
|
-
@duration = duration * 1000
|
112
|
-
@x_offset = x
|
113
|
-
@y_offset = y
|
114
|
-
@origin = element || origin
|
115
|
-
end
|
116
|
-
|
117
|
-
def type
|
118
|
-
:pointerMove
|
119
|
-
end
|
120
|
-
|
121
|
-
def encode
|
122
|
-
output = {type: type, duration: @duration.to_i, x: @x_offset, y: @y_offset}
|
123
|
-
output[:origin] = @origin
|
124
|
-
output
|
125
|
-
end
|
126
|
-
end # Move
|
127
|
-
|
128
|
-
class PointerCancel < Interaction
|
129
|
-
def type
|
130
|
-
:pointerCancel
|
131
|
-
end
|
132
|
-
|
133
|
-
def encode
|
134
|
-
{type: type}
|
135
|
-
end
|
136
|
-
end # Cancel
|
137
68
|
end # Interactions
|
138
69
|
end # WebDriver
|
139
70
|
end # Selenium
|
@@ -0,0 +1,60 @@
|
|
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
|
+
# Action related to moving the pointer.
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
29
|
+
class PointerMove < Interaction
|
30
|
+
include PointerEventProperties
|
31
|
+
|
32
|
+
VIEWPORT = :viewport
|
33
|
+
POINTER = :pointer
|
34
|
+
ORIGINS = [VIEWPORT, POINTER].freeze
|
35
|
+
|
36
|
+
def initialize(source, duration, x, y, **opts)
|
37
|
+
super(source)
|
38
|
+
@duration = duration * 1000
|
39
|
+
@x_offset = x
|
40
|
+
@y_offset = y
|
41
|
+
@origin = opts.delete(:element) || opts.delete(:origin) || :viewport
|
42
|
+
@type = :pointerMove
|
43
|
+
@opts = opts
|
44
|
+
end
|
45
|
+
|
46
|
+
def assert_source(source)
|
47
|
+
raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? PointerInput
|
48
|
+
end
|
49
|
+
|
50
|
+
def encode
|
51
|
+
process_opts.merge('type' => type.to_s,
|
52
|
+
'duration' => @duration.to_i,
|
53
|
+
'x' => @x_offset,
|
54
|
+
'y' => @y_offset,
|
55
|
+
'origin' => @origin)
|
56
|
+
end
|
57
|
+
end # PointerMove
|
58
|
+
end # Interactions
|
59
|
+
end # WebDriver
|
60
|
+
end # Selenium
|