selenium-webdriver 4.1.0 → 4.2.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 +46 -1
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/lib/selenium/server.rb +14 -9
- data/lib/selenium/webdriver/bidi/session.rb +38 -0
- data/lib/selenium/webdriver/bidi.rb +55 -0
- data/lib/selenium/webdriver/chrome/features.rb +5 -0
- data/lib/selenium/webdriver/chrome/options.rb +19 -19
- data/lib/selenium/webdriver/common/action_builder.rb +108 -21
- data/lib/selenium/webdriver/common/driver.rb +2 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -1
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -1
- data/lib/selenium/webdriver/common/element.rb +1 -1
- data/lib/selenium/webdriver/common/error.rb +1 -1
- 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 +49 -43
- 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 +57 -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/platform.rb +4 -4
- data/lib/selenium/webdriver/common/search_context.rb +0 -6
- data/lib/selenium/webdriver/common/service_manager.rb +2 -3
- data/lib/selenium/webdriver/common/shadow_root.rb +1 -1
- data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +149 -0
- data/lib/selenium/webdriver/common.rb +14 -2
- data/lib/selenium/webdriver/devtools/request.rb +1 -1
- data/lib/selenium/webdriver/devtools/response.rb +1 -1
- data/lib/selenium/webdriver/devtools.rb +5 -112
- data/lib/selenium/webdriver/edge/features.rb +1 -0
- data/lib/selenium/webdriver/firefox/driver.rb +1 -0
- data/lib/selenium/webdriver/firefox/features.rb +2 -5
- data/lib/selenium/webdriver/firefox/options.rb +3 -1
- data/lib/selenium/webdriver/firefox/profile.rb +1 -5
- data/lib/selenium/webdriver/firefox/util.rb +46 -0
- data/lib/selenium/webdriver/firefox.rb +1 -0
- data/lib/selenium/webdriver/remote/bridge.rb +21 -19
- data/lib/selenium/webdriver/remote/commands.rb +0 -5
- data/lib/selenium/webdriver/remote/http/default.rb +6 -12
- data/lib/selenium/webdriver/remote/response.rb +2 -2
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +4 -4
- data/lib/selenium/webdriver/support/color.rb +7 -7
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -1
- data/lib/selenium/webdriver/support/guards.rb +1 -1
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +1 -0
- data/selenium-webdriver.gemspec +7 -4
- metadata +55 -5
@@ -22,8 +22,15 @@ require 'securerandom'
|
|
22
22
|
module Selenium
|
23
23
|
module WebDriver
|
24
24
|
module Interactions
|
25
|
+
#
|
26
|
+
# Superclass for the input device sources
|
27
|
+
# Manages Array of Interaction instances for the device
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
#
|
31
|
+
|
25
32
|
class InputDevice
|
26
|
-
attr_reader :name, :actions
|
33
|
+
attr_reader :name, :actions, :type
|
27
34
|
|
28
35
|
def initialize(name = nil)
|
29
36
|
@name = name || SecureRandom.uuid
|
@@ -44,9 +51,8 @@ module Selenium
|
|
44
51
|
add_action(Pause.new(self, duration))
|
45
52
|
end
|
46
53
|
|
47
|
-
def
|
48
|
-
actions
|
49
|
-
actions.empty?
|
54
|
+
def encode
|
55
|
+
{type: type, id: name, actions: @actions.map(&:encode)} unless @actions.empty?
|
50
56
|
end
|
51
57
|
end # InputDevice
|
52
58
|
end # Interactions
|
@@ -20,37 +20,24 @@
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
22
|
module Interactions
|
23
|
-
|
24
|
-
|
23
|
+
#
|
24
|
+
# Superclass for classes defining actions
|
25
|
+
# Do not initialize directly, only use subclass
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
25
29
|
|
26
|
-
|
30
|
+
class Interaction
|
31
|
+
attr_reader :type
|
27
32
|
|
28
33
|
def initialize(source)
|
29
|
-
|
30
|
-
raise TypeError,
|
31
|
-
"#{source.type} is not a valid input type"
|
32
|
-
end
|
33
|
-
|
34
|
-
@source = source
|
34
|
+
assert_source(source)
|
35
35
|
end
|
36
|
-
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
super(source)
|
41
|
-
@duration = duration
|
37
|
+
def assert_source(_source)
|
38
|
+
raise NotImplementedError, 'subclass responsibility'
|
42
39
|
end
|
43
|
-
|
44
|
-
def type
|
45
|
-
PAUSE
|
46
|
-
end
|
47
|
-
|
48
|
-
def encode
|
49
|
-
output = {type: type}
|
50
|
-
output[:duration] = (@duration * 1000).to_i if @duration
|
51
|
-
output
|
52
|
-
end
|
53
|
-
end # Interaction
|
40
|
+
end
|
54
41
|
end # Interactions
|
55
42
|
end # WebDriver
|
56
43
|
end # Selenium
|
@@ -23,20 +23,40 @@ module Selenium
|
|
23
23
|
KEY = :key
|
24
24
|
POINTER = :pointer
|
25
25
|
NONE = :none
|
26
|
-
|
26
|
+
WHEEL = :wheel
|
27
|
+
|
28
|
+
#
|
29
|
+
# Class methods for initializing known Input devices
|
30
|
+
#
|
27
31
|
|
28
32
|
class << self
|
29
|
-
def key(name)
|
33
|
+
def key(name = nil)
|
30
34
|
KeyInput.new(name)
|
31
35
|
end
|
32
36
|
|
33
|
-
def pointer(kind,
|
34
|
-
PointerInput.new(kind,
|
37
|
+
def pointer(kind = :mouse, name: nil)
|
38
|
+
PointerInput.new(kind, name: name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def mouse(name: nil)
|
42
|
+
pointer(name: name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def pen(name: nil)
|
46
|
+
pointer(:pen, name: name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def touch(name: nil)
|
50
|
+
pointer(:touch, name: name)
|
35
51
|
end
|
36
52
|
|
37
53
|
def none(name = nil)
|
38
54
|
NoneInput.new(name)
|
39
55
|
end
|
56
|
+
|
57
|
+
def wheel(name = nil)
|
58
|
+
WheelInput.new(name)
|
59
|
+
end
|
40
60
|
end
|
41
61
|
end # Interactions
|
42
62
|
end # WebDriver
|
@@ -134,12 +134,16 @@ module Selenium
|
|
134
134
|
#
|
135
135
|
|
136
136
|
def key_action(*args, action: nil, device: nil)
|
137
|
-
key_input =
|
137
|
+
key_input = key_input(device)
|
138
138
|
click(args.shift) if args.first.is_a? Element
|
139
139
|
key_input.send(action, args.last)
|
140
140
|
tick(key_input)
|
141
141
|
self
|
142
142
|
end
|
143
|
+
|
144
|
+
def key_input(name = nil)
|
145
|
+
device(name: name, type: Interactions::KEY) || add_key_input('keyboard')
|
146
|
+
end
|
143
147
|
end # KeyActions
|
144
148
|
end # WebDriver
|
145
149
|
end # Selenium
|
@@ -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 ||=
|
31
|
+
@default_move_duration ||= @duration / 1000 # 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,21 @@ 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
|
-
#
|
71
|
+
# Moves the pointer to the middle of the given element.
|
72
|
+
# its location is calculated using getBoundingClientRect.
|
73
|
+
# Then the pointer is moved to optional offset coordinates from the element.
|
73
74
|
#
|
74
|
-
#
|
75
|
-
#
|
75
|
+
# The element is not scrolled into view.
|
76
|
+
# MoveTargetOutOfBoundsError will be raised if element with offset is outside the viewport
|
76
77
|
#
|
77
|
-
#
|
78
|
+
# When using offsets, both coordinates need to be passed.
|
78
79
|
#
|
79
|
-
# @example
|
80
|
+
# @example Move the pointer to element
|
80
81
|
#
|
81
82
|
# el = driver.find_element(id: "some_id")
|
82
83
|
# driver.action.move_to(el).perform
|
@@ -95,10 +96,12 @@ module Selenium
|
|
95
96
|
# @return [ActionBuilder] A self reference.
|
96
97
|
#
|
97
98
|
|
98
|
-
def move_to(element, right_by = nil, down_by = nil, device: nil)
|
99
|
-
pointer =
|
100
|
-
# New actions offset is from center of element
|
99
|
+
def move_to(element, right_by = nil, down_by = nil, device: nil, duration: default_move_duration, **opts)
|
100
|
+
pointer = pointer_input(device)
|
101
101
|
if right_by || down_by
|
102
|
+
WebDriver.logger.warn("moving to an element with offset currently tries to use
|
103
|
+
the top left corner of the element as the origin; in Selenium 4.3 it will use the in-view
|
104
|
+
center point of the element as the origin.")
|
102
105
|
size = element.size
|
103
106
|
left_offset = (size[:width] / 2).to_i
|
104
107
|
top_offset = (size[:height] / 2).to_i
|
@@ -108,48 +111,50 @@ module Selenium
|
|
108
111
|
left = 0
|
109
112
|
top = 0
|
110
113
|
end
|
111
|
-
pointer.create_pointer_move(duration:
|
114
|
+
pointer.create_pointer_move(duration: duration,
|
112
115
|
x: left,
|
113
116
|
y: top,
|
114
|
-
|
117
|
+
origin: element,
|
118
|
+
**opts)
|
115
119
|
tick(pointer)
|
116
120
|
self
|
117
121
|
end
|
118
122
|
|
119
123
|
#
|
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.
|
124
|
+
# Moves the pointer from its current position by the given offset.
|
124
125
|
#
|
125
|
-
#
|
126
|
+
# The viewport is not scrolled if the coordinates provided are outside the viewport.
|
127
|
+
# MoveTargetOutOfBoundsError will be raised if the offsets are outside the viewport
|
128
|
+
#
|
129
|
+
# @example Move the pointer to a certain offset from its current position
|
126
130
|
#
|
127
131
|
# driver.action.move_by(100, 100).perform
|
128
132
|
#
|
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
|
133
|
+
# @param [Integer] right_by horizontal offset. A negative value means moving the pointer left.
|
134
|
+
# @param [Integer] down_by vertical offset. A negative value means moving the pointer up.
|
131
135
|
# @param [Symbol || String] device optional name of the PointerInput device to move
|
132
136
|
# @return [ActionBuilder] A self reference.
|
133
137
|
# @raise [MoveTargetOutOfBoundsError] if the provided offset is outside the document's boundaries.
|
134
138
|
#
|
135
139
|
|
136
|
-
def move_by(right_by, down_by, device: nil)
|
137
|
-
pointer =
|
138
|
-
pointer.create_pointer_move(duration:
|
140
|
+
def move_by(right_by, down_by, device: nil, duration: default_move_duration, **opts)
|
141
|
+
pointer = pointer_input(device)
|
142
|
+
pointer.create_pointer_move(duration: duration,
|
139
143
|
x: Integer(right_by),
|
140
144
|
y: Integer(down_by),
|
141
|
-
origin: Interactions::PointerMove::POINTER
|
145
|
+
origin: Interactions::PointerMove::POINTER,
|
146
|
+
**opts)
|
142
147
|
tick(pointer)
|
143
148
|
self
|
144
149
|
end
|
145
150
|
|
146
151
|
#
|
147
|
-
# Moves the
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
152
|
+
# Moves the pointer to a given location in the viewport.
|
153
|
+
#
|
154
|
+
# The viewport is not scrolled if the coordinates provided are outside the viewport.
|
155
|
+
# MoveTargetOutOfBoundsError will be raised if the offsets are outside the viewport
|
151
156
|
#
|
152
|
-
# @example Move the
|
157
|
+
# @example Move the pointer to a certain position in the viewport
|
153
158
|
#
|
154
159
|
# driver.action.move_to_location(100, 100).perform
|
155
160
|
#
|
@@ -160,12 +165,13 @@ module Selenium
|
|
160
165
|
# @raise [MoveTargetOutOfBoundsError] if the provided x or y value is outside the document's boundaries.
|
161
166
|
#
|
162
167
|
|
163
|
-
def move_to_location(x, y, device: nil)
|
164
|
-
pointer =
|
165
|
-
pointer.create_pointer_move(duration:
|
168
|
+
def move_to_location(x, y, device: nil, duration: default_move_duration, **opts)
|
169
|
+
pointer = pointer_input(device)
|
170
|
+
pointer.create_pointer_move(duration: duration,
|
166
171
|
x: Integer(x),
|
167
172
|
y: Integer(y),
|
168
|
-
origin: Interactions::PointerMove::VIEWPORT
|
173
|
+
origin: Interactions::PointerMove::VIEWPORT,
|
174
|
+
**opts)
|
169
175
|
tick(pointer)
|
170
176
|
self
|
171
177
|
end
|
@@ -348,15 +354,15 @@ module Selenium
|
|
348
354
|
|
349
355
|
private
|
350
356
|
|
351
|
-
def button_action(button, action
|
352
|
-
pointer =
|
353
|
-
pointer.send(action, button)
|
357
|
+
def button_action(button, action, device: nil, **opts)
|
358
|
+
pointer = pointer_input(device)
|
359
|
+
pointer.send(action, button, **opts)
|
354
360
|
tick(pointer)
|
355
361
|
self
|
356
362
|
end
|
357
363
|
|
358
|
-
def
|
359
|
-
|
364
|
+
def pointer_input(name = nil)
|
365
|
+
device(name: name, type: Interactions::POINTER) || add_pointer_input(:mouse, 'mouse')
|
360
366
|
end
|
361
367
|
end # PointerActions
|
362
368
|
end # WebDriver
|
@@ -0,0 +1,45 @@
|
|
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 cancel any other Pointer Action.
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
|
29
|
+
class PointerCancel < Interaction
|
30
|
+
def initialize(source)
|
31
|
+
super(source)
|
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
|
37
|
+
end
|
38
|
+
|
39
|
+
def encode
|
40
|
+
{type: type}
|
41
|
+
end
|
42
|
+
end # PointerCancel
|
43
|
+
end # Interactions
|
44
|
+
end # WebDriver
|
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
|