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 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
@@ -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
@@ -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
- firefox_options_caps = caps[:firefox_options] || {}
69
- caps[:firefox_options] = firefox_options_caps.merge(opts[:firefox_options] || {})
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
- caps[:firefox_options][:profile] = profile.encoded
104
+ firefox_options[:profile] = profile.encoded
76
105
  end
77
106
 
78
- Binary.path = caps[:firefox_options][:binary] if caps[:firefox_options].key?(:binary)
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
- WebDriver.logger.warn <<-DEPRECATE.gsub(/\n +| {2,}/, ' ').freeze
44
- [DEPRECATION] `:port` is deprecated. Use `:url` with full path
45
- DEPRECATE
46
- end
47
- port = opts.delete(:port) || 4444
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 :set_window_size, {}, {width: width,
238
- height: height}
237
+ execute :set_window_rect, {}, {width: width, height: height}
239
238
  end
240
239
 
241
- def maximize_window(handle = :current)
240
+ def window_size(handle = :current)
242
241
  unless handle == :current
243
- raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size'
242
+ raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size'
244
243
  end
245
- execute :maximize_window
244
+ data = execute :get_window_rect
245
+
246
+ Dimension.new data['width'], data['height']
246
247
  end
247
248
 
248
- def full_screen_window
249
- execute :fullscreen_window
249
+ def minimize_window
250
+ execute :minimize_window
250
251
  end
251
252
 
252
- def window_size(handle = :current)
253
+ def maximize_window(handle = :current)
253
254
  unless handle == :current
254
- raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size'
255
+ raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size'
255
256
  end
256
- data = execute :get_window_size
257
+ execute :maximize_window
258
+ end
257
259
 
258
- Dimension.new data['width'], data['height']
260
+ def full_screen_window
261
+ execute :fullscreen_window
259
262
  end
260
263
 
261
264
  def reposition_window(x, y)
262
- execute :set_window_position, {}, {x: x, y: y}
265
+ execute :set_window_rect, {}, {x: x, y: y}
263
266
  end
264
267
 
265
268
  def window_position
266
- data = execute :get_window_position
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
- execute :element_send_keys, {id: element}, {value: keys.join('').split(//)}
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
 
@@ -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.3.0'
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.3.0
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-03-07 00:00:00 -06:00
14
+ date: 2017-04-21 00:00:00 -05:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency