selenium-webdriver 2.53.4 → 3.8.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.
- checksums.yaml +7 -0
- data/CHANGES +363 -10
- data/LICENSE +1 -1
- data/README.md +2 -3
- data/lib/selenium-webdriver.rb +0 -2
- data/lib/selenium/server.rb +69 -70
- data/lib/selenium/webdriver.rb +32 -23
- data/lib/selenium/webdriver/atoms.rb +18 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +8 -0
- data/lib/selenium/webdriver/chrome.rb +8 -6
- data/lib/selenium/webdriver/chrome/driver.rb +112 -0
- data/lib/selenium/webdriver/chrome/options.rb +168 -0
- data/lib/selenium/webdriver/chrome/profile.rb +17 -17
- data/lib/selenium/webdriver/chrome/service.rb +22 -89
- data/lib/selenium/webdriver/common.rb +13 -6
- data/lib/selenium/webdriver/common/action_builder.rb +49 -57
- data/lib/selenium/webdriver/common/alert.rb +5 -15
- data/lib/selenium/webdriver/common/bridge_helper.rb +10 -17
- data/lib/selenium/webdriver/common/driver.rb +53 -68
- data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_addons.rb} +13 -23
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +4 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +4 -7
- data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +0 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +1 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +0 -5
- data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +4 -9
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +7 -7
- data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +2 -7
- data/lib/selenium/webdriver/common/element.rb +57 -39
- data/lib/selenium/webdriver/common/error.rb +204 -106
- data/lib/selenium/webdriver/common/file_reaper.rb +3 -11
- data/lib/selenium/webdriver/common/html5/local_storage.rb +6 -10
- data/lib/selenium/webdriver/common/html5/session_storage.rb +6 -10
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +7 -18
- data/lib/selenium/webdriver/{safari/options.rb → common/interactions/input_device.rb} +20 -31
- data/lib/selenium/webdriver/common/interactions/interaction.rb +50 -0
- data/lib/selenium/webdriver/{safari/browser.rb → common/interactions/interactions.rb} +16 -15
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +143 -0
- data/lib/selenium/webdriver/common/interactions/key_input.rb +62 -0
- data/lib/selenium/webdriver/{android.rb → common/interactions/none_input.rb} +11 -6
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +353 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +132 -0
- data/lib/selenium/webdriver/common/keyboard.rb +7 -14
- data/lib/selenium/webdriver/common/keys.rb +99 -82
- data/lib/selenium/webdriver/common/log_entry.rb +3 -6
- data/lib/selenium/webdriver/common/logger.rb +140 -0
- data/lib/selenium/webdriver/common/logs.rb +2 -6
- data/lib/selenium/webdriver/common/mouse.rb +9 -14
- data/lib/selenium/webdriver/common/navigation.rb +2 -6
- data/lib/selenium/webdriver/common/options.rb +20 -23
- data/lib/selenium/webdriver/common/platform.rb +70 -97
- data/lib/selenium/webdriver/common/port_prober.rb +3 -4
- data/lib/selenium/webdriver/common/profile_helper.rb +6 -11
- data/lib/selenium/webdriver/common/proxy.rb +58 -72
- data/lib/selenium/webdriver/common/search_context.rb +22 -29
- data/lib/selenium/webdriver/common/service.rb +161 -0
- data/lib/selenium/webdriver/common/socket_lock.rb +6 -14
- data/lib/selenium/webdriver/common/socket_poller.rb +5 -12
- data/lib/selenium/webdriver/common/target_locator.rb +11 -15
- data/lib/selenium/webdriver/common/timeouts.rb +4 -8
- data/lib/selenium/webdriver/common/touch_action_builder.rb +2 -6
- data/lib/selenium/webdriver/common/touch_screen.rb +19 -23
- data/lib/selenium/webdriver/common/w3c_action_builder.rb +209 -0
- data/lib/selenium/webdriver/{phantomjs.rb → common/w3c_options.rb} +16 -14
- data/lib/selenium/webdriver/common/wait.rb +6 -13
- data/lib/selenium/webdriver/common/window.rb +48 -17
- data/lib/selenium/webdriver/common/zipper.rb +6 -10
- data/lib/selenium/webdriver/edge.rb +5 -12
- data/lib/selenium/webdriver/edge/bridge.rb +32 -63
- data/lib/selenium/webdriver/edge/driver.rb +73 -0
- data/lib/selenium/webdriver/edge/service.rb +18 -87
- data/lib/selenium/webdriver/firefox.rb +20 -11
- data/lib/selenium/webdriver/firefox/binary.rb +40 -56
- data/lib/selenium/webdriver/firefox/driver.rb +48 -0
- data/lib/selenium/webdriver/firefox/extension.rb +18 -8
- data/lib/selenium/webdriver/firefox/extension/prefs.json +3 -11
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/launcher.rb +13 -22
- data/lib/selenium/webdriver/firefox/legacy/driver.rb +79 -0
- data/lib/selenium/webdriver/{iphone.rb → firefox/marionette/bridge.rb} +25 -6
- data/lib/selenium/webdriver/firefox/marionette/driver.rb +96 -0
- data/lib/selenium/webdriver/firefox/options.rb +149 -0
- data/lib/selenium/webdriver/firefox/profile.rb +46 -46
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +8 -18
- data/lib/selenium/webdriver/firefox/service.rb +23 -83
- data/lib/selenium/webdriver/firefox/util.rb +0 -4
- data/lib/selenium/webdriver/ie.rb +4 -8
- data/lib/selenium/webdriver/ie/driver.rb +90 -0
- data/lib/selenium/webdriver/ie/options.rb +136 -0
- data/lib/selenium/webdriver/ie/service.rb +58 -0
- data/lib/selenium/webdriver/remote.rb +8 -16
- data/lib/selenium/webdriver/remote/bridge.rb +96 -565
- data/lib/selenium/webdriver/remote/capabilities.rb +76 -94
- data/lib/selenium/webdriver/remote/driver.rb +49 -0
- data/lib/selenium/webdriver/remote/http/common.rb +22 -20
- data/lib/selenium/webdriver/remote/http/curb.rb +9 -12
- data/lib/selenium/webdriver/remote/http/default.rb +54 -41
- data/lib/selenium/webdriver/remote/http/persistent.rb +9 -8
- data/lib/selenium/webdriver/remote/oss/bridge.rb +586 -0
- data/lib/selenium/webdriver/remote/oss/commands.rb +221 -0
- data/lib/selenium/webdriver/remote/response.rb +39 -27
- data/lib/selenium/webdriver/remote/server_error.rb +1 -5
- data/lib/selenium/webdriver/remote/w3c/bridge.rb +573 -0
- data/lib/selenium/webdriver/remote/w3c/capabilities.rb +290 -0
- data/lib/selenium/webdriver/remote/w3c/commands.rb +148 -0
- data/lib/selenium/webdriver/safari.rb +20 -29
- data/lib/selenium/webdriver/{firefox/w3c_bridge.rb → safari/driver.rb} +21 -30
- data/lib/selenium/webdriver/safari/service.rb +57 -0
- data/lib/selenium/webdriver/support.rb +1 -2
- data/lib/selenium/webdriver/support/abstract_event_listener.rb +17 -4
- data/lib/selenium/webdriver/support/block_event_listener.rb +1 -5
- data/lib/selenium/webdriver/support/color.rb +57 -42
- data/lib/selenium/webdriver/support/escaper.rb +41 -0
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +36 -40
- data/lib/selenium/webdriver/support/select.rb +33 -86
- data/selenium-webdriver.gemspec +22 -25
- metadata +254 -261
- data/lib/selenium-client.rb +0 -21
- data/lib/selenium/client.rb +0 -57
- data/lib/selenium/client/base.rb +0 -151
- data/lib/selenium/client/driver.rb +0 -29
- data/lib/selenium/client/errors.rb +0 -28
- data/lib/selenium/client/extensions.rb +0 -132
- data/lib/selenium/client/idiomatic.rb +0 -507
- data/lib/selenium/client/javascript_expression_builder.rb +0 -135
- data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -32
- data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -32
- data/lib/selenium/client/legacy_driver.rb +0 -1722
- data/lib/selenium/client/protocol.rb +0 -123
- data/lib/selenium/client/selenium_helper.rb +0 -49
- data/lib/selenium/rake/server_task.rb +0 -176
- data/lib/selenium/webdriver/android/bridge.rb +0 -68
- data/lib/selenium/webdriver/chrome/bridge.rb +0 -139
- data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
- data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
- data/lib/selenium/webdriver/common/html5/location.rb +0 -19
- data/lib/selenium/webdriver/common/w3c_error.rb +0 -194
- data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
- data/lib/selenium/webdriver/firefox/bridge.rb +0 -89
- data/lib/selenium/webdriver/ie/bridge.rb +0 -88
- data/lib/selenium/webdriver/ie/server.rb +0 -133
- data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
- data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -78
- data/lib/selenium/webdriver/phantomjs/service.rb +0 -130
- data/lib/selenium/webdriver/remote/commands.rb +0 -211
- data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -668
- data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -236
- data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -132
- data/lib/selenium/webdriver/safari/bridge.rb +0 -135
- data/lib/selenium/webdriver/safari/resources/client.js +0 -7255
- data/lib/selenium/webdriver/safari/server.rb +0 -187
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
#
|
|
3
1
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
2
|
# or more contributor license agreements. See the NOTICE file
|
|
5
3
|
# distributed with this work for additional information
|
|
@@ -24,27 +22,47 @@ module Selenium
|
|
|
24
22
|
module WebDriver
|
|
25
23
|
module Remote
|
|
26
24
|
module Http
|
|
27
|
-
|
|
28
25
|
# @api private
|
|
29
26
|
class Default < Common
|
|
30
|
-
|
|
27
|
+
attr_writer :proxy
|
|
28
|
+
|
|
29
|
+
attr_accessor :open_timeout
|
|
30
|
+
attr_accessor :read_timeout
|
|
31
|
+
|
|
32
|
+
# Initializes object.
|
|
33
|
+
# Warning: Setting {#open_timeout} to non-nil values will cause a separate thread to spawn.
|
|
34
|
+
# Debuggers that freeze the process will not be able to evaluate any operations if that happens.
|
|
35
|
+
# @param [Numeric] open_timeout - Open timeout to apply to HTTP client.
|
|
36
|
+
# @param [Numeric] read_timeout - Read timeout (seconds) to apply to HTTP client.
|
|
37
|
+
def initialize(open_timeout: nil, read_timeout: nil)
|
|
38
|
+
@open_timeout = open_timeout
|
|
39
|
+
@read_timeout = read_timeout
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Maintaining backward compatibility.
|
|
43
|
+
# @param [Numeric] value - Timeout in seconds to apply to both open timeout and read timeouts.
|
|
44
|
+
# @deprecated Please set the specific desired timeout {#read_timeout} or {#open_timeout} directly.
|
|
45
|
+
def timeout=(value)
|
|
46
|
+
WebDriver.logger.deprecate ':timeout=', '#read_timeout= and #open_timeout='
|
|
47
|
+
self.open_timeout = value
|
|
48
|
+
self.read_timeout = value
|
|
49
|
+
end
|
|
31
50
|
|
|
32
51
|
private
|
|
33
52
|
|
|
34
53
|
def http
|
|
35
54
|
@http ||= (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
http = new_http_client
|
|
56
|
+
if server_url.scheme == 'https'
|
|
57
|
+
http.use_ssl = true
|
|
58
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
59
|
+
end
|
|
41
60
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
61
|
+
# Defaulting open_timeout to nil to be consistent with Ruby 2.2 and earlier.
|
|
62
|
+
http.open_timeout = self.open_timeout
|
|
63
|
+
http.read_timeout = self.read_timeout if self.read_timeout
|
|
46
64
|
|
|
47
|
-
|
|
65
|
+
http
|
|
48
66
|
)
|
|
49
67
|
end
|
|
50
68
|
|
|
@@ -74,17 +92,13 @@ module Selenium
|
|
|
74
92
|
retries += 1
|
|
75
93
|
sleep 2
|
|
76
94
|
retry
|
|
77
|
-
|
|
78
95
|
rescue Errno::ECONNREFUSED => ex
|
|
79
|
-
if use_proxy?
|
|
80
|
-
|
|
81
|
-
else
|
|
82
|
-
raise
|
|
83
|
-
end
|
|
96
|
+
raise ex.class, "using proxy: #{proxy.http}" if use_proxy?
|
|
97
|
+
raise
|
|
84
98
|
end
|
|
85
99
|
|
|
86
|
-
if response.
|
|
87
|
-
raise Error::WebDriverError,
|
|
100
|
+
if response.is_a? Net::HTTPRedirection
|
|
101
|
+
raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
|
|
88
102
|
request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
|
|
89
103
|
else
|
|
90
104
|
create_response response.code, response.body, response.content_type
|
|
@@ -109,7 +123,8 @@ module Selenium
|
|
|
109
123
|
|
|
110
124
|
def new_http_client
|
|
111
125
|
if use_proxy?
|
|
112
|
-
|
|
126
|
+
url = @proxy.http
|
|
127
|
+
unless proxy.respond_to?(:http) && url
|
|
113
128
|
raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}"
|
|
114
129
|
end
|
|
115
130
|
|
|
@@ -124,13 +139,13 @@ module Selenium
|
|
|
124
139
|
|
|
125
140
|
def proxy
|
|
126
141
|
@proxy ||= (
|
|
127
|
-
|
|
128
|
-
|
|
142
|
+
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
|
143
|
+
no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
|
|
129
144
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
145
|
+
if proxy
|
|
146
|
+
proxy = "http://#{proxy}" unless proxy.start_with?('http://')
|
|
147
|
+
Proxy.new(http: proxy, no_proxy: no_proxy)
|
|
148
|
+
end
|
|
134
149
|
)
|
|
135
150
|
end
|
|
136
151
|
|
|
@@ -138,24 +153,22 @@ module Selenium
|
|
|
138
153
|
return false if proxy.nil?
|
|
139
154
|
|
|
140
155
|
if proxy.no_proxy
|
|
141
|
-
ignored = proxy.no_proxy.split(
|
|
142
|
-
host ==
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
ignored = proxy.no_proxy.split(',').any? do |host|
|
|
157
|
+
host == '*' ||
|
|
158
|
+
host == server_url.host || (
|
|
159
|
+
begin
|
|
160
|
+
IPAddr.new(host).include?(server_url.host)
|
|
161
|
+
rescue ArgumentError
|
|
162
|
+
false
|
|
163
|
+
end
|
|
164
|
+
)
|
|
151
165
|
end
|
|
152
166
|
|
|
153
|
-
|
|
167
|
+
!ignored
|
|
154
168
|
else
|
|
155
169
|
true
|
|
156
170
|
end
|
|
157
171
|
end
|
|
158
|
-
|
|
159
172
|
end # Default
|
|
160
173
|
end # Http
|
|
161
174
|
end # Remote
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
#
|
|
3
1
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
2
|
# or more contributor license agreements. See the NOTICE file
|
|
5
3
|
# distributed with this work for additional information
|
|
@@ -23,10 +21,8 @@ module Selenium
|
|
|
23
21
|
module WebDriver
|
|
24
22
|
module Remote
|
|
25
23
|
module Http
|
|
26
|
-
|
|
27
24
|
# @api private
|
|
28
25
|
class Persistent < Default
|
|
29
|
-
|
|
30
26
|
def close
|
|
31
27
|
@http.shutdown if @http
|
|
32
28
|
end
|
|
@@ -37,19 +33,24 @@ module Selenium
|
|
|
37
33
|
proxy = nil
|
|
38
34
|
|
|
39
35
|
if @proxy
|
|
40
|
-
unless @proxy.respond_to?(:http)
|
|
41
|
-
|
|
36
|
+
unless @proxy.respond_to?(:http)
|
|
37
|
+
url = @proxy.http
|
|
38
|
+
raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}" unless url
|
|
42
39
|
end
|
|
43
40
|
proxy = URI.parse(url)
|
|
44
41
|
end
|
|
45
42
|
|
|
46
|
-
Net::HTTP::Persistent
|
|
43
|
+
if Net::HTTP::Persistent::VERSION >= '3'
|
|
44
|
+
Net::HTTP::Persistent.new name: 'webdriver', proxy: proxy
|
|
45
|
+
else
|
|
46
|
+
WebDriver.logger.warn 'Support for this version of net-http-persistent is deprecated. Please upgrade.'
|
|
47
|
+
Net::HTTP::Persistent.new 'webdriver', proxy
|
|
48
|
+
end
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
def response_for(request)
|
|
50
52
|
http.request server_url, request
|
|
51
53
|
end
|
|
52
|
-
|
|
53
54
|
end # Persistent
|
|
54
55
|
end # Http
|
|
55
56
|
end # Remote
|
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
# or more contributor license agreements. See the NOTICE file
|
|
3
|
+
# distributed with this work for additional information
|
|
4
|
+
# regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
# to you under the Apache License, Version 2.0 (the
|
|
6
|
+
# "License"); you may not use this file except in compliance
|
|
7
|
+
# with the License. You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
18
|
+
module Selenium
|
|
19
|
+
module WebDriver
|
|
20
|
+
module Remote
|
|
21
|
+
module OSS
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# Low level bridge to the remote server implementing JSON wire
|
|
25
|
+
# protocol (OSS dialect), through which the rest of the API works.
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
|
|
29
|
+
class Bridge < Remote::Bridge
|
|
30
|
+
|
|
31
|
+
def initialize(capabilities, session_id, **opts)
|
|
32
|
+
@capabilities = capabilities
|
|
33
|
+
@session_id = session_id
|
|
34
|
+
super(opts)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def dialect
|
|
38
|
+
:oss
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def commands(command)
|
|
42
|
+
COMMANDS[command]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def status
|
|
46
|
+
execute :status
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get(url)
|
|
50
|
+
execute :get, {}, {url: url}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def session_capabilities
|
|
54
|
+
Capabilities.json_create execute(:get_capabilities)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def implicit_wait_timeout=(milliseconds)
|
|
58
|
+
execute :implicitly_wait, {}, {ms: milliseconds}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def script_timeout=(milliseconds)
|
|
62
|
+
execute :set_script_timeout, {}, {ms: milliseconds}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def timeout(type, milliseconds)
|
|
66
|
+
execute :set_timeout, {}, {type: type, ms: milliseconds}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
#
|
|
70
|
+
# alerts
|
|
71
|
+
#
|
|
72
|
+
|
|
73
|
+
def accept_alert
|
|
74
|
+
execute :accept_alert
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def dismiss_alert
|
|
78
|
+
execute :dismiss_alert
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def alert=(keys)
|
|
82
|
+
execute :set_alert_value, {}, {text: keys.to_s}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def alert_text
|
|
86
|
+
execute :get_alert_text
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def authentication(credentials)
|
|
90
|
+
execute :set_authentication, {}, credentials
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#
|
|
94
|
+
# navigation
|
|
95
|
+
#
|
|
96
|
+
|
|
97
|
+
def go_back
|
|
98
|
+
execute :go_back
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def go_forward
|
|
102
|
+
execute :go_forward
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def url
|
|
106
|
+
execute :get_current_url
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def title
|
|
110
|
+
execute :get_title
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def page_source
|
|
114
|
+
execute :get_page_source
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def switch_to_window(name)
|
|
118
|
+
execute :switch_to_window, {}, {name: name}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def switch_to_frame(id)
|
|
122
|
+
execute :switch_to_frame, {}, {id: id}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def switch_to_parent_frame
|
|
126
|
+
execute :switch_to_parent_frame
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def switch_to_default_content
|
|
130
|
+
switch_to_frame(nil)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def quit
|
|
134
|
+
execute :quit
|
|
135
|
+
http.close
|
|
136
|
+
rescue *http.quit_errors
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def close
|
|
140
|
+
execute :close
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def refresh
|
|
144
|
+
execute :refresh
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
#
|
|
148
|
+
# window handling
|
|
149
|
+
#
|
|
150
|
+
|
|
151
|
+
def window_handles
|
|
152
|
+
execute :get_window_handles
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def window_handle
|
|
156
|
+
execute :get_current_window_handle
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def resize_window(width, height, handle = :current)
|
|
160
|
+
execute :set_window_size, {window_handle: handle},
|
|
161
|
+
{width: width,
|
|
162
|
+
height: height}
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def maximize_window(handle = :current)
|
|
166
|
+
execute :maximize_window, window_handle: handle
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def window_size(handle = :current)
|
|
170
|
+
data = execute :get_window_size, window_handle: handle
|
|
171
|
+
|
|
172
|
+
Dimension.new data['width'], data['height']
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def reposition_window(x, y, handle = :current)
|
|
176
|
+
execute :set_window_position, {window_handle: handle},
|
|
177
|
+
{x: x, y: y}
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def window_position(handle = :current)
|
|
181
|
+
data = execute :get_window_position, window_handle: handle
|
|
182
|
+
|
|
183
|
+
Point.new data['x'], data['y']
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def screenshot
|
|
187
|
+
execute :screenshot
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
#
|
|
191
|
+
# HTML 5
|
|
192
|
+
#
|
|
193
|
+
|
|
194
|
+
def local_storage_item(key, value = nil)
|
|
195
|
+
if value
|
|
196
|
+
execute :set_local_storage_item, {}, {key: key, value: value}
|
|
197
|
+
else
|
|
198
|
+
execute :get_local_storage_item, key: key
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def remove_local_storage_item(key)
|
|
203
|
+
execute :remove_local_storage_item, key: key
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def local_storage_keys
|
|
207
|
+
execute :get_local_storage_keys
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def clear_local_storage
|
|
211
|
+
execute :clear_local_storage
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def local_storage_size
|
|
215
|
+
execute :get_local_storage_size
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def session_storage_item(key, value = nil)
|
|
219
|
+
if value
|
|
220
|
+
execute :set_session_storage_item, {}, {key: key, value: value}
|
|
221
|
+
else
|
|
222
|
+
execute :get_session_storage_item, key: key
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def remove_session_storage_item(key)
|
|
227
|
+
execute :remove_session_storage_item, key: key
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def session_storage_keys
|
|
231
|
+
execute :get_session_storage_keys
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def clear_session_storage
|
|
235
|
+
execute :clear_session_storage
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def session_storage_size
|
|
239
|
+
execute :get_session_storage_size
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def location
|
|
243
|
+
obj = execute(:get_location) || {}
|
|
244
|
+
Location.new obj['latitude'], obj['longitude'], obj['altitude']
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def set_location(lat, lon, alt)
|
|
248
|
+
loc = {latitude: lat, longitude: lon, altitude: alt}
|
|
249
|
+
execute :set_location, {}, {location: loc}
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def network_connection
|
|
253
|
+
execute :get_network_connection
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def network_connection=(type)
|
|
257
|
+
execute :set_network_connection, {}, {parameters: {type: type}}
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
#
|
|
261
|
+
# javascript execution
|
|
262
|
+
#
|
|
263
|
+
|
|
264
|
+
def execute_script(script, *args)
|
|
265
|
+
assert_javascript_enabled
|
|
266
|
+
|
|
267
|
+
result = execute :execute_script, {}, {script: script, args: args}
|
|
268
|
+
unwrap_script_result result
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def execute_async_script(script, *args)
|
|
272
|
+
assert_javascript_enabled
|
|
273
|
+
|
|
274
|
+
result = execute :execute_async_script, {}, {script: script, args: args}
|
|
275
|
+
unwrap_script_result result
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
#
|
|
279
|
+
# cookies
|
|
280
|
+
#
|
|
281
|
+
|
|
282
|
+
def options
|
|
283
|
+
@options ||= WebDriver::Options.new(self)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def add_cookie(cookie)
|
|
287
|
+
execute :add_cookie, {}, {cookie: cookie}
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def delete_cookie(name)
|
|
291
|
+
execute :delete_cookie, name: name
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def cookies
|
|
295
|
+
execute :get_cookies
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def delete_all_cookies
|
|
299
|
+
execute :delete_all_cookies
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
#
|
|
303
|
+
# actions
|
|
304
|
+
#
|
|
305
|
+
|
|
306
|
+
#
|
|
307
|
+
# @return [ActionBuilder]
|
|
308
|
+
# @api public
|
|
309
|
+
#
|
|
310
|
+
|
|
311
|
+
def action
|
|
312
|
+
ActionBuilder.new Mouse.new(self), Keyboard.new(self)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def mouse
|
|
316
|
+
WebDriver.logger.deprecate 'Driver#mouse', 'driver.action.<command>.perform'
|
|
317
|
+
Mouse.new self
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def keyboard
|
|
321
|
+
WebDriver.logger.deprecate 'Driver#keyboard', 'driver.action.<command>.perform'
|
|
322
|
+
Keyboard.new self
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def click_element(element)
|
|
326
|
+
execute :click_element, id: element
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def click
|
|
330
|
+
execute :click, {}, {button: 0}
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def double_click
|
|
334
|
+
execute :double_click
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def context_click
|
|
338
|
+
execute :click, {}, {button: 2}
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def mouse_down
|
|
342
|
+
execute :mouse_down
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def mouse_up
|
|
346
|
+
execute :mouse_up
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def mouse_move_to(element, x = nil, y = nil)
|
|
350
|
+
params = {element: element}
|
|
351
|
+
|
|
352
|
+
if x && y
|
|
353
|
+
params[:xoffset] = x
|
|
354
|
+
params[:yoffset] = y
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
execute :mouse_move_to, {}, params
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def send_keys_to_active_element(key)
|
|
361
|
+
execute :send_keys_to_active_element, {}, {value: key}
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def send_keys_to_element(element, keys)
|
|
365
|
+
if @file_detector
|
|
366
|
+
local_file = @file_detector.call(keys)
|
|
367
|
+
keys = upload(local_file) if local_file
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
execute :send_keys_to_element, {id: element}, {value: Array(keys)}
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def upload(local_file)
|
|
374
|
+
unless File.file?(local_file)
|
|
375
|
+
raise Error::WebDriverError, "you may only upload files: #{local_file.inspect}"
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def clear_element(element)
|
|
382
|
+
execute :clear_element, id: element
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def submit_element(element)
|
|
386
|
+
execute :submit_element, id: element
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def drag_element(element, right_by, down_by)
|
|
390
|
+
execute :drag_element, {id: element}, {x: right_by, y: down_by}
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def touch_single_tap(element)
|
|
394
|
+
execute :touch_single_tap, {}, {element: element}
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def touch_double_tap(element)
|
|
398
|
+
execute :touch_double_tap, {}, {element: element}
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def touch_long_press(element)
|
|
402
|
+
execute :touch_long_press, {}, {element: element}
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def touch_down(x, y)
|
|
406
|
+
execute :touch_down, {}, {x: x, y: y}
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def touch_up(x, y)
|
|
410
|
+
execute :touch_up, {}, {x: x, y: y}
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def touch_move(x, y)
|
|
414
|
+
execute :touch_move, {}, {x: x, y: y}
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def touch_scroll(element, x, y)
|
|
418
|
+
if element
|
|
419
|
+
execute :touch_scroll, {}, {element: element,
|
|
420
|
+
xoffset: x,
|
|
421
|
+
yoffset: y}
|
|
422
|
+
else
|
|
423
|
+
execute :touch_scroll, {}, {xoffset: x, yoffset: y}
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
def touch_flick(xspeed, yspeed)
|
|
428
|
+
execute :touch_flick, {}, {xspeed: xspeed, yspeed: yspeed}
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def touch_element_flick(element, right_by, down_by, speed)
|
|
432
|
+
execute :touch_flick, {}, {element: element,
|
|
433
|
+
xoffset: right_by,
|
|
434
|
+
yoffset: down_by,
|
|
435
|
+
speed: speed}
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def screen_orientation=(orientation)
|
|
439
|
+
execute :set_screen_orientation, {}, {orientation: orientation}
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
def screen_orientation
|
|
443
|
+
execute :get_screen_orientation
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
#
|
|
447
|
+
# logs
|
|
448
|
+
#
|
|
449
|
+
|
|
450
|
+
def available_log_types
|
|
451
|
+
types = execute :get_available_log_types
|
|
452
|
+
Array(types).map(&:to_sym)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def log(type)
|
|
456
|
+
data = execute :get_log, {}, {type: type.to_s}
|
|
457
|
+
|
|
458
|
+
Array(data).map do |l|
|
|
459
|
+
begin
|
|
460
|
+
LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
|
|
461
|
+
rescue KeyError
|
|
462
|
+
next
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
#
|
|
468
|
+
# element properties
|
|
469
|
+
#
|
|
470
|
+
|
|
471
|
+
def element_tag_name(element)
|
|
472
|
+
execute :get_element_tag_name, id: element
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def element_attribute(element, name)
|
|
476
|
+
execute :get_element_attribute, id: element.ref, name: name
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
# Backwards compatibility for w3c
|
|
480
|
+
def element_property(element, name)
|
|
481
|
+
execute_script 'return arguments[0][arguments[1]]', element, name
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def element_value(element)
|
|
485
|
+
execute :get_element_value, id: element
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def element_text(element)
|
|
489
|
+
execute :get_element_text, id: element
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def element_location(element)
|
|
493
|
+
data = execute :get_element_location, id: element
|
|
494
|
+
|
|
495
|
+
Point.new data['x'], data['y']
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def element_rect(element)
|
|
499
|
+
loc = execute :get_element_location, id: element
|
|
500
|
+
size = execute :get_element_size, id: element
|
|
501
|
+
|
|
502
|
+
Rectangle.new loc['x'], loc['y'], size['width'], size['height']
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def element_location_once_scrolled_into_view(element)
|
|
506
|
+
data = execute :get_element_location_once_scrolled_into_view, id: element
|
|
507
|
+
|
|
508
|
+
Point.new data['x'], data['y']
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
def element_size(element)
|
|
512
|
+
data = execute :get_element_size, id: element
|
|
513
|
+
|
|
514
|
+
Dimension.new data['width'], data['height']
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def element_enabled?(element)
|
|
518
|
+
execute :is_element_enabled, id: element
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def element_selected?(element)
|
|
522
|
+
execute :is_element_selected, id: element
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def element_displayed?(element)
|
|
526
|
+
execute :is_element_displayed, id: element
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def element_value_of_css_property(element, prop)
|
|
530
|
+
execute :get_element_value_of_css_property, id: element, property_name: prop
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
#
|
|
534
|
+
# finding elements
|
|
535
|
+
#
|
|
536
|
+
|
|
537
|
+
def active_element
|
|
538
|
+
Element.new self, element_id_from(execute(:get_active_element))
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
alias_method :switch_to_active_element, :active_element
|
|
542
|
+
|
|
543
|
+
def find_element_by(how, what, parent = nil)
|
|
544
|
+
id = if parent
|
|
545
|
+
execute :find_child_element, {id: parent}, {using: how, value: what}
|
|
546
|
+
else
|
|
547
|
+
execute :find_element, {}, {using: how, value: what}
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
Element.new self, element_id_from(id)
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
def find_elements_by(how, what, parent = nil)
|
|
554
|
+
ids = if parent
|
|
555
|
+
execute :find_child_elements, {id: parent}, {using: how, value: what}
|
|
556
|
+
else
|
|
557
|
+
execute :find_elements, {}, {using: how, value: what}
|
|
558
|
+
end
|
|
559
|
+
# see https://github.com/SeleniumHQ/selenium/issues/4555
|
|
560
|
+
ids ||= []
|
|
561
|
+
|
|
562
|
+
ids.map { |id| Element.new self, element_id_from(id) }
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
private
|
|
566
|
+
|
|
567
|
+
def assert_javascript_enabled
|
|
568
|
+
return if capabilities.javascript_enabled?
|
|
569
|
+
raise Error::UnsupportedOperationError, 'underlying webdriver instance does not support javascript'
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
#
|
|
573
|
+
# executes a command on the remote server.
|
|
574
|
+
#
|
|
575
|
+
# Returns the 'value' of the returned payload
|
|
576
|
+
#
|
|
577
|
+
|
|
578
|
+
def execute(*args)
|
|
579
|
+
super['value']
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
end # Bridge
|
|
583
|
+
end # OSS
|
|
584
|
+
end # Remote
|
|
585
|
+
end # WebDriver
|
|
586
|
+
end # Selenium
|