selenium-webdriver 4.0.0.beta2 → 4.0.0.rc2
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 +4 -4
- data/CHANGES +1947 -0
- data/Gemfile +6 -0
- data/LICENSE +202 -0
- data/NOTICE +2 -0
- data/README.md +34 -0
- data/lib/selenium/webdriver/atoms/findElements.js +0 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +25 -25
- data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
- data/lib/selenium/webdriver/chrome/driver.rb +16 -4
- data/lib/selenium/webdriver/chrome/features.rb +44 -4
- data/lib/selenium/webdriver/chrome/options.rb +25 -2
- data/lib/selenium/webdriver/chrome/profile.rb +5 -2
- data/lib/selenium/webdriver/common/driver.rb +5 -1
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -17
- data/lib/selenium/{devtools.rb → webdriver/common/driver_extensions/has_launching.rb} +16 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -6
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +8 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +87 -18
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
- data/lib/selenium/webdriver/common/driver_extensions/prints_page.rb +28 -1
- data/lib/selenium/webdriver/common/element.rb +35 -6
- data/lib/selenium/webdriver/common/error.rb +12 -0
- data/lib/selenium/webdriver/common/log_entry.rb +2 -2
- data/lib/selenium/webdriver/common/manager.rb +3 -13
- data/lib/selenium/webdriver/common/options.rb +31 -12
- data/lib/selenium/webdriver/common/proxy.rb +2 -2
- data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
- data/lib/selenium/webdriver/common/socket_poller.rb +19 -30
- data/lib/selenium/webdriver/common/takes_screenshot.rb +9 -6
- data/lib/selenium/webdriver/common/target_locator.rb +28 -0
- data/lib/selenium/webdriver/common/window.rb +0 -4
- data/lib/selenium/webdriver/common.rb +8 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
- data/lib/selenium/webdriver/devtools/request.rb +27 -17
- data/lib/selenium/webdriver/devtools/response.rb +66 -0
- data/lib/selenium/webdriver/devtools.rb +50 -12
- data/lib/selenium/webdriver/edge/features.rb +5 -0
- data/lib/selenium/webdriver/edge/options.rb +0 -0
- data/lib/selenium/webdriver/edge/profile.rb +0 -0
- data/lib/selenium/webdriver/firefox/driver.rb +15 -2
- data/lib/selenium/webdriver/firefox/features.rb +20 -1
- data/lib/selenium/webdriver/firefox/options.rb +24 -1
- data/lib/selenium/webdriver/firefox.rb +0 -1
- data/lib/selenium/webdriver/ie/options.rb +3 -1
- data/lib/selenium/webdriver/ie/service.rb +1 -1
- data/lib/selenium/webdriver/remote/bridge.rb +43 -13
- data/lib/selenium/webdriver/remote/capabilities.rb +97 -53
- data/lib/selenium/webdriver/remote/commands.rb +5 -0
- data/lib/selenium/webdriver/remote/driver.rb +7 -7
- data/lib/selenium/webdriver/remote.rb +1 -1
- data/lib/selenium/webdriver/safari/driver.rb +1 -1
- data/lib/selenium/webdriver/safari/options.rb +7 -0
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +2 -2
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +1 -1
- data/selenium-webdriver.gemspec +63 -0
- metadata +60 -44
@@ -39,23 +39,17 @@ module Selenium
|
|
39
39
|
:timeouts,
|
40
40
|
:unhandled_prompt_behavior,
|
41
41
|
:strict_file_interactability,
|
42
|
+
:web_socket_url,
|
42
43
|
|
43
|
-
# remote-specific
|
44
|
-
:remote_session_id
|
45
|
-
|
46
|
-
# TODO: (AR) deprecate compatibility with OSS-capabilities
|
47
|
-
:implicit_timeout,
|
48
|
-
:page_load_timeout,
|
49
|
-
:script_timeout
|
44
|
+
# remote-specific (webdriver.remote.sessionid)
|
45
|
+
:remote_session_id
|
50
46
|
].freeze
|
51
47
|
|
52
|
-
KNOWN.each do |key|
|
48
|
+
(KNOWN - %i[proxy timeouts]).each do |key|
|
53
49
|
define_method key do
|
54
|
-
@capabilities
|
50
|
+
@capabilities[key]
|
55
51
|
end
|
56
52
|
|
57
|
-
next if key == :proxy
|
58
|
-
|
59
53
|
define_method "#{key}=" do |value|
|
60
54
|
@capabilities[key] = value
|
61
55
|
end
|
@@ -89,16 +83,10 @@ module Selenium
|
|
89
83
|
alias_method :microsoftedge, :edge
|
90
84
|
|
91
85
|
def firefox(opts = {})
|
92
|
-
|
93
|
-
|
94
|
-
opts
|
95
|
-
opts[:timeouts]['implicit'] = opts.delete(:implicit_timeout) if opts.key?(:implicit_timeout)
|
96
|
-
opts[:timeouts]['pageLoad'] = opts.delete(:page_load_timeout) if opts.key?(:page_load_timeout)
|
97
|
-
opts[:timeouts]['script'] = opts.delete(:script_timeout) if opts.key?(:script_timeout)
|
98
|
-
opts.delete(:timeouts) if opts[:timeouts].empty?
|
99
|
-
new({browser_name: 'firefox'}.merge(opts))
|
86
|
+
new({
|
87
|
+
browser_name: 'firefox'
|
88
|
+
}.merge(opts))
|
100
89
|
end
|
101
|
-
|
102
90
|
alias_method :ff, :firefox
|
103
91
|
|
104
92
|
def safari(opts = {})
|
@@ -121,18 +109,21 @@ module Selenium
|
|
121
109
|
end
|
122
110
|
alias_method :ie, :internet_explorer
|
123
111
|
|
112
|
+
def always_match(capabilities)
|
113
|
+
new(always_match: capabilities)
|
114
|
+
end
|
115
|
+
|
116
|
+
def first_match(*capabilities)
|
117
|
+
new(first_match: capabilities)
|
118
|
+
end
|
119
|
+
|
124
120
|
#
|
125
121
|
# @api private
|
126
122
|
#
|
127
123
|
|
128
124
|
def json_create(data)
|
129
125
|
data = data.dup
|
130
|
-
|
131
126
|
caps = new
|
132
|
-
(KNOWN - %i[timeouts proxy]).each do |cap|
|
133
|
-
data_value = camel_case(cap)
|
134
|
-
caps[cap] = data.delete(data_value) if data.key?(data_value)
|
135
|
-
end
|
136
127
|
|
137
128
|
process_timeouts(caps, data.delete('timeouts'))
|
138
129
|
|
@@ -146,6 +137,11 @@ module Selenium
|
|
146
137
|
caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
|
147
138
|
end
|
148
139
|
|
140
|
+
KNOWN.each do |cap|
|
141
|
+
data_value = camel_case(cap)
|
142
|
+
caps[cap] = data.delete(data_value) if data.key?(data_value)
|
143
|
+
end
|
144
|
+
|
149
145
|
# any remaining pairs will be added as is, with no conversion
|
150
146
|
caps.merge!(data)
|
151
147
|
|
@@ -179,8 +175,9 @@ module Selenium
|
|
179
175
|
#
|
180
176
|
|
181
177
|
def initialize(opts = {})
|
182
|
-
@capabilities =
|
183
|
-
self.proxy = opts.delete(:proxy)
|
178
|
+
@capabilities = {}
|
179
|
+
self.proxy = opts.delete(:proxy) if opts[:proxy]
|
180
|
+
@capabilities.merge!(opts)
|
184
181
|
end
|
185
182
|
|
186
183
|
#
|
@@ -205,6 +202,10 @@ module Selenium
|
|
205
202
|
end
|
206
203
|
end
|
207
204
|
|
205
|
+
def proxy
|
206
|
+
@capabilities[:proxy]
|
207
|
+
end
|
208
|
+
|
208
209
|
def proxy=(proxy)
|
209
210
|
case proxy
|
210
211
|
when Hash
|
@@ -216,33 +217,46 @@ module Selenium
|
|
216
217
|
end
|
217
218
|
end
|
218
219
|
|
220
|
+
def timeouts
|
221
|
+
@capabilities[:timeouts] ||= {}
|
222
|
+
end
|
223
|
+
|
224
|
+
def timeouts=(timeouts)
|
225
|
+
@capabilities[:timeouts] = timeouts
|
226
|
+
end
|
227
|
+
|
228
|
+
def implicit_timeout
|
229
|
+
timeouts[:implicit]
|
230
|
+
end
|
231
|
+
|
232
|
+
def implicit_timeout=(timeout)
|
233
|
+
timeouts[:implicit] = timeout
|
234
|
+
end
|
235
|
+
|
236
|
+
def page_load_timeout
|
237
|
+
timeouts[:page_load] || timeouts[:pageLoad]
|
238
|
+
end
|
239
|
+
|
240
|
+
def page_load_timeout=(timeout)
|
241
|
+
timeouts[:page_load] = timeout
|
242
|
+
end
|
243
|
+
|
244
|
+
def script_timeout
|
245
|
+
timeouts[:script]
|
246
|
+
end
|
247
|
+
|
248
|
+
def script_timeout=(timeout)
|
249
|
+
timeouts[:script] = timeout
|
250
|
+
end
|
251
|
+
|
219
252
|
#
|
220
253
|
# @api private
|
221
254
|
#
|
222
255
|
|
223
256
|
def as_json(*)
|
224
|
-
|
225
|
-
|
226
|
-
@capabilities.each do |key, value|
|
227
|
-
case key
|
228
|
-
when :platform
|
229
|
-
hash['platform'] = value.to_s.upcase
|
230
|
-
when :proxy
|
231
|
-
next unless value
|
232
|
-
|
233
|
-
process_proxy(hash, value)
|
234
|
-
when :unhandled_prompt_behavior
|
235
|
-
hash['unhandledPromptBehavior'] = value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
|
236
|
-
when String
|
237
|
-
hash[key.to_s] = value
|
238
|
-
when Symbol
|
239
|
-
hash[self.class.camel_case(key)] = value
|
240
|
-
else
|
241
|
-
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class} / #{value.inspect}"
|
242
|
-
end
|
257
|
+
@capabilities.each_with_object({}) do |(key, value), hash|
|
258
|
+
hash[convert_key(key)] = process_capabilities(key, value, hash)
|
243
259
|
end
|
244
|
-
|
245
|
-
hash
|
246
260
|
end
|
247
261
|
|
248
262
|
def to_json(*)
|
@@ -263,13 +277,43 @@ module Selenium
|
|
263
277
|
|
264
278
|
private
|
265
279
|
|
266
|
-
def
|
267
|
-
|
268
|
-
|
280
|
+
def process_capabilities(key, value, hash)
|
281
|
+
case value
|
282
|
+
when Array
|
283
|
+
value.map { |v| process_capabilities(key, v, hash) }
|
284
|
+
when Hash
|
285
|
+
value.each_with_object({}) do |(k, v), h|
|
286
|
+
h[convert_key(k)] = process_capabilities(k, v, h)
|
287
|
+
end
|
288
|
+
when Capabilities, Options
|
289
|
+
value.as_json
|
290
|
+
else
|
291
|
+
convert_value(key, value)
|
292
|
+
end
|
293
|
+
end
|
269
294
|
|
270
|
-
|
295
|
+
def convert_key(key)
|
296
|
+
case key
|
297
|
+
when String
|
298
|
+
key.to_s
|
299
|
+
when Symbol
|
300
|
+
self.class.camel_case(key)
|
301
|
+
else
|
302
|
+
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
|
303
|
+
end
|
304
|
+
end
|
271
305
|
|
272
|
-
|
306
|
+
def convert_value(key, value)
|
307
|
+
case key
|
308
|
+
when :platform
|
309
|
+
value.to_s.upcase
|
310
|
+
when :proxy
|
311
|
+
value&.as_json
|
312
|
+
when :unhandled_prompt_behavior
|
313
|
+
value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
|
314
|
+
else
|
315
|
+
value
|
316
|
+
end
|
273
317
|
end
|
274
318
|
end # Capabilities
|
275
319
|
end # Remote
|
@@ -77,11 +77,16 @@ module Selenium
|
|
77
77
|
find_elements: [:post, 'session/:session_id/elements'],
|
78
78
|
find_child_element: [:post, 'session/:session_id/element/:id/element'],
|
79
79
|
find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
|
80
|
+
find_shadow_child_element: [:post, 'session/:session_id/shadow/:id/element'],
|
81
|
+
find_shadow_child_elements: [:post, 'session/:session_id/shadow/:id/elements'],
|
80
82
|
get_active_element: [:get, 'session/:session_id/element/active'],
|
83
|
+
get_element_shadow_root: [:get, 'session/:session_id/element/:id/shadow'],
|
81
84
|
is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
|
82
85
|
get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
|
83
86
|
get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
|
84
87
|
get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
|
88
|
+
get_element_aria_role: [:get, 'session/:session_id/element/:id/computedrole'],
|
89
|
+
get_element_aria_label: [:get, 'session/:session_id/element/:id/computedlabel'],
|
85
90
|
get_element_text: [:get, 'session/:session_id/element/:id/text'],
|
86
91
|
get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
|
87
92
|
get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
|
@@ -42,19 +42,19 @@ module Selenium
|
|
42
42
|
end
|
43
43
|
opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
|
44
44
|
super
|
45
|
-
|
46
|
-
|
47
|
-
def print_page(**options)
|
48
|
-
options[:page_ranges] &&= Array(options[:page_ranges])
|
49
|
-
|
50
|
-
@bridge.print_page(options)
|
45
|
+
@bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
|
51
46
|
end
|
52
47
|
|
53
48
|
private
|
54
49
|
|
55
|
-
def
|
50
|
+
def devtools_url
|
56
51
|
capabilities['se:cdp']
|
57
52
|
end
|
53
|
+
|
54
|
+
def devtools_version
|
55
|
+
capabilities['se:cdpVersion']&.split('.')&.first ||
|
56
|
+
raise(Error::WebDriverError, "DevTools is not supported by the Remote Server")
|
57
|
+
end
|
58
58
|
end # Driver
|
59
59
|
end # Remote
|
60
60
|
end # WebDriver
|
@@ -18,6 +18,7 @@
|
|
18
18
|
# under the License.
|
19
19
|
|
20
20
|
require 'uri'
|
21
|
+
require 'selenium/webdriver/remote/server_error'
|
21
22
|
|
22
23
|
module Selenium
|
23
24
|
module WebDriver
|
@@ -25,7 +26,6 @@ module Selenium
|
|
25
26
|
autoload :Bridge, 'selenium/webdriver/remote/bridge'
|
26
27
|
autoload :Driver, 'selenium/webdriver/remote/driver'
|
27
28
|
autoload :Response, 'selenium/webdriver/remote/response'
|
28
|
-
autoload :ServerError, 'selenium/webdriver/remote/server_error'
|
29
29
|
autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
|
30
30
|
autoload :COMMANDS, 'selenium/webdriver/remote/commands'
|
31
31
|
module Http
|
@@ -28,6 +28,13 @@ module Selenium
|
|
28
28
|
automatic_profiling: 'safari:automaticProfiling'}.freeze
|
29
29
|
BROWSER = 'safari'
|
30
30
|
|
31
|
+
def add_option(name, value = nil)
|
32
|
+
key = name.is_a?(Hash) ? name.keys.first : name
|
33
|
+
raise ArgumentError, 'Safari does not support options that are not namespaced' unless key.to_s.include?(':')
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
31
38
|
end # Options
|
32
39
|
end # Safari
|
33
40
|
end # WebDriver
|
@@ -0,0 +1,63 @@
|
|
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
|
+
# This file is automatically generated. Any changes will be lost!
|
21
|
+
module Selenium
|
22
|
+
module DevTools
|
23
|
+
module <%= version %>
|
24
|
+
class <%= domain[:domain] %>
|
25
|
+
<% if domain[:events] %>
|
26
|
+
EVENTS = {
|
27
|
+
<% domain[:events].each do |event| %>
|
28
|
+
<%= h.snake_case(event[:name]) %>: '<%= event[:name] %>',
|
29
|
+
<% end %>
|
30
|
+
}.freeze
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
def initialize(devtools)
|
34
|
+
@devtools = devtools
|
35
|
+
end
|
36
|
+
|
37
|
+
def on(event, &block)
|
38
|
+
event = EVENTS[event] if event.is_a?(Symbol)
|
39
|
+
@devtools.callbacks["<%= domain[:domain] %>.#{event}"] << block
|
40
|
+
end
|
41
|
+
|
42
|
+
<% domain[:commands].each do |command| %>
|
43
|
+
<% if command[:parameters] %>
|
44
|
+
def <%= h.snake_case(command[:name]) %>(<%= h.kwargs(command[:parameters]) %>)
|
45
|
+
<% else %>
|
46
|
+
def <%= h.snake_case(command[:name]) %>
|
47
|
+
<% end %>
|
48
|
+
<% if command[:parameters] %>
|
49
|
+
@devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>',
|
50
|
+
<% until command[:parameters].empty? %>
|
51
|
+
<% parameter = command[:parameters].shift %>
|
52
|
+
<%= parameter[:name] %>: <%= h.snake_case(parameter[:name]) %><%= command[:parameters].empty? ? ')' : ',' %>
|
53
|
+
<% end %>
|
54
|
+
<% else %>
|
55
|
+
@devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>')
|
56
|
+
<% end %>
|
57
|
+
end
|
58
|
+
|
59
|
+
<% end %>
|
60
|
+
end # <%= domain[:domain] %>
|
61
|
+
end # <%= version %>
|
62
|
+
end # DevTools
|
63
|
+
end # Selenium
|
@@ -0,0 +1,108 @@
|
|
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 'erb'
|
21
|
+
require 'fileutils'
|
22
|
+
require 'json'
|
23
|
+
|
24
|
+
module Selenium
|
25
|
+
module WebDriver
|
26
|
+
module Support
|
27
|
+
class CDPClientGenerator
|
28
|
+
# Input JSON files are generated from PDL tasks.
|
29
|
+
TEMPLATE_PATH = File.expand_path('cdp/domain.rb.erb', __dir__)
|
30
|
+
|
31
|
+
RESERVED_KEYWORDS = %w[end].freeze
|
32
|
+
|
33
|
+
def call(output_dir:, version:, browser_protocol_path: nil, js_protocol_path: nil, loader_path: nil, **)
|
34
|
+
@template = ERB.new(File.read(TEMPLATE_PATH))
|
35
|
+
@output_dir = output_dir
|
36
|
+
@loader_path = loader_path || "#{@output_dir}.rb"
|
37
|
+
@version = version
|
38
|
+
|
39
|
+
browser_protocol_path ||= File.expand_path('cdp/browser_protocol.json', __dir__)
|
40
|
+
js_protocol_path ||= File.expand_path('cdp/js_protocol.json', __dir__)
|
41
|
+
|
42
|
+
browser_protocol = JSON.parse(File.read(browser_protocol_path), symbolize_names: true)
|
43
|
+
js_protocol = JSON.parse(File.read(js_protocol_path), symbolize_names: true)
|
44
|
+
|
45
|
+
FileUtils.mkdir_p(@output_dir)
|
46
|
+
|
47
|
+
browser_protocol[:domains].each(&method(:process_domain))
|
48
|
+
js_protocol[:domains].each(&method(:process_domain))
|
49
|
+
require_file
|
50
|
+
end
|
51
|
+
|
52
|
+
def process_domain(domain)
|
53
|
+
result = @template.result_with_hash(domain: domain, version: @version.upcase, h: self)
|
54
|
+
filename = File.join(@output_dir, "#{snake_case(domain[:domain])}.rb")
|
55
|
+
File.write(filename, remove_empty_lines(result))
|
56
|
+
end
|
57
|
+
|
58
|
+
def snake_case(string)
|
59
|
+
name = string.gsub('JavaScript', 'Javascript')
|
60
|
+
.gsub(/([A-Z]+)([A-Z][a-z]{2,})/, '\1_\2')
|
61
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
62
|
+
.downcase
|
63
|
+
# Certain CDP parameters conflict with Ruby keywords
|
64
|
+
# so we prefix the name with underscore.
|
65
|
+
name = "_#{name}" if RESERVED_KEYWORDS.include?(name)
|
66
|
+
|
67
|
+
name
|
68
|
+
end
|
69
|
+
|
70
|
+
def kwargs(parameters)
|
71
|
+
parameters = parameters.map do |parameter|
|
72
|
+
if parameter[:optional]
|
73
|
+
"#{snake_case(parameter[:name])}: nil"
|
74
|
+
else
|
75
|
+
"#{snake_case(parameter[:name])}:"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
parameters.join(', ')
|
79
|
+
end
|
80
|
+
|
81
|
+
def remove_empty_lines(string)
|
82
|
+
string.split("\n").reject { |l| l =~ /^\s+$/ }.join("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
def require_file
|
86
|
+
# rubocop:disable Lint/InterpolationCheck
|
87
|
+
dynamic_location = '#{File.dirname(File.absolute_path(__FILE__))}'
|
88
|
+
# rubocop:enable Lint/InterpolationCheck
|
89
|
+
|
90
|
+
require_all = "Dir.glob(\"#{dynamic_location}/#{@version}/*\", &method(:require))"
|
91
|
+
File.open(@loader_path, 'w') { |file| file.write(require_all) }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
if $PROGRAM_NAME == __FILE__
|
99
|
+
browser_protocol_path, js_protocol_path, output_dir, loader_path, version = *ARGV
|
100
|
+
|
101
|
+
Selenium::WebDriver::Support::CDPClientGenerator.new.call(
|
102
|
+
browser_protocol_path: browser_protocol_path,
|
103
|
+
js_protocol_path: js_protocol_path,
|
104
|
+
output_dir: output_dir,
|
105
|
+
loader_path: loader_path,
|
106
|
+
version: version
|
107
|
+
)
|
108
|
+
end
|
@@ -76,7 +76,7 @@ module Selenium
|
|
76
76
|
@delegate.find_element_by how, what, parent
|
77
77
|
end
|
78
78
|
|
79
|
-
Element.new self, e.ref
|
79
|
+
Element.new self, e.ref.last
|
80
80
|
end
|
81
81
|
|
82
82
|
def find_elements_by(how, what, parent = nil)
|
@@ -84,7 +84,7 @@ module Selenium
|
|
84
84
|
@delegate.find_elements_by(how, what, parent)
|
85
85
|
end
|
86
86
|
|
87
|
-
es.map { |e| Element.new self, e.ref }
|
87
|
+
es.map { |e| Element.new self, e.ref.last }
|
88
88
|
end
|
89
89
|
|
90
90
|
def execute_script(script, *args)
|
data/lib/selenium/webdriver.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
root = File.expand_path(File.dirname(__FILE__))
|
4
|
+
raise "cwd must be #{root} when reading gemspec" if root != Dir.pwd
|
5
|
+
|
6
|
+
$LOAD_PATH.push(File.expand_path('lib', root))
|
7
|
+
require 'selenium/webdriver/version'
|
8
|
+
|
9
|
+
Gem::Specification.new do |s|
|
10
|
+
s.name = 'selenium-webdriver'
|
11
|
+
s.version = Selenium::WebDriver::VERSION
|
12
|
+
|
13
|
+
s.authors = ['Alex Rodionov', 'Titus Fortner', 'Thomas Walpole']
|
14
|
+
s.email = %w[p0deje@gmail.com titusfortner@gmail.com twalpole@gmail.com]
|
15
|
+
|
16
|
+
s.summary = 'Selenium is a browser automation tool for automated testing of webapps and more'
|
17
|
+
s.description = <<-DESCRIPTION
|
18
|
+
Selenium implements the W3C WebDriver protocol to automate popular browsers.
|
19
|
+
It aims to mimic the behaviour of a real user as it interacts with the application's HTML.
|
20
|
+
It's primarily intended for web application testing, but any web-based task can automated.
|
21
|
+
DESCRIPTION
|
22
|
+
|
23
|
+
s.license = 'Apache-2.0'
|
24
|
+
s.homepage = 'https://selenium.dev'
|
25
|
+
s.metadata = {
|
26
|
+
'changelog_uri' => 'https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES',
|
27
|
+
'source_code_uri' => 'https://github.com/SeleniumHQ/selenium/tree/trunk/rb'
|
28
|
+
}
|
29
|
+
|
30
|
+
s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
|
31
|
+
s.required_ruby_version = Gem::Requirement.new('>= 2.5')
|
32
|
+
|
33
|
+
s.files = [
|
34
|
+
'CHANGES',
|
35
|
+
'LICENSE',
|
36
|
+
'NOTICE',
|
37
|
+
'Gemfile',
|
38
|
+
'README.md',
|
39
|
+
'selenium-webdriver.gemspec',
|
40
|
+
'lib/selenium-webdriver.rb',
|
41
|
+
'lib/selenium/server.rb',
|
42
|
+
'lib/selenium/webdriver.rb'
|
43
|
+
] + Dir['lib/selenium/webdriver/**/*']
|
44
|
+
|
45
|
+
s.require_paths = ['lib']
|
46
|
+
|
47
|
+
s.add_runtime_dependency 'childprocess', ['>= 0.5', '< 5.0']
|
48
|
+
s.add_runtime_dependency 'rexml', ['~> 3.2']
|
49
|
+
s.add_runtime_dependency 'rubyzip', ['>= 1.2.2']
|
50
|
+
|
51
|
+
# childprocess requires ffi on windows but doesn't declare it in its dependencies
|
52
|
+
s.add_development_dependency 'ffi'
|
53
|
+
s.add_development_dependency 'pry', ['~> 0.14']
|
54
|
+
s.add_development_dependency 'rack', ['~> 2.0']
|
55
|
+
s.add_development_dependency 'rake'
|
56
|
+
s.add_development_dependency 'rspec', ['~> 3.0']
|
57
|
+
s.add_development_dependency 'rubocop', ['~> 1.8.0']
|
58
|
+
s.add_development_dependency 'rubocop-performance'
|
59
|
+
s.add_development_dependency 'rubocop-rspec'
|
60
|
+
s.add_development_dependency 'webmock', ['~> 3.5']
|
61
|
+
s.add_development_dependency 'webrick', ['~> 1.7']
|
62
|
+
s.add_development_dependency 'yard', ['~> 0.9.11']
|
63
|
+
end
|