selenium-webdriver 4.1.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +85 -1
  3. data/LICENSE +1 -1
  4. data/NOTICE +1 -1
  5. data/lib/selenium/server.rb +15 -10
  6. data/lib/selenium/webdriver/bidi/session.rb +38 -0
  7. data/lib/selenium/webdriver/bidi.rb +55 -0
  8. data/lib/selenium/webdriver/chrome/features.rb +5 -0
  9. data/lib/selenium/webdriver/chrome/options.rb +33 -19
  10. data/lib/selenium/webdriver/chrome.rb +0 -14
  11. data/lib/selenium/webdriver/common/action_builder.rb +108 -21
  12. data/lib/selenium/webdriver/common/driver.rb +22 -55
  13. data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +12 -5
  14. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -0
  15. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -2
  16. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -1
  17. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -67
  18. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -1
  19. data/lib/selenium/webdriver/common/element.rb +1 -1
  20. data/lib/selenium/webdriver/common/error.rb +1 -1
  21. data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
  22. data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
  23. data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
  24. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
  25. data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
  26. data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
  27. data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
  28. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
  29. data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
  30. data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
  31. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
  32. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
  33. data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
  34. data/lib/selenium/webdriver/common/interactions/scroll.rb +57 -0
  35. data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
  36. data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
  37. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
  38. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
  39. data/lib/selenium/webdriver/common/keys.rb +1 -0
  40. data/lib/selenium/webdriver/common/manager.rb +0 -27
  41. data/lib/selenium/webdriver/common/options.rb +2 -9
  42. data/lib/selenium/webdriver/common/platform.rb +4 -4
  43. data/lib/selenium/webdriver/common/search_context.rb +0 -6
  44. data/lib/selenium/webdriver/common/service_manager.rb +2 -3
  45. data/lib/selenium/webdriver/common/shadow_root.rb +1 -1
  46. data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
  47. data/lib/selenium/webdriver/common/takes_screenshot.rb +1 -1
  48. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +83 -0
  49. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +73 -0
  50. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  51. data/lib/selenium/webdriver/common/websocket_connection.rb +156 -0
  52. data/lib/selenium/webdriver/common/window.rb +6 -6
  53. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  54. data/lib/selenium/webdriver/common.rb +17 -3
  55. data/lib/selenium/webdriver/devtools/network_interceptor.rb +176 -0
  56. data/lib/selenium/webdriver/devtools/request.rb +1 -1
  57. data/lib/selenium/webdriver/devtools/response.rb +1 -1
  58. data/lib/selenium/webdriver/devtools.rb +6 -112
  59. data/lib/selenium/webdriver/edge/features.rb +1 -0
  60. data/lib/selenium/webdriver/firefox/driver.rb +1 -0
  61. data/lib/selenium/webdriver/firefox/features.rb +2 -5
  62. data/lib/selenium/webdriver/firefox/options.rb +3 -1
  63. data/lib/selenium/webdriver/firefox/profile.rb +1 -5
  64. data/lib/selenium/webdriver/firefox/util.rb +46 -0
  65. data/lib/selenium/webdriver/firefox.rb +1 -14
  66. data/lib/selenium/webdriver/ie.rb +0 -14
  67. data/lib/selenium/webdriver/remote/bridge.rb +54 -19
  68. data/lib/selenium/webdriver/remote/commands.rb +15 -6
  69. data/lib/selenium/webdriver/remote/driver.rb +0 -1
  70. data/lib/selenium/webdriver/remote/http/default.rb +6 -12
  71. data/lib/selenium/webdriver/remote/response.rb +2 -2
  72. data/lib/selenium/webdriver/safari.rb +0 -14
  73. data/lib/selenium/webdriver/support/cdp_client_generator.rb +4 -4
  74. data/lib/selenium/webdriver/support/color.rb +7 -7
  75. data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -1
  76. data/lib/selenium/webdriver/support/guards.rb +1 -1
  77. data/lib/selenium/webdriver/version.rb +1 -1
  78. data/lib/selenium/webdriver.rb +1 -0
  79. data/selenium-webdriver.gemspec +9 -6
  80. metadata +64 -12
  81. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
