selenium-webdriver 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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 = {})