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.
- data/CHANGES +17 -0
- data/lib/selenium/webdriver/chrome.rb +13 -13
- data/lib/selenium/webdriver/chrome/bridge.rb +4 -3
- data/lib/selenium/webdriver/chrome/service.rb +6 -4
- data/lib/selenium/webdriver/common.rb +1 -0
- data/lib/selenium/webdriver/common/driver.rb +1 -1
- data/lib/selenium/webdriver/common/element.rb +14 -0
- data/lib/selenium/webdriver/common/options.rb +12 -10
- data/lib/selenium/webdriver/common/port_prober.rb +2 -1
- data/lib/selenium/webdriver/common/service.rb +23 -8
- data/lib/selenium/webdriver/common/w3c_options.rb +45 -0
- data/lib/selenium/webdriver/edge.rb +13 -13
- data/lib/selenium/webdriver/edge/bridge.rb +98 -1
- data/lib/selenium/webdriver/edge/service.rb +6 -4
- data/lib/selenium/webdriver/firefox.rb +13 -13
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/service.rb +10 -4
- data/lib/selenium/webdriver/firefox/w3c_bridge.rb +2 -1
- data/lib/selenium/webdriver/ie.rb +13 -13
- data/lib/selenium/webdriver/ie/bridge.rb +3 -1
- data/lib/selenium/webdriver/ie/service.rb +6 -4
- data/lib/selenium/webdriver/phantomjs.rb +13 -9
- data/lib/selenium/webdriver/phantomjs/bridge.rb +2 -1
- data/lib/selenium/webdriver/phantomjs/service.rb +2 -4
- data/lib/selenium/webdriver/remote/bridge.rb +102 -108
- data/lib/selenium/webdriver/remote/commands.rb +188 -185
- data/lib/selenium/webdriver/remote/w3c_bridge.rb +75 -94
- data/lib/selenium/webdriver/remote/w3c_capabilities.rb +3 -3
- data/lib/selenium/webdriver/remote/w3c_commands.rb +108 -104
- data/lib/selenium/webdriver/safari.rb +14 -13
- data/lib/selenium/webdriver/safari/bridge.rb +2 -1
- data/lib/selenium/webdriver/safari/service.rb +16 -4
- data/selenium-webdriver.gemspec +1 -1
- metadata +3 -4
- data/Gemfile.lock +0 -53
- 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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
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?(:
|
104
|
-
service_args << "--silent=#{args.delete(:silent)}" if args.key?(:
|
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'
|
@@ -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
|
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]
|
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
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
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 = {})
|