selenium-webdriver 3.0.1 → 3.0.2

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.
Files changed (36) hide show
  1. data/CHANGES +17 -0
  2. data/lib/selenium/webdriver/chrome.rb +13 -13
  3. data/lib/selenium/webdriver/chrome/bridge.rb +4 -3
  4. data/lib/selenium/webdriver/chrome/service.rb +6 -4
  5. data/lib/selenium/webdriver/common.rb +1 -0
  6. data/lib/selenium/webdriver/common/driver.rb +1 -1
  7. data/lib/selenium/webdriver/common/element.rb +14 -0
  8. data/lib/selenium/webdriver/common/options.rb +12 -10
  9. data/lib/selenium/webdriver/common/port_prober.rb +2 -1
  10. data/lib/selenium/webdriver/common/service.rb +23 -8
  11. data/lib/selenium/webdriver/common/w3c_options.rb +45 -0
  12. data/lib/selenium/webdriver/edge.rb +13 -13
  13. data/lib/selenium/webdriver/edge/bridge.rb +98 -1
  14. data/lib/selenium/webdriver/edge/service.rb +6 -4
  15. data/lib/selenium/webdriver/firefox.rb +13 -13
  16. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  17. data/lib/selenium/webdriver/firefox/service.rb +10 -4
  18. data/lib/selenium/webdriver/firefox/w3c_bridge.rb +2 -1
  19. data/lib/selenium/webdriver/ie.rb +13 -13
  20. data/lib/selenium/webdriver/ie/bridge.rb +3 -1
  21. data/lib/selenium/webdriver/ie/service.rb +6 -4
  22. data/lib/selenium/webdriver/phantomjs.rb +13 -9
  23. data/lib/selenium/webdriver/phantomjs/bridge.rb +2 -1
  24. data/lib/selenium/webdriver/phantomjs/service.rb +2 -4
  25. data/lib/selenium/webdriver/remote/bridge.rb +102 -108
  26. data/lib/selenium/webdriver/remote/commands.rb +188 -185
  27. data/lib/selenium/webdriver/remote/w3c_bridge.rb +75 -94
  28. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +3 -3
  29. data/lib/selenium/webdriver/remote/w3c_commands.rb +108 -104
  30. data/lib/selenium/webdriver/safari.rb +14 -13
  31. data/lib/selenium/webdriver/safari/bridge.rb +2 -1
  32. data/lib/selenium/webdriver/safari/service.rb +16 -4
  33. data/selenium-webdriver.gemspec +1 -1
  34. metadata +3 -4
  35. data/Gemfile.lock +0 -53
  36. data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
data/CHANGES CHANGED
@@ -1,3 +1,20 @@
1
+ 3.0.2 (2016-11-25)
2
+ ===================
3
+
4
+ Ruby:
5
+ * Implement #driver_path as parameter when initializing a driver (thanks lmtierney)
6
+ * Improve Ruby syntax in driver commands (thanks joe_schulte)
7
+ * Improve performance when shutting down drivers (thanks lmtierney)
8
+ * Fix bug for finding open ports on Windows (thanks kou1okada)
9
+ * Fix bug in auto detection of drivers which allowed selection of non-executable binaries
10
+
11
+ W3C:
12
+ * Implement #cookie_named and #delete_all_cookies methods (thanks lmtierney)

13
+ * Implement element #property method (thanks lmtierney)

14
+
15
+ Chrome:
16
+ * Fix bug in switches (thanks danvine)

17
+
1
18
  3.0.1 (2016-11-06)
2
19
  ===================
3
20
 
@@ -26,25 +26,25 @@ require 'selenium/webdriver/chrome/profile'
26
26
  module Selenium
27
27
  module WebDriver
28
28
  module Chrome
29
- MISSING_TEXT = <<-ERROR.tr("\n", '').freeze
30
- Unable to find chromedriver. Please download the server from
31
- http://chromedriver.storage.googleapis.com/index.html and place it
32
- somewhere on your PATH. More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver.
33
- ERROR
34
-
35
29
  def self.driver_path=(path)
30
+ warn <<-DEPRECATE.gsub(/\n +| {2,}/, ' ').freeze
31
+ [DEPRECATION] `driver_path=` is deprecated. Pass the driver path as an option instead.
32
+ e.g. Selenium::WebDriver.for :chrome, driver_path: '/path'
33
+ DEPRECATE
34
+
36
35
  Platform.assert_executable path
37
36
  @driver_path = path
38
37
  end
39
38
 
40
- def self.driver_path
41
- @driver_path ||= begin
42
- path = Platform.find_binary('chromedriver')
43
- raise Error::WebDriverError, MISSING_TEXT unless path
44
- Platform.assert_executable path
45
-
46
- path
39
+ def self.driver_path(warning = true)
40
+ if warning
41
+ warn <<-DEPRECATE.gsub(/\n +| {2,}/, ' ').freeze
42
+ [DEPRECATION] `driver_path` is deprecated. Pass the driver path as an option instead.
43
+ e.g. Selenium::WebDriver.for :chrome, driver_path: '/path'
44
+ DEPRECATE
47
45
  end
46
+
47
+ @driver_path ||= nil
48
48
  end
49
49
 
50
50
  def self.path=(path)
@@ -31,7 +31,8 @@ module Selenium
31
31
  end
32
32
 
33
33
  unless opts.key?(:url)
34
- @service = Service.new(Chrome.driver_path, port, *extract_service_args(service_args))
34
+ driver_path = opts.delete(:driver_path) || Chrome.driver_path(false)
35
+ @service = Service.new(driver_path, port, *extract_service_args(service_args))
35
36
  @service.start
36
37
  opts[:url] = @service.uri
37
38
  end
@@ -100,8 +101,8 @@ module Selenium
100
101
  service_args << "--url-base=#{args.delete(:url_base)}" if args.key?(:url_base)
101
102
  service_args << "--port-server=#{args.delete(:port_server)}" if args.key?(:port_server)
102
103
  service_args << "--whitelisted-ips=#{args.delete(:whitelisted_ips)}" if args.key?(:whitelisted_ips)
103
- service_args << "--verbose=#{args.delete(:verbose)}" if args.key?(:whitelisted_ips)
104
- service_args << "--silent=#{args.delete(:silent)}" if args.key?(:whitelisted_ips)
104
+ service_args << "--verbose=#{args.delete(:verbose)}" if args.key?(:verbose)
105
+ service_args << "--silent=#{args.delete(:silent)}" if args.key?(:silent)
105
106
  service_args
106
107
  end
107
108
  end # Bridge
@@ -26,6 +26,12 @@ module Selenium
26
26
 
27
27
  class Service < WebDriver::Service
28
28
  DEFAULT_PORT = 9515
29
+ @executable = 'chromedriver'.freeze
30
+ @missing_text = <<-ERROR.gsub(/\n +| {2,}/, ' ').freeze
31
+ Unable to find chromedriver. Please download the server from
32
+ http://chromedriver.storage.googleapis.com/index.html and place it somewhere on your PATH.
33
+ More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver.
34
+ ERROR
29
35
 
30
36
  private
31
37
 
@@ -37,10 +43,6 @@ module Selenium
37
43
  @process.start
38
44
  end
39
45
 
40
- def stop_server
41
- connect_to_server { |http| http.get('/shutdown') }
42
- end
43
-
44
46
  def cannot_connect_error_text
45
47
  "unable to connect to chromedriver #{@host}:#{@port}"
46
48
  end
@@ -39,6 +39,7 @@ require 'selenium/webdriver/common/timeouts'
39
39
  require 'selenium/webdriver/common/window'
40
40
  require 'selenium/webdriver/common/logs'
41
41
  require 'selenium/webdriver/common/options'
42
+ require 'selenium/webdriver/common/w3c_options'
42
43
  require 'selenium/webdriver/common/search_context'
43
44
  require 'selenium/webdriver/common/action_builder'
44
45
  require 'selenium/webdriver/common/touch_action_builder'
@@ -121,7 +121,7 @@ module Selenium
121
121
  #
122
122
 
123
123
  def manage
124
- @manage ||= WebDriver::Options.new(bridge)
124
+ bridge.options
125
125
  end
126
126
 
127
127
  #
@@ -118,6 +118,20 @@ module Selenium
118
118
  bridge.element_attribute self, name
119
119
  end
120
120
 
121
+ #
122
+ # Get the value of a the given property with the same name of the element. If the value is not
123
+ # set, nil is returned.
124
+ #
125
+ # @param [String]
126
+ # property name
127
+ # @return [String,nil]
128
+ # property value
129
+ #
130
+
131
+ def property(name)
132
+ bridge.element_property self, name
133
+ end
134
+
121
135
  #
122
136
  # Get the text content of this element
123
137
  #
@@ -90,16 +90,7 @@ module Selenium
90
90
  #
91
91
 
92
92
  def all_cookies
93
- @bridge.cookies.map do |cookie|
94
- {
95
- name: cookie['name'],
96
- value: cookie['value'],
97
- path: cookie['path'],
98
- domain: cookie['domain'] && strip_port(cookie['domain']),
99
- expires: cookie['expiry'] && datetime_at(cookie['expiry']),
100
- secure: cookie['secure']
101
- }
102
- end
93
+ @bridge.cookies.map { |cookie| convert_cookie(cookie) }
103
94
  end
104
95
 
105
96
  def timeouts
@@ -146,6 +137,17 @@ module Selenium
146
137
  def strip_port(str)
147
138
  str.split(':', 2).first
148
139
  end
140
+
141
+ def convert_cookie(cookie)
142
+ {
143
+ name: cookie['name'],
144
+ value: cookie['value'],
145
+ path: cookie['path'],
146
+ domain: cookie['domain'] && strip_port(cookie['domain']),
147
+ expires: cookie['expiry'] && datetime_at(cookie['expiry']),
148
+ secure: cookie['secure']
149
+ }
150
+ end
149
151
  end # Options
150
152
  end # WebDriver
151
153
  end # Selenium
@@ -38,8 +38,9 @@ module Selenium
38
38
  port
39
39
  end
40
40
 
41
- IGNORED_ERRORS = [Errno::EADDRNOTAVAIL].freeze
41
+ IGNORED_ERRORS = [Errno::EADDRNOTAVAIL]
42
42
  IGNORED_ERRORS << Errno::EBADF if Platform.cygwin?
43
+ IGNORED_ERRORS.freeze
43
44
 
44
45
  def self.free?(port)
45
46
  Platform.interfaces.each do |host|
@@ -36,10 +36,17 @@ module Selenium
36
36
  SOCKET_LOCK_TIMEOUT = 45
37
37
  STOP_TIMEOUT = 20
38
38
 
39
+ @executable = nil
40
+ @missing_text = nil
41
+
42
+ class << self
43
+ attr_reader :executable, :missing_text
44
+ end
45
+
39
46
  attr_accessor :host
40
47
 
41
48
  def initialize(executable_path, port, *extra_args)
42
- @executable_path = executable_path
49
+ @executable_path = binary_path(executable_path)
43
50
  @host = Platform.localhost
44
51
  @port = Integer(port)
45
52
  @extra_args = extra_args
@@ -47,6 +54,13 @@ module Selenium
47
54
  raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
48
55
  end
49
56
 
57
+ def binary_path(path)
58
+ path = Platform.find_binary(self.class.executable) if path.nil?
59
+ raise Error::WebDriverError, self.class.missing_text unless path
60
+ Platform.assert_executable path
61
+ path
62
+ end
63
+
50
64
  def start
51
65
  if process_running?
52
66
  raise "already started: #{uri.inspect} #{@executable_path.inspect}"
@@ -62,8 +76,9 @@ module Selenium
62
76
  end
63
77
 
64
78
  def stop
65
- return if process_exited?
66
79
  stop_server
80
+ @process.poll_for_exit STOP_TIMEOUT
81
+ rescue ChildProcess::TimeoutError
67
82
  ensure
68
83
  stop_process
69
84
  end
@@ -91,16 +106,16 @@ module Selenium
91
106
  raise NotImplementedError, 'subclass responsibility'
92
107
  end
93
108
 
94
- def stop_server
95
- raise NotImplementedError, 'subclass responsibility'
96
- end
97
-
98
109
  def stop_process
99
- @process.poll_for_exit STOP_TIMEOUT
100
- rescue ChildProcess::TimeoutError
110
+ return if process_exited?
101
111
  @process.stop STOP_TIMEOUT
102
112
  end
103
113
 
114
+ def stop_server
115
+ return if process_exited?
116
+ connect_to_server { |http| http.get('/shutdown') }
117
+ end
118
+
104
119
  def process_running?
105
120
  @process && @process.alive?
106
121
  end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
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
+ class W3COptions < Options
23
+
24
+ #
25
+ # Get the cookie with the given name
26
+ #
27
+ # @param [String] name the name of the cookie
28
+ # @return [Hash, nil] the cookie, or nil if it wasn't found.
29
+ #
30
+
31
+ def cookie_named(name)
32
+ convert_cookie(@bridge.cookie(name))
33
+ end
34
+
35
+ #
36
+ # Delete all cookies
37
+ #
38
+
39
+ def delete_all_cookies
40
+ @bridge.delete_all_cookies
41
+ end
42
+
43
+ end # WC3Options
44
+ end # WebDriver
45
+ end # Selenium
@@ -25,25 +25,25 @@ require 'selenium/webdriver/edge/bridge'
25
25
  module Selenium
26
26
  module WebDriver
27
27
  module Edge
28
- MISSING_TEXT = <<-ERROR.tr("\n", '').freeze
29
- Unable to find MicrosoftWebDriver. Please download the server from
30
- https://www.microsoft.com/en-us/download/details.aspx?id=48212 and place it
31
- somewhere on your PATH. More info at https://github.com/SeleniumHQ/selenium/wiki/MicrosoftWebDriver.
32
- ERROR
33
-
34
28
  def self.driver_path=(path)
29
+ warn <<-DEPRECATE.gsub(/\n +| {2,}/, ' ').freeze
30
+ [DEPRECATION] `driver_path=` is deprecated. Pass the driver path as an option instead.
31
+ e.g. Selenium::WebDriver.for :edge, driver_path: '/path'
32
+ DEPRECATE
33
+
35
34
  Platform.assert_executable path
36
35
  @driver_path = path
37
36
  end
38
37
 
39
- def self.driver_path
40
- @driver_path ||= begin
41
- path = Platform.find_binary('MicrosoftWebDriver')
42
- raise Error::WebDriverError, MISSING_TEXT unless path
43
- Platform.assert_executable path
44
-
45
- path
38
+ def self.driver_path(warning = true)
39
+ if warning
40
+ warn <<-DEPRECATE.gsub(/\n +| {2,}/, ' ').freeze
41
+ [DEPRECATION] `driver_path` is deprecated. Pass the driver path as an option instead.
42
+ e.g. Selenium::WebDriver.for :edge, driver_path: '/path'
43
+ DEPRECATE
46
44
  end
45
+
46
+ @driver_path ||= nil
47
47
  end
48
48
  end # Edge
49
49
  end # WebDriver
@@ -28,8 +28,10 @@ module Selenium
28
28
  def initialize(opts = {})
29
29
  port = opts.delete(:port) || Service::DEFAULT_PORT
30
30
  service_args = opts.delete(:service_args) || {}
31
+
31
32
  unless opts.key?(:url)
32
- @service = Service.new(Edge.driver_path, port, *extract_service_args(service_args))
33
+ driver_path = opts.delete(:driver_path) || Edge.driver_path(false)
34
+ @service = Service.new(driver_path, port, *extract_service_args(service_args))
33
35
  @service.host = 'localhost' if @service.host == '127.0.0.1'
34
36
  @service.start
35
37
  opts[:url] = @service.uri
@@ -51,6 +53,20 @@ module Selenium
51
53
  ]
52
54
  end
53
55
 
56
+ def commands(command)
57
+ unsupported = %i[execute_script execute_async_script submit_element double_click
58
+ mouse_down mouse_up mouse_move_to click
59
+ send_keys_to_active_element get_window_handles get_current_window_handle
60
+ get_window_size set_window_size get_window_position set_window_position
61
+ maximize_window get_alert_text accept_alert dismiss_alert]
62
+ if unsupported.include? command
63
+ Remote::Bridge::COMMANDS[command]
64
+ else
65
+ super
66
+ end
67
+
68
+ end
69
+
54
70
  def capabilities
55
71
  @capabilities ||= Remote::Capabilities.edge
56
72
  end
@@ -61,6 +77,87 @@ module Selenium
61
77
  @service.stop if @service
62
78
  end
63
79
 
80
+ def execute_script(script, *args)
81
+ result = execute :execute_script, {}, {script: script, args: args}
82
+ unwrap_script_result result
83
+ end
84
+
85
+ def execute_async_script(script, *args)
86
+ result = execute :execute_async_script, {}, {script: script, args: args}
87
+ unwrap_script_result result
88
+ end
89
+
90
+ def submit_element(element)
91
+ execute :submit_element, id: element['ELEMENT']
92
+ end
93
+
94
+ def double_click
95
+ execute :double_click
96
+ end
97
+
98
+ def click
99
+ execute :click, {}, {button: 0}
100
+ end
101
+
102
+ def context_click
103
+ execute :click, {}, {button: 2}
104
+ end
105
+
106
+ def mouse_down
107
+ execute :mouse_down
108
+ end
109
+
110
+ def mouse_up
111
+ execute :mouse_up
112
+ end
113
+
114
+ def mouse_move_to(element, x = nil, y = nil)
115
+ element_id = element['ELEMENT'] if element
116
+ params = {element: element_id}
117
+
118
+ if x && y
119
+ params[:xoffset] = x
120
+ params[:yoffset] = y
121
+ end
122
+
123
+ execute :mouse_move_to, {}, params
124
+ end
125
+
126
+ def send_keys_to_active_element(key)
127
+ execute :send_keys_to_active_element, {}, {value: key}
128
+ end
129
+
130
+ def window_handle
131
+ execute :get_current_window_handle
132
+ end
133
+
134
+ def window_size(handle = :current)
135
+ data = execute :get_window_size, window_handle: handle
136
+
137
+ Dimension.new data['width'], data['height']
138
+ end
139
+
140
+ def resize_window(width, height, handle = :current)
141
+ execute :set_window_size, {window_handle: handle},
142
+ {width: width,
143
+ height: height}
144
+ end
145
+
146
+ def window_position(handle = :current)
147
+ data = execute :get_window_position, window_handle: handle
148
+
149
+ Point.new data['x'], data['y']
150
+ end
151
+
152
+ def reposition_window(x, y, handle = :current)
153
+ execute :set_window_position, {window_handle: handle},
154
+ {x: x, y: y}
155
+ end
156
+
157
+ def maximize_window(handle = :current)
158
+ execute :maximize_window, window_handle: handle
159
+ end
160
+
64
161
  private
65
162
 
66
163
  def extract_service_args(args = {})