@@ -23,11 +23,12 @@ module Selenium
23
23
  attr_writer :default_move_duration
24
24
 
25
25
  #
26
- # The overridable duration for movement used by methods in this module
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.25 # 250 milliseconds
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, action: :create_pointer_down, device: device)
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, action: :create_pointer_up, device: device)
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 mouse to the middle of the given element. The element is scrolled into
71
- # view and its location is calculated using getBoundingClientRect. Then the
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
- # This is adapted to be backward compatible from non- actions. calculates offset from the center point
75
- # of the element
74
+ # The element is not scrolled into view.
75
+ # MoveTargetOutOfBoundsError will be raised if element with offset is outside the viewport
76
76
  #
77
- # Note that when using offsets, both coordinates need to be passed.
77
+ # When using offsets, both coordinates need to be passed.
78
78
  #
79
- # @example Scroll element into view and move the mouse to it
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,60 @@ 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 top-left corner. A negative value means
91
- # coordinates to the left of the element.
92
- # @param [Integer] down_by Optional offset from the top-left corner. A negative value means
93
- # coordinates above the element.
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.
94
94
  # @param [Symbol || String] device optional name of the PointerInput device to move.
95
95
  # @return [ActionBuilder] A self reference.
96
96
  #
97
97
 
98
- def move_to(element, right_by = nil, down_by = nil, device: nil)
99
- pointer = get_pointer(device)
100
- # New actions offset is from center of element
101
- if right_by || down_by
102
- size = element.size
103
- left_offset = (size[:width] / 2).to_i
104
- top_offset = (size[:height] / 2).to_i
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)
98
+ def move_to(element, right_by = nil, down_by = nil, device: nil, duration: default_move_duration, **opts)
99
+ pointer = pointer_input(device)
100
+ pointer.create_pointer_move(duration: duration,
101
+ x: right_by || 0,
102
+ y: down_by || 0,
103
+ origin: element,
104
+ **opts)
115
105
  tick(pointer)
116
106
  self
117
107
  end
118
108
 
119
109
  #
120
- # Moves the mouse from its current position by the given offset.
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.
110
+ # Moves the pointer from its current position by the given offset.
124
111
  #
125
- # @example Move the mouse to a certain offset from its current position
112
+ # The viewport is not scrolled if the coordinates provided are outside the viewport.
113
+ # MoveTargetOutOfBoundsError will be raised if the offsets are outside the viewport
114
+ #
115
+ # @example Move the pointer to a certain offset from its current position
126
116
  #
127
117
  # driver.action.move_by(100, 100).perform
128
118
  #
129
- # @param [Integer] right_by horizontal offset. A negative value means moving the mouse left.
130
- # @param [Integer] down_by vertical offset. A negative value means moving the mouse up.
119
+ # @param [Integer] right_by horizontal offset. A negative value means moving the pointer left.
120
+ # @param [Integer] down_by vertical offset. A negative value means moving the pointer up.
131
121
  # @param [Symbol || String] device optional name of the PointerInput device to move
132
122
  # @return [ActionBuilder] A self reference.
133
123
  # @raise [MoveTargetOutOfBoundsError] if the provided offset is outside the document's boundaries.
134
124
  #
135
125
 
136
- def move_by(right_by, down_by, device: nil)
137
- pointer = get_pointer(device)
138
- pointer.create_pointer_move(duration: default_move_duration,
126
+ def move_by(right_by, down_by, device: nil, duration: default_move_duration, **opts)
127
+ pointer = pointer_input(device)
128
+ pointer.create_pointer_move(duration: duration,
139
129
  x: Integer(right_by),
140
130
  y: Integer(down_by),
141
- origin: Interactions::PointerMove::POINTER)
131
+ origin: Interactions::PointerMove::POINTER,
132
+ **opts)
142
133
  tick(pointer)
143
134
  self
144
135
  end
145
136
 
146
137
  #
147
- # Moves the mouse to a given location in the viewport.
148
- # If the coordinates provided are outside the viewport (the mouse will
149
- # end up outside the browser window) then the viewport is scrolled to
150
- # match.
138
+ # Moves the pointer to a given location in the viewport.
139
+ #
140
+ # The viewport is not scrolled if the coordinates provided are outside the viewport.
141
+ # MoveTargetOutOfBoundsError will be raised if the offsets are outside the viewport
151
142
  #
152
- # @example Move the mouse to a certain position in the viewport
143
+ # @example Move the pointer to a certain position in the viewport
153
144
  #
154
145
  # driver.action.move_to_location(100, 100).perform
155
146
  #
@@ -160,12 +151,13 @@ module Selenium
160
151
  # @raise [MoveTargetOutOfBoundsError] if the provided x or y value is outside the document's boundaries.
161
152
  #
162
153
 
163
- def move_to_location(x, y, device: nil)
164
- pointer = get_pointer(device)
165
- pointer.create_pointer_move(duration: default_move_duration,
154
+ def move_to_location(x, y, device: nil, duration: default_move_duration, **opts)
155
+ pointer = pointer_input(device)
156
+ pointer.create_pointer_move(duration: duration,
166
157
  x: Integer(x),
167
158
  y: Integer(y),
168
- origin: Interactions::PointerMove::VIEWPORT)
159
+ origin: Interactions::PointerMove::VIEWPORT,
160
+ **opts)
169
161
  tick(pointer)
170
162
  self
171
163
  end
@@ -186,9 +178,9 @@ module Selenium
186
178
  # @return [ActionBuilder] A self reference.
187
179
  #
188
180
 
189
- def click_and_hold(element = nil, device: nil)
181
+ def click_and_hold(element = nil, button: nil, device: nil)
190
182
  move_to(element, device: device) if element
191
- pointer_down(:left, device: device)
183
+ pointer_down(button || :left, device: device)
192
184
  self
193
185
  end
194
186
 
@@ -205,8 +197,8 @@ module Selenium
205
197
  # @return [ActionBuilder] A self reference.
206
198
  #
207
199
 
208
- def release(device: nil)
209
- pointer_up(:left, device: device)
200
+ def release(button: nil, device: nil)
201
+ pointer_up(button || :left, device: device)
210
202
  self
211
203
  end
212
204
 
@@ -232,10 +224,10 @@ module Selenium
232
224
  # @return [ActionBuilder] A self reference.
233
225
  #
234
226
 
235
- def click(element = nil, device: nil)
227
+ def click(element = nil, button: nil, device: nil)
236
228
  move_to(element, device: device) if element
237
- pointer_down(:left, device: device)
238
- pointer_up(:left, device: device)
229
+ pointer_down(button || :left, device: device)
230
+ pointer_up(button || :left, device: device)
239
231
  self
240
232
  end
241
233
 
@@ -290,10 +282,7 @@ module Selenium
290
282
  #
291
283
 
292
284
  def context_click(element = nil, device: nil)
293
- move_to(element, device: device) if element
294
- pointer_down(:right, device: device)
295
- pointer_up(:right, device: device)
296
- self
285
+ click(element, button: :right, device: device)
297
286
  end
298
287
 
299
288
  #
@@ -348,15 +337,15 @@ module Selenium
348
337
 
349
338
  private
350
339
 
351
- def button_action(button, action: nil, device: nil)
352
- pointer = get_pointer(device)
353
- pointer.send(action, button)
340
+ def button_action(button, action, device: nil, **opts)
341
+ pointer = pointer_input(device)
342
+ pointer.send(action, button, **opts)
354
343
  tick(pointer)
355
344
  self
356
345
  end
357
346
 
