selenium-webdriver 3.3.0 → 3.4.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.
- data/CHANGES +18 -0
- data/lib/selenium/webdriver.rb +1 -0
- data/lib/selenium/webdriver/common/element.rb +10 -0
- data/lib/selenium/webdriver/common/w3c_error.rb +13 -0
- data/lib/selenium/webdriver/common/window.rb +36 -0
- data/lib/selenium/webdriver/edge/bridge.rb +44 -0
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/w3c_bridge.rb +34 -4
- data/lib/selenium/webdriver/remote/bridge.rb +15 -6
- data/lib/selenium/webdriver/remote/capabilities.rb +1 -1
- data/lib/selenium/webdriver/remote/w3c_bridge.rb +36 -16
- data/lib/selenium/webdriver/remote/w3c_commands.rb +3 -0
- data/selenium-webdriver.gemspec +1 -1
- metadata +2 -2
data/CHANGES
CHANGED
@@ -1,6 +1,24 @@
|
|
1
|
+
3.4.0 (Unreleased)
|
2
|
+
===================
|
3
|
+
|
4
|
+
Edge:
|
5
|
+
* Fix bug when response is not wrapped with "value"
|
6
|
+
|
7
|
+
Firefox:
|
8
|
+
* Support geckodriver v0.16
|
9
|
+
|
10
|
+
Ruby:
|
11
|
+
* Support ElementClickIntercepted error from W3C spec
|
12
|
+
* Support ElementNotInteractable error from W3C spec
|
13
|
+
* Implement window rect commands
|
14
|
+
* Implement window minimize command
|
15
|
+
|
1
16
|
3.3.0 (2017-03-07)
|
2
17
|
===================
|
3
18
|
|
19
|
+
Firefox:
|
20
|
+
* geckodriver v0.15 or later is required
|
21
|
+
|
4
22
|
W3C:
|
5
23
|
* Support for command response data to be wrapped in a 'value' key
|
6
24
|
* Support for updated timeout formats
|
data/lib/selenium/webdriver.rb
CHANGED
@@ -30,6 +30,7 @@ module Selenium
|
|
30
30
|
module WebDriver
|
31
31
|
Point = Struct.new(:x, :y)
|
32
32
|
Dimension = Struct.new(:width, :height)
|
33
|
+
Rectangle = Struct.new(:x, :y, :width, :height)
|
33
34
|
Location = Struct.new(:latitude, :longitude, :altitude)
|
34
35
|
|
35
36
|
autoload :Chrome, 'selenium/webdriver/chrome'
|
@@ -235,6 +235,16 @@ module Selenium
|
|
235
235
|
bridge.element_location @id
|
236
236
|
end
|
237
237
|
|
238
|
+
#
|
239
|
+
# Get the dimensions and coordinates of this element.
|
240
|
+
#
|
241
|
+
# @return [WebDriver::Rectangle]
|
242
|
+
#
|
243
|
+
|
244
|
+
def rect
|
245
|
+
bridge.element_rect @id
|
246
|
+
end
|
247
|
+
|
238
248
|
#
|
239
249
|
# Determine an element's location on the screen once it has been scrolled into view.
|
240
250
|
#
|
@@ -178,6 +178,19 @@ module Selenium
|
|
178
178
|
|
179
179
|
class UnsupportedOperationError < WebDriverError; end
|
180
180
|
|
181
|
+
#
|
182
|
+
# Indicates that the Element Click command could not be completed because the element receiving the events
|
183
|
+
# is obscuring the element that was requested clicked.
|
184
|
+
#
|
185
|
+
|
186
|
+
class ElementClickIntercepted < WebDriverError; end
|
187
|
+
|
188
|
+
#
|
189
|
+
# Indicates that a command could not be completed because the element is not pointer or keyboard interactable.
|
190
|
+
#
|
191
|
+
|
192
|
+
class ElementNotInteractable < WebDriverError; end
|
193
|
+
|
181
194
|
# aliased for backwards compatibility
|
182
195
|
NoAlertPresentError = NoSuchAlertError
|
183
196
|
ScriptTimeOutError = ScriptTimeoutError
|
@@ -82,6 +82,34 @@ module Selenium
|
|
82
82
|
@bridge.window_position
|
83
83
|
end
|
84
84
|
|
85
|
+
#
|
86
|
+
# Sets the current window rect to the given point and position.
|
87
|
+
#
|
88
|
+
# @param [Selenium::WebDriver::Rectangle, #x, #y, #width, #height] rectangle The new rect.
|
89
|
+
#
|
90
|
+
|
91
|
+
def rect=(rectangle)
|
92
|
+
unless %w[x y width height].all? { |val| rectangle.respond_to? val }
|
93
|
+
raise ArgumentError, "expected #{rectangle.inspect}:#{rectangle.class}" \
|
94
|
+
' to respond to #x, #y, #width, and #height'
|
95
|
+
end
|
96
|
+
|
97
|
+
@bridge.set_window_rect(x: rectangle.x,
|
98
|
+
y: rectangle.y,
|
99
|
+
width: rectangle.width,
|
100
|
+
height: rectangle.height)
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Get the rect of the current window.
|
105
|
+
#
|
106
|
+
# @return [Selenium::WebDriver::Rectangle] The rectangle.
|
107
|
+
#
|
108
|
+
|
109
|
+
def rect
|
110
|
+
@bridge.window_rect
|
111
|
+
end
|
112
|
+
|
85
113
|
#
|
86
114
|
# Equivalent to #size=, but accepts width and height arguments.
|
87
115
|
#
|
@@ -115,6 +143,14 @@ module Selenium
|
|
115
143
|
@bridge.maximize_window
|
116
144
|
end
|
117
145
|
|
146
|
+
#
|
147
|
+
# Minimize the current window
|
148
|
+
#
|
149
|
+
|
150
|
+
def minimize
|
151
|
+
@bridge.minimize_window
|
152
|
+
end
|
153
|
+
|
118
154
|
#
|
119
155
|
# Make current window full screen
|
120
156
|
#
|
@@ -115,6 +115,50 @@ module Selenium
|
|
115
115
|
def maximize_window(handle = :current)
|
116
116
|
execute :maximize_window, window_handle: handle
|
117
117
|
end
|
118
|
+
|
119
|
+
def create_session(desired_capabilities)
|
120
|
+
resp = raw_execute :new_session, {}, {desiredCapabilities: desired_capabilities}
|
121
|
+
@session_id = resp['sessionId']
|
122
|
+
return Remote::W3CCapabilities.json_create resp['value'] if @session_id
|
123
|
+
|
124
|
+
raise Error::WebDriverError, 'no sessionId in returned payload'
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# executes a command on the remote server.
|
129
|
+
#
|
130
|
+
#
|
131
|
+
# Returns the 'value' of the returned payload
|
132
|
+
#
|
133
|
+
|
134
|
+
def execute(*args)
|
135
|
+
result = raw_execute(*args)
|
136
|
+
result.payload.key?('value') ? result['value'] : result
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# executes a command on the remote server.
|
141
|
+
#
|
142
|
+
# @return [WebDriver::Remote::Response]
|
143
|
+
#
|
144
|
+
|
145
|
+
def raw_execute(command, opts = {}, command_hash = nil)
|
146
|
+
verb, path = commands(command) || raise(ArgumentError, "unknown command: #{command.inspect}")
|
147
|
+
path = path.dup
|
148
|
+
|
149
|
+
path[':session_id'] = @session_id if path.include?(':session_id')
|
150
|
+
|
151
|
+
begin
|
152
|
+
opts.each do |key, value|
|
153
|
+
path[key.inspect] = escaper.escape(value.to_s)
|
154
|
+
end
|
155
|
+
rescue IndexError
|
156
|
+
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
157
|
+
end
|
158
|
+
|
159
|
+
WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
|
160
|
+
http.call verb, path, command_hash
|
161
|
+
end
|
118
162
|
end # Bridge
|
119
163
|
end # Edge
|
120
164
|
end # WebDriver
|
Binary file
|
@@ -60,22 +60,52 @@ module Selenium
|
|
60
60
|
@service.stop if @service
|
61
61
|
end
|
62
62
|
|
63
|
+
# Support for geckodriver < 0.15
|
64
|
+
def resize_window(width, height, handle = :current)
|
65
|
+
super
|
66
|
+
rescue Error::UnknownCommandError
|
67
|
+
execute :set_window_size, {}, {width: width, height: height}
|
68
|
+
end
|
69
|
+
|
70
|
+
def window_size(handle = :current)
|
71
|
+
data = super
|
72
|
+
rescue Error::UnknownCommandError
|
73
|
+
data = execute :get_window_size
|
74
|
+
ensure
|
75
|
+
return Dimension.new data['width'], data['height']
|
76
|
+
end
|
77
|
+
|
78
|
+
def reposition_window(x, y)
|
79
|
+
super
|
80
|
+
rescue Error::UnknownCommandError
|
81
|
+
execute :set_window_position, {}, {x: x, y: y}
|
82
|
+
end
|
83
|
+
|
84
|
+
def window_position
|
85
|
+
data = super
|
86
|
+
rescue Error::UnknownCommandError
|
87
|
+
data = execute :get_window_position
|
88
|
+
ensure
|
89
|
+
return Point.new data['x'], data['y']
|
90
|
+
end
|
91
|
+
|
63
92
|
private
|
64
93
|
|
65
94
|
def create_capabilities(opts)
|
66
95
|
caps = Remote::W3CCapabilities.firefox
|
67
96
|
caps.merge!(opts.delete(:desired_capabilities)) if opts.key? :desired_capabilities
|
68
|
-
|
69
|
-
|
97
|
+
firefox_options = caps[:firefox_options] || {}
|
98
|
+
firefox_options = firefox_options_caps.merge(opts[:firefox_options]) if opts.key?(:firefox_options)
|
70
99
|
if opts.key?(:profile)
|
71
100
|
profile = opts.delete(:profile)
|
72
101
|
unless profile.is_a?(Profile)
|
73
102
|
profile = Profile.from_name(profile)
|
74
103
|
end
|
75
|
-
|
104
|
+
firefox_options[:profile] = profile.encoded
|
76
105
|
end
|
77
106
|
|
78
|
-
Binary.path =
|
107
|
+
Binary.path = firefox_options[:binary] if firefox_options.key?(:binary)
|
108
|
+
caps[:firefox_options] = firefox_options unless firefox_options.empty?
|
79
109
|
caps
|
80
110
|
end
|
81
111
|
end # W3CBridge
|
@@ -39,12 +39,14 @@ module Selenium
|
|
39
39
|
def initialize(opts = {})
|
40
40
|
opts = opts.dup
|
41
41
|
|
42
|
-
if opts.key?(:port)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
port = if opts.key?(:port)
|
43
|
+
WebDriver.logger.warn <<-DEPRECATE.gsub(/\n +| {2,}/, ' ').freeze
|
44
|
+
[DEPRECATION] `:port` is deprecated. Use `:url` with full path
|
45
|
+
DEPRECATE
|
46
|
+
opts.delete(:port)
|
47
|
+
else
|
48
|
+
4444
|
49
|
+
end
|
48
50
|
|
49
51
|
http_client = opts.delete(:http_client) { Http::Default.new }
|
50
52
|
desired_capabilities = opts.delete(:desired_capabilities) { Capabilities.firefox }
|
@@ -571,6 +573,13 @@ module Selenium
|
|
571
573
|
Point.new data['x'], data['y']
|
572
574
|
end
|
573
575
|
|
576
|
+
def element_rect(element)
|
577
|
+
loc = execute :get_element_location, id: element
|
578
|
+
size = execute :get_element_size, id: element
|
579
|
+
|
580
|
+
Rectangle.new loc['x'], loc['y'], size['width'], size['height']
|
581
|
+
end
|
582
|
+
|
574
583
|
def element_location_once_scrolled_into_view(element)
|
575
584
|
data = execute :get_element_location_once_scrolled_into_view, id: element
|
576
585
|
|
@@ -139,7 +139,7 @@ module Selenium
|
|
139
139
|
caps = new
|
140
140
|
caps.browser_name = data.delete('browserName')
|
141
141
|
caps.version = data.delete('version')
|
142
|
-
caps.platform = data.delete('platform').downcase.to_sym if data.key?('platform')
|
142
|
+
caps.platform = data.delete('platform').downcase.tr(' ','_').to_sym if data.key?('platform')
|
143
143
|
caps.javascript_enabled = data.delete('javascriptEnabled')
|
144
144
|
caps.css_selectors_enabled = data.delete('cssSelectorsEnabled')
|
145
145
|
caps.takes_screenshot = data.delete('takesScreenshot')
|
@@ -113,7 +113,7 @@ module Selenium
|
|
113
113
|
def create_session(desired_capabilities)
|
114
114
|
resp = execute :new_session, {}, {desiredCapabilities: desired_capabilities}
|
115
115
|
@session_id = resp['sessionId']
|
116
|
-
return W3CCapabilities.json_create resp['value'] if @session_id
|
116
|
+
return W3CCapabilities.json_create(resp['capabilities'] || resp['value']) if @session_id
|
117
117
|
|
118
118
|
raise Error::WebDriverError, 'no sessionId in returned payload'
|
119
119
|
end
|
@@ -152,7 +152,7 @@ module Selenium
|
|
152
152
|
end
|
153
153
|
|
154
154
|
def alert=(keys)
|
155
|
-
execute :send_alert_text, {}, {value: keys.split(//)}
|
155
|
+
execute :send_alert_text, {}, {value: keys.split(//), text: keys}
|
156
156
|
end
|
157
157
|
|
158
158
|
def alert_text
|
@@ -234,39 +234,51 @@ module Selenium
|
|
234
234
|
unless handle == :current
|
235
235
|
raise Error::WebDriverError, 'Switch to desired window before changing its size'
|
236
236
|
end
|
237
|
-
execute :
|
238
|
-
height: height}
|
237
|
+
execute :set_window_rect, {}, {width: width, height: height}
|
239
238
|
end
|
240
239
|
|
241
|
-
def
|
240
|
+
def window_size(handle = :current)
|
242
241
|
unless handle == :current
|
243
|
-
raise Error::UnsupportedOperationError, 'Switch to desired window before
|
242
|
+
raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size'
|
244
243
|
end
|
245
|
-
execute :
|
244
|
+
data = execute :get_window_rect
|
245
|
+
|
246
|
+
Dimension.new data['width'], data['height']
|
246
247
|
end
|
247
248
|
|
248
|
-
def
|
249
|
-
execute :
|
249
|
+
def minimize_window
|
250
|
+
execute :minimize_window
|
250
251
|
end
|
251
252
|
|
252
|
-
def
|
253
|
+
def maximize_window(handle = :current)
|
253
254
|
unless handle == :current
|
254
|
-
raise Error::UnsupportedOperationError, 'Switch to desired window before
|
255
|
+
raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size'
|
255
256
|
end
|
256
|
-
|
257
|
+
execute :maximize_window
|
258
|
+
end
|
257
259
|
|
258
|
-
|
260
|
+
def full_screen_window
|
261
|
+
execute :fullscreen_window
|
259
262
|
end
|
260
263
|
|
261
264
|
def reposition_window(x, y)
|
262
|
-
execute :
|
265
|
+
execute :set_window_rect, {}, {x: x, y: y}
|
263
266
|
end
|
264
267
|
|
265
268
|
def window_position
|
266
|
-
data = execute :
|
269
|
+
data = execute :get_window_rect
|
267
270
|
Point.new data['x'], data['y']
|
268
271
|
end
|
269
272
|
|
273
|
+
def set_window_rect(x: nil, y: nil, width: nil, height: nil)
|
274
|
+
execute :set_window_rect, {}, {x: x, y: y, width: width, height: height}
|
275
|
+
end
|
276
|
+
|
277
|
+
def window_rect
|
278
|
+
data = execute :get_window_rect
|
279
|
+
Rectangle.new data['x'], data['y'], data['width'], data['height']
|
280
|
+
end
|
281
|
+
|
270
282
|
def screenshot
|
271
283
|
execute :take_screenshot
|
272
284
|
end
|
@@ -415,7 +427,9 @@ module Selenium
|
|
415
427
|
|
416
428
|
# TODO: - Implement file verification
|
417
429
|
def send_keys_to_element(element, keys)
|
418
|
-
|
430
|
+
# Keep .split(//) for backward compatibility for now
|
431
|
+
text = keys.join('')
|
432
|
+
execute :element_send_keys, {id: element}, {value: text.split(//), text: text}
|
419
433
|
end
|
420
434
|
|
421
435
|
def clear_element(element)
|
@@ -516,6 +530,12 @@ module Selenium
|
|
516
530
|
Point.new data['x'], data['y']
|
517
531
|
end
|
518
532
|
|
533
|
+
def element_rect(element)
|
534
|
+
data = execute :get_element_rect, id: element
|
535
|
+
|
536
|
+
Rectangle.new data['x'], data['y'], data['width'], data['height']
|
537
|
+
end
|
538
|
+
|
519
539
|
def element_location_once_scrolled_into_view(element)
|
520
540
|
send_keys_to_element(element, [''])
|
521
541
|
element_location(element)
|
@@ -54,11 +54,14 @@ module Selenium
|
|
54
54
|
switch_to_window: [:post, 'session/:session_id/window'.freeze],
|
55
55
|
get_window_handles: [:get, 'session/:session_id/window/handles'.freeze],
|
56
56
|
fullscreen_window: [:post, 'session/:session_id/window/fullscreen'.freeze],
|
57
|
+
minimize_window: [:post, 'session/:session_id/window/minimize'.freeze],
|
57
58
|
maximize_window: [:post, 'session/:session_id/window/maximize'.freeze],
|
58
59
|
set_window_size: [:post, 'session/:session_id/window/size'.freeze],
|
59
60
|
get_window_size: [:get, 'session/:session_id/window/size'.freeze],
|
60
61
|
set_window_position: [:post, 'session/:session_id/window/position'.freeze],
|
61
62
|
get_window_position: [:get, 'session/:session_id/window/position'.freeze],
|
63
|
+
set_window_rect: [:post, 'session/:session_id/window/rect'.freeze],
|
64
|
+
get_window_rect: [:get, 'session/:session_id/window/rect'.freeze],
|
62
65
|
switch_to_frame: [:post, 'session/:session_id/frame'.freeze],
|
63
66
|
switch_to_parent_frame: [:post, 'session/:session_id/frame/parent'.freeze],
|
64
67
|
|
data/selenium-webdriver.gemspec
CHANGED
@@ -5,7 +5,7 @@ raise "cwd must be #{root} when reading gemspec" if root != Dir.pwd
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'selenium-webdriver'
|
8
|
-
s.version = '3.
|
8
|
+
s.version = '3.4.0'
|
9
9
|
|
10
10
|
s.authors = ['Alex Rodionov', 'Titus Fortner']
|
11
11
|
s.email = ['p0deje@gmail.com', 'titusfortner@gmail.com']
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: selenium-webdriver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 3.
|
5
|
+
version: 3.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Alex Rodionov
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2017-
|
14
|
+
date: 2017-04-21 00:00:00 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|