selenium-webdriver 3.0.0.beta4.0 → 4.0.0.alpha5
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 +679 -0
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/lib/selenium-webdriver.rb +2 -2
- data/lib/selenium/server.rb +23 -16
- data/lib/selenium/webdriver.rb +43 -25
- data/lib/selenium/webdriver/atoms.rb +20 -1
- data/lib/selenium/webdriver/atoms/findElements.js +122 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +84 -11
- data/lib/selenium/webdriver/atoms/isDisplayed.js +100 -0
- data/lib/selenium/webdriver/chrome.rb +15 -20
- data/lib/selenium/webdriver/chrome/bridge.rb +29 -66
- data/lib/selenium/webdriver/{edge/service.rb → chrome/driver.rb} +19 -22
- data/lib/selenium/webdriver/chrome/options.rb +221 -0
- data/lib/selenium/webdriver/chrome/profile.rb +6 -7
- data/lib/selenium/webdriver/chrome/service.rb +20 -20
- data/lib/selenium/webdriver/common.rb +19 -11
- data/lib/selenium/webdriver/common/action_builder.rb +98 -246
- data/lib/selenium/webdriver/common/alert.rb +2 -7
- data/lib/selenium/webdriver/common/driver.rb +89 -51
- data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_debugger.rb} +12 -25
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +3 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +3 -3
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +2 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +2 -2
- data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +2 -2
- data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +4 -4
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +9 -3
- data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +3 -5
- data/lib/selenium/webdriver/common/element.rb +32 -10
- data/lib/selenium/webdriver/common/error.rb +103 -121
- data/lib/selenium/webdriver/common/file_reaper.rb +3 -5
- data/lib/selenium/webdriver/common/html5/local_storage.rb +2 -2
- data/lib/selenium/webdriver/common/html5/session_storage.rb +2 -2
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +3 -2
- data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
- data/lib/selenium/webdriver/{phantomjs.rb → common/interactions/interactions.rb} +17 -20
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
- data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
- data/lib/selenium/webdriver/common/interactions/none_input.rb +36 -0
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
- data/lib/selenium/webdriver/common/keys.rb +37 -15
- data/lib/selenium/webdriver/common/log_entry.rb +4 -4
- data/lib/selenium/webdriver/common/logger.rb +147 -0
- data/lib/selenium/webdriver/common/logs.rb +2 -2
- data/lib/selenium/webdriver/common/manager.rb +177 -0
- data/lib/selenium/webdriver/common/navigation.rb +2 -2
- data/lib/selenium/webdriver/common/options.rb +47 -105
- data/lib/selenium/webdriver/common/platform.rb +44 -38
- data/lib/selenium/webdriver/common/port_prober.rb +8 -19
- data/lib/selenium/webdriver/common/profile_helper.rb +13 -5
- data/lib/selenium/webdriver/common/proxy.rb +14 -8
- data/lib/selenium/webdriver/common/search_context.rb +16 -20
- data/lib/selenium/webdriver/common/service.rb +115 -30
- data/lib/selenium/webdriver/common/socket_lock.rb +12 -7
- data/lib/selenium/webdriver/common/socket_poller.rb +29 -22
- data/lib/selenium/webdriver/common/target_locator.rb +6 -6
- data/lib/selenium/webdriver/common/timeouts.rb +2 -2
- data/lib/selenium/webdriver/common/wait.rb +14 -8
- data/lib/selenium/webdriver/common/window.rb +38 -2
- data/lib/selenium/webdriver/common/zipper.rb +3 -5
- data/lib/selenium/webdriver/edge.rb +33 -20
- data/lib/selenium/webdriver/edge_chrome/bridge.rb +30 -0
- data/lib/selenium/webdriver/edge_chrome/driver.rb +38 -0
- data/lib/selenium/webdriver/{common/driver_extensions/has_touch_screen.rb → edge_chrome/options.rb} +10 -12
- data/lib/selenium/webdriver/edge_chrome/profile.rb +33 -0
- data/lib/selenium/webdriver/edge_chrome/service.rb +36 -0
- data/lib/selenium/webdriver/edge_html/driver.rb +39 -0
- data/lib/selenium/webdriver/edge_html/options.rb +91 -0
- data/lib/selenium/webdriver/edge_html/service.rb +47 -0
- data/lib/selenium/webdriver/firefox.rb +24 -29
- data/lib/selenium/webdriver/firefox/bridge.rb +15 -39
- data/lib/selenium/webdriver/firefox/{util.rb → driver.rb} +13 -19
- data/lib/selenium/webdriver/firefox/extension.rb +28 -8
- data/lib/selenium/webdriver/firefox/options.rb +162 -0
- data/lib/selenium/webdriver/firefox/profile.rb +23 -82
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +5 -5
- data/lib/selenium/webdriver/firefox/service.rb +18 -37
- data/lib/selenium/webdriver/ie.rb +13 -19
- data/lib/selenium/webdriver/ie/driver.rb +40 -0
- data/lib/selenium/webdriver/ie/options.rb +118 -0
- data/lib/selenium/webdriver/ie/service.rb +20 -20
- data/lib/selenium/webdriver/remote.rb +15 -17
- data/lib/selenium/webdriver/remote/bridge.rb +281 -300
- data/lib/selenium/webdriver/remote/capabilities.rb +102 -83
- data/lib/selenium/webdriver/remote/commands.rb +132 -192
- data/lib/selenium/webdriver/remote/driver.rb +52 -0
- data/lib/selenium/webdriver/remote/http/common.rb +23 -13
- data/lib/selenium/webdriver/remote/http/curb.rb +10 -7
- data/lib/selenium/webdriver/remote/http/default.rb +52 -32
- data/lib/selenium/webdriver/remote/http/persistent.rb +8 -4
- data/lib/selenium/webdriver/remote/response.rb +32 -35
- data/lib/selenium/webdriver/remote/server_error.rb +2 -2
- data/lib/selenium/webdriver/safari.rb +24 -22
- data/lib/selenium/webdriver/safari/bridge.rb +21 -21
- data/lib/selenium/webdriver/safari/driver.rb +41 -0
- data/lib/selenium/webdriver/safari/options.rb +66 -0
- data/lib/selenium/webdriver/safari/service.rb +8 -24
- data/lib/selenium/webdriver/support.rb +3 -2
- data/lib/selenium/webdriver/support/abstract_event_listener.rb +2 -2
- data/lib/selenium/webdriver/support/block_event_listener.rb +3 -3
- data/lib/selenium/webdriver/support/color.rb +13 -13
- data/lib/selenium/webdriver/support/escaper.rb +2 -2
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
- data/lib/selenium/webdriver/support/select.rb +20 -21
- data/lib/selenium/webdriver/version.rb +24 -0
- data/selenium-webdriver.gemspec +31 -17
- metadata +331 -248
- data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
- data/lib/selenium/webdriver/common/keyboard.rb +0 -69
- data/lib/selenium/webdriver/common/mouse.rb +0 -88
- data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -81
- data/lib/selenium/webdriver/common/touch_screen.rb +0 -121
- data/lib/selenium/webdriver/common/w3c_error.rb +0 -191
- data/lib/selenium/webdriver/edge/bridge.rb +0 -76
- data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
- data/lib/selenium/webdriver/firefox/binary.rb +0 -186
- data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/launcher.rb +0 -114
- data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/firefox/w3c_bridge.rb +0 -79
- data/lib/selenium/webdriver/ie/bridge.rb +0 -76
- data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -65
- data/lib/selenium/webdriver/phantomjs/service.rb +0 -66
- data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -682
- data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -228
- data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -135
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
3
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
4
|
# or more contributor license agreements. See the NOTICE file
|
|
5
5
|
# distributed with this work for additional information
|
|
@@ -22,7 +22,7 @@ module Selenium
|
|
|
22
22
|
module Keys
|
|
23
23
|
#
|
|
24
24
|
# @see Element#send_keys
|
|
25
|
-
# @see http://www.google.com.au/search?&q=unicode+pua&
|
|
25
|
+
# @see http://www.google.com.au/search?&q=unicode+pua&btnK=Search
|
|
26
26
|
#
|
|
27
27
|
|
|
28
28
|
KEYS = {
|
|
@@ -88,7 +88,22 @@ module Selenium
|
|
|
88
88
|
f11: "\ue03B",
|
|
89
89
|
f12: "\ue03C",
|
|
90
90
|
meta: "\ue03D",
|
|
91
|
-
command: "\ue03D" # alias
|
|
91
|
+
command: "\ue03D", # alias
|
|
92
|
+
left_meta: "\ue03D", # alias
|
|
93
|
+
right_shift: "\ue050",
|
|
94
|
+
right_control: "\ue051",
|
|
95
|
+
right_alt: "\ue052",
|
|
96
|
+
right_meta: "\ue053",
|
|
97
|
+
numpad_page_up: "\ue054",
|
|
98
|
+
numpad_page_down: "\ue055",
|
|
99
|
+
numpad_end: "\ue056",
|
|
100
|
+
numpad_home: "\ue057",
|
|
101
|
+
numpad_left: "\ue058",
|
|
102
|
+
numpad_up: "\ue059",
|
|
103
|
+
numpad_right: "\ue05A",
|
|
104
|
+
numpad_down: "\ue05B",
|
|
105
|
+
numpad_insert: "\ue05C",
|
|
106
|
+
numpad_delete: "\ue05D"
|
|
92
107
|
}.freeze
|
|
93
108
|
|
|
94
109
|
#
|
|
@@ -97,6 +112,7 @@ module Selenium
|
|
|
97
112
|
|
|
98
113
|
def self.[](key)
|
|
99
114
|
return KEYS[key] if KEYS[key]
|
|
115
|
+
|
|
100
116
|
raise Error::UnsupportedOperationError, "no such key #{key.inspect}"
|
|
101
117
|
end
|
|
102
118
|
|
|
@@ -105,18 +121,24 @@ module Selenium
|
|
|
105
121
|
#
|
|
106
122
|
|
|
107
123
|
def self.encode(keys)
|
|
108
|
-
keys.map
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
keys.map { |key| encode_key(key) }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# @api private
|
|
129
|
+
#
|
|
130
|
+
|
|
131
|
+
def self.encode_key(key)
|
|
132
|
+
case key
|
|
133
|
+
when Symbol
|
|
134
|
+
Keys[key]
|
|
135
|
+
when Array
|
|
136
|
+
key = key.map { |e| e.is_a?(Symbol) ? Keys[e] : e }.join
|
|
137
|
+
key << Keys[:null]
|
|
115
138
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
end
|
|
139
|
+
key
|
|
140
|
+
else
|
|
141
|
+
key.to_s
|
|
120
142
|
end
|
|
121
143
|
end
|
|
122
144
|
end # Keys
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
3
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
4
|
# or more contributor license agreements. See the NOTICE file
|
|
5
5
|
# distributed with this work for additional information
|
|
@@ -30,9 +30,9 @@ module Selenium
|
|
|
30
30
|
|
|
31
31
|
def as_json(*)
|
|
32
32
|
{
|
|
33
|
-
'level'
|
|
33
|
+
'level' => level,
|
|
34
34
|
'timestamp' => timestamp,
|
|
35
|
-
'message'
|
|
35
|
+
'message' => message
|
|
36
36
|
}
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
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
|
+
require 'forwardable'
|
|
21
|
+
require 'logger'
|
|
22
|
+
|
|
23
|
+
module Selenium
|
|
24
|
+
module WebDriver
|
|
25
|
+
#
|
|
26
|
+
# @example Enable full logging
|
|
27
|
+
# Selenium::WebDriver.logger.level = :debug
|
|
28
|
+
#
|
|
29
|
+
# @example Log to file
|
|
30
|
+
# Selenium::WebDriver.logger.output = 'selenium.log'
|
|
31
|
+
#
|
|
32
|
+
# @example Use logger manually
|
|
33
|
+
# Selenium::WebDriver.logger.info('This is info message')
|
|
34
|
+
# Selenium::WebDriver.logger.warn('This is warning message')
|
|
35
|
+
#
|
|
36
|
+
class Logger
|
|
37
|
+
extend Forwardable
|
|
38
|
+
|
|
39
|
+
def_delegators :@logger,
|
|
40
|
+
:close,
|
|
41
|
+
:debug, :debug?,
|
|
42
|
+
:info, :info?,
|
|
43
|
+
:warn, :warn?,
|
|
44
|
+
:error, :error?,
|
|
45
|
+
:fatal, :fatal?,
|
|
46
|
+
:level, :level=
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# @param [String] progname Allow child projects to use Selenium's Logger pattern
|
|
50
|
+
#
|
|
51
|
+
def initialize(progname = 'Selenium')
|
|
52
|
+
@logger = create_logger(progname)
|
|
53
|
+
@ignored = []
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Changes logger output to a new IO.
|
|
58
|
+
#
|
|
59
|
+
# @param [String] io
|
|
60
|
+
#
|
|
61
|
+
def output=(io)
|
|
62
|
+
@logger.reopen(io)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Returns IO object used by logger internally.
|
|
67
|
+
#
|
|
68
|
+
# Normally, we would have never needed it, but we want to
|
|
69
|
+
# use it as IO object for all child processes to ensure their
|
|
70
|
+
# output is redirected there.
|
|
71
|
+
#
|
|
72
|
+
# It is only used in debug level, in other cases output is suppressed.
|
|
73
|
+
#
|
|
74
|
+
# @api private
|
|
75
|
+
#
|
|
76
|
+
def io
|
|
77
|
+
@logger.instance_variable_get(:@logdev).dev
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# Will not log the provided ID.
|
|
82
|
+
#
|
|
83
|
+
# @param [Array, Symbol] id
|
|
84
|
+
#
|
|
85
|
+
def ignore(id)
|
|
86
|
+
Array(id).each { |ignore| @ignored << ignore }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Overrides default #warn to skip ignored messages by provided id
|
|
91
|
+
#
|
|
92
|
+
# @param [String] message
|
|
93
|
+
# @param [Symbol, Array<Sybmol>] id
|
|
94
|
+
# @yield see #deprecate
|
|
95
|
+
#
|
|
96
|
+
def warn(message, id: [])
|
|
97
|
+
id = Array(id)
|
|
98
|
+
return if (@ignored & id).any?
|
|
99
|
+
|
|
100
|
+
msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
|
|
101
|
+
msg += " #{yield}" if block_given?
|
|
102
|
+
|
|
103
|
+
@logger.warn { msg }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
# Marks code as deprecated with/without replacement.
|
|
108
|
+
#
|
|
109
|
+
# @param [String] old
|
|
110
|
+
# @param [String, nil] new
|
|
111
|
+
# @param [Symbol, Array<Sybmol>] id
|
|
112
|
+
# @yield appends additional message to end of provided template
|
|
113
|
+
#
|
|
114
|
+
def deprecate(old, new = nil, id: [], &block)
|
|
115
|
+
id = Array(id)
|
|
116
|
+
return if @ignored.include?(:deprecations) || (@ignored & id).any?
|
|
117
|
+
|
|
118
|
+
ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
|
|
119
|
+
|
|
120
|
+
message = +"[DEPRECATION] #{ids}#{old} is deprecated"
|
|
121
|
+
message << if new
|
|
122
|
+
". Use #{new} instead."
|
|
123
|
+
else
|
|
124
|
+
' and will be removed in a future release.'
|
|
125
|
+
end
|
|
126
|
+
warn message, &block
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
def create_logger(name)
|
|
132
|
+
logger = ::Logger.new($stdout)
|
|
133
|
+
logger.progname = name
|
|
134
|
+
logger.level = default_level
|
|
135
|
+
logger.formatter = proc do |severity, time, progname, msg|
|
|
136
|
+
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
logger
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def default_level
|
|
143
|
+
$DEBUG || ENV.key?('DEBUG') ? :debug : :warn
|
|
144
|
+
end
|
|
145
|
+
end # Logger
|
|
146
|
+
end # WebDriver
|
|
147
|
+
end # Selenium
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
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 Manager
|
|
23
|
+
#
|
|
24
|
+
# @api private
|
|
25
|
+
#
|
|
26
|
+
|
|
27
|
+
def initialize(bridge)
|
|
28
|
+
@bridge = bridge
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#
|
|
32
|
+
# Add a cookie to the browser
|
|
33
|
+
#
|
|
34
|
+
# @param [Hash] opts the options to create a cookie with.
|
|
35
|
+
# @option opts [String] :name A name
|
|
36
|
+
# @option opts [String] :value A value
|
|
37
|
+
# @option opts [String] :path ('/') A path
|
|
38
|
+
# @option opts [String] :secure (false) A boolean
|
|
39
|
+
# @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
|
|
40
|
+
#
|
|
41
|
+
# @raise [ArgumentError] if :name or :value is not specified
|
|
42
|
+
#
|
|
43
|
+
|
|
44
|
+
def add_cookie(opts = {})
|
|
45
|
+
raise ArgumentError, 'name is required' unless opts[:name]
|
|
46
|
+
raise ArgumentError, 'value is required' unless opts[:value]
|
|
47
|
+
|
|
48
|
+
opts[:path] ||= '/'
|
|
49
|
+
opts[:secure] ||= false
|
|
50
|
+
|
|
51
|
+
obj = opts.delete(:expires)
|
|
52
|
+
opts[:expiry] = seconds_from(obj).to_i if obj
|
|
53
|
+
|
|
54
|
+
@bridge.add_cookie opts
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# Get the cookie with the given name
|
|
59
|
+
#
|
|
60
|
+
# @param [String] name the name of the cookie
|
|
61
|
+
# @return [Hash, nil] the cookie, or nil if it wasn't found.
|
|
62
|
+
#
|
|
63
|
+
|
|
64
|
+
def cookie_named(name)
|
|
65
|
+
convert_cookie(@bridge.cookie(name))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# Delete the cookie with the given name
|
|
70
|
+
#
|
|
71
|
+
# @param [String] name the name of the cookie to delete
|
|
72
|
+
#
|
|
73
|
+
|
|
74
|
+
def delete_cookie(name)
|
|
75
|
+
@bridge.delete_cookie name
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Delete all cookies
|
|
80
|
+
#
|
|
81
|
+
|
|
82
|
+
def delete_all_cookies
|
|
83
|
+
@bridge.delete_all_cookies
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
#
|
|
87
|
+
# Get all cookies
|
|
88
|
+
#
|
|
89
|
+
# @return [Array<Hash>] list of cookies
|
|
90
|
+
#
|
|
91
|
+
|
|
92
|
+
def all_cookies
|
|
93
|
+
@bridge.cookies.map { |cookie| convert_cookie(cookie) }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def timeouts
|
|
97
|
+
@timeouts ||= Timeouts.new(@bridge)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# @api beta This API may be changed or removed in a future release.
|
|
102
|
+
#
|
|
103
|
+
|
|
104
|
+
def logs
|
|
105
|
+
@logs ||= Logs.new(@bridge)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# Create a new top-level browsing context
|
|
110
|
+
# https://w3c.github.io/webdriver/#new-window
|
|
111
|
+
# @param type [Symbol] Supports two values: :tab and :window.
|
|
112
|
+
# Use :tab if you'd like the new window to share an OS-level window
|
|
113
|
+
# with the current browsing context.
|
|
114
|
+
# Use :window otherwise
|
|
115
|
+
# @return [String] The value of the window handle
|
|
116
|
+
#
|
|
117
|
+
def new_window(type = :tab)
|
|
118
|
+
case type
|
|
119
|
+
when :tab, :window
|
|
120
|
+
result = @bridge.new_window(type)
|
|
121
|
+
unless result.key?('handle')
|
|
122
|
+
raise UnknownError, "the driver did not return a handle. " \
|
|
123
|
+
"The returned result: #{result.inspect}"
|
|
124
|
+
end
|
|
125
|
+
result['handle']
|
|
126
|
+
else
|
|
127
|
+
raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
|
|
128
|
+
"Try :tab or :window"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
#
|
|
133
|
+
# @api beta This API may be changed or removed in a future release.
|
|
134
|
+
#
|
|
135
|
+
|
|
136
|
+
def window
|
|
137
|
+
@window ||= Window.new(@bridge)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
SECONDS_PER_DAY = 86_400.0
|
|
143
|
+
|
|
144
|
+
def datetime_at(int)
|
|
145
|
+
DateTime.civil(1970) + (int / SECONDS_PER_DAY)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def seconds_from(obj)
|
|
149
|
+
case obj
|
|
150
|
+
when Time
|
|
151
|
+
obj.to_f
|
|
152
|
+
when DateTime
|
|
153
|
+
(obj - DateTime.civil(1970)) * SECONDS_PER_DAY
|
|
154
|
+
when Numeric
|
|
155
|
+
obj
|
|
156
|
+
else
|
|
157
|
+
raise ArgumentError, "invalid value for expiration date: #{obj.inspect}"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def strip_port(str)
|
|
162
|
+
str.split(':', 2).first
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def convert_cookie(cookie)
|
|
166
|
+
{
|
|
167
|
+
name: cookie['name'],
|
|
168
|
+
value: cookie['value'],
|
|
169
|
+
path: cookie['path'],
|
|
170
|
+
domain: cookie['domain'] && strip_port(cookie['domain']),
|
|
171
|
+
expires: cookie['expiry'] && datetime_at(cookie['expiry']),
|
|
172
|
+
secure: cookie['secure']
|
|
173
|
+
}
|
|
174
|
+
end
|
|
175
|
+
end # Options
|
|
176
|
+
end # WebDriver
|
|
177
|
+
end # Selenium
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
3
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
4
|
# or more contributor license agreements. See the NOTICE file
|
|
5
5
|
# distributed with this work for additional information
|
|
@@ -20,131 +20,73 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
class Options
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
attr_accessor :options
|
|
24
|
+
|
|
25
|
+
def initialize(options: nil, **opts)
|
|
26
|
+
@options = if options
|
|
27
|
+
WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
|
|
28
|
+
"custom values directly in #new constructor",
|
|
29
|
+
id: :options_options)
|
|
30
|
+
opts.merge(options)
|
|
31
|
+
else
|
|
32
|
+
opts
|
|
33
|
+
end
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
#
|
|
32
|
-
# Add a
|
|
37
|
+
# Add a new option not yet handled by bindings.
|
|
33
38
|
#
|
|
34
|
-
# @
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# @option opts [String] :path ('/') A path
|
|
38
|
-
# @option opts [String] :secure (false) A boolean
|
|
39
|
-
# @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
|
|
39
|
+
# @example Leave Chrome open when chromedriver is killed
|
|
40
|
+
# options = Selenium::WebDriver::Chrome::Options.new
|
|
41
|
+
# options.add_option(:detach, true)
|
|
40
42
|
#
|
|
41
|
-
# @
|
|
43
|
+
# @param [String, Symbol] name Name of the option
|
|
44
|
+
# @param [Boolean, String, Integer] value Value of the option
|
|
42
45
|
#
|
|
43
46
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
raise ArgumentError, 'value is required' unless opts[:value]
|
|
47
|
-
|
|
48
|
-
opts[:path] ||= '/'
|
|
49
|
-
opts[:secure] ||= false
|
|
50
|
-
|
|
51
|
-
obj = opts.delete(:expires)
|
|
52
|
-
opts[:expiry] = seconds_from(obj).to_i if obj
|
|
53
|
-
|
|
54
|
-
@bridge.add_cookie opts
|
|
47
|
+
def add_option(name, value)
|
|
48
|
+
@options[name] = value
|
|
55
49
|
end
|
|
56
50
|
|
|
57
51
|
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
# @param [String] name the name of the cookie
|
|
61
|
-
# @return [Hash, nil] the cookie, or nil if it wasn't found.
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
def cookie_named(name)
|
|
65
|
-
all_cookies.find { |c| c[:name] == name }
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
# Delete the cookie with the given name
|
|
70
|
-
#
|
|
71
|
-
# @param [String] name the name of the cookie to delete
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
def delete_cookie(name)
|
|
75
|
-
@bridge.delete_cookie name
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
#
|
|
79
|
-
# Delete all cookies
|
|
52
|
+
# @api private
|
|
80
53
|
#
|
|
81
54
|
|
|
82
|
-
def
|
|
83
|
-
@
|
|
84
|
-
end
|
|
55
|
+
def as_json(*)
|
|
56
|
+
options = @options.dup
|
|
85
57
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# @return [Array<Hash>] list of cookies
|
|
90
|
-
#
|
|
91
|
-
|
|
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
|
-
}
|
|
58
|
+
opts = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
|
|
59
|
+
capability_value = options.delete(capability_alias)
|
|
60
|
+
hash[capability_name] = capability_value unless capability_value.nil?
|
|
102
61
|
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def timeouts
|
|
106
|
-
@timeouts ||= Timeouts.new(@bridge)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
#
|
|
110
|
-
# @api beta This API may be changed or removed in a future release.
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
def logs
|
|
114
|
-
@logs ||= Logs.new(@bridge)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
#
|
|
118
|
-
# @api beta This API may be changed or removed in a future release.
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
def window
|
|
122
|
-
@window ||= Window.new(@bridge)
|
|
62
|
+
opts.merge(options)
|
|
123
63
|
end
|
|
124
64
|
|
|
125
65
|
private
|
|
126
66
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
obj.to_f
|
|
137
|
-
when DateTime
|
|
138
|
-
(obj - DateTime.civil(1970)) * SECONDS_PER_DAY
|
|
139
|
-
when Numeric
|
|
140
|
-
obj
|
|
67
|
+
def generate_as_json(value)
|
|
68
|
+
if value.respond_to?(:as_json)
|
|
69
|
+
value.as_json
|
|
70
|
+
elsif value.is_a?(Hash)
|
|
71
|
+
value.each_with_object({}) { |(key, val), hash| hash[convert_json_key(key)] = generate_as_json(val) }
|
|
72
|
+
elsif value.is_a?(Array)
|
|
73
|
+
value.map(&method(:generate_as_json))
|
|
74
|
+
elsif value.is_a?(Symbol)
|
|
75
|
+
value.to_s
|
|
141
76
|
else
|
|
142
|
-
|
|
77
|
+
value
|
|
143
78
|
end
|
|
144
79
|
end
|
|
145
80
|
|
|
146
|
-
def
|
|
147
|
-
|
|
81
|
+
def convert_json_key(key)
|
|
82
|
+
key = camel_case(key) if key.is_a?(Symbol)
|
|
83
|
+
return key if key.is_a?(String)
|
|
84
|
+
|
|
85
|
+
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def camel_case(str)
|
|
89
|
+
str.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
|
|
148
90
|
end
|
|
149
91
|
end # Options
|
|
150
92
|
end # WebDriver
|