358
- def get_pointer(device = nil)
359
- get_device(device) || pointer_inputs.first
347
+ def pointer_input(name = nil)
348
+ device(name: name, type: Interactions::POINTER) || add_pointer_input(:mouse, 'mouse')
360
349
  end
361
350
  end # PointerActions
362
351
  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
@@ -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
- end
32
-
33
- def type
34
- Interactions::POINTER
37
+ @type = Interactions::POINTER
35
38
  end
36
39
 
37
40
  def encode
38
- return nil if no_actions?
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, element: nil, origin: nil)
52
- add_action(PointerMove.new(self, duration, x, y, element: element, origin: origin))
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, element: nil, origin: nil, **opts)
37
+ super(source)
38
+ @duration = duration * 1000
39
+ @x_offset = x
40
+ @y_offset = y
41
+ @origin = element || 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
@@ -0,0 +1,85 @@
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 clicking, tapping or pressing the pointer.
25
+ #
26
+ # @api private
27
+ #
28
+
29
+ class PointerPress < Interaction
30
+ include PointerEventProperties
31
+
32
+ BUTTONS = {left: 0,
33
+ touch: 0,
34
+ pen_contact: 0,
35
+ middle: 1,
36
+ right: 2,
37
+ pen_barrel: 2,
38
+ x1: 3,
39
+ back: 3,
40
+ x2: 4,
41
+ forward: 4}.freeze
42
+ DIRECTIONS = {down: :pointerDown, up: :pointerUp}.freeze
43
+
44
+ def initialize(source, direction, button, **opts)
45
+ super(source)
46
+ @direction = assert_direction(direction)
47
+ @button = assert_button(button)
48
+ @type = @direction
49
+ @opts = opts
50
+ end
51
+
52
+ def encode
53
+ process_opts.merge('type' => type.to_s, 'button' => @button)
54
+ end
55
+
56
+ private
57
+
58
+ def assert_source(source)
59
+ raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? PointerInput
60
+ end
61
+
62
+ def assert_button(button)
63
+ case button
64
+ when Symbol
65
+ raise ArgumentError, "#{button} is not a valid button!" unless BUTTONS.key? button
66
+
67
+ BUTTONS[button]
68
+ when Integer
69
+ raise ArgumentError, 'Button number cannot be negative!' if button.negative?
70
+
71
+ button
72
+ else
73
+ raise TypeError, "button must be a positive integer or one of #{BUTTONS.keys}, not #{button.class}"
74
+ end
75
+ end
76
+
77
+ def assert_direction(direction)
78
+ raise ArgumentError, "#{direction.inspect} is not a valid button direction" unless DIRECTIONS.key? direction
79
+
80
+ DIRECTIONS[direction]
81
+ end
82
+ end # PointerPress
83
+ end # Interactions
84
+ end # WebDriver
85
+ end # Selenium
@@ -0,0 +1,57 @@
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 scrolling a wheel.
25
+ #
26
+ # @api private
27
+ #
28
+
29
+ class Scroll < Interaction
30
+ def initialize(source:, x: 0, y: 0, delta_x: 0, delta_y: 0, origin: :viewport, duration: 0.25)
31
+ super(source)
32
+ @type = :scroll
33
+ @duration = duration * 1000
34
+ @origin = origin
35
+ @x_offset = x
36
+ @y_offset = y
37
+ @delta_x = delta_x
38
+ @delta_y = delta_y
39
+ end
40
+
41
+ def assert_source(source)
42
+ raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? WheelInput
43
+ end
44
+
45
+ def encode
46
+ {'type' => type.to_s,
47
+ 'duration' => @duration.to_i,
48
+ 'x' => @x_offset,
49
+ 'y' => @y_offset,
50
+ 'deltaX' => @delta_x,
51
+ 'deltaY' => @delta_y,
52
+ 'origin' => @origin.is_a?(Element) ? @origin : @origin.to_s}
53
+ end
54
+ end # PointerPress
55
+ end # Interactions
56
+ end # WebDriver
57
+ end # Selenium