selenium-webdriver 4.0.0.alpha2 → 4.0.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 +5 -5
- data/CHANGES +338 -4
- data/Gemfile +3 -1
- data/LICENSE +1 -1
- data/NOTICE +2 -0
- data/README.md +4 -5
- data/lib/selenium/server.rb +21 -29
- data/lib/selenium/webdriver/atoms/findElements.js +122 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +100 -7
- data/lib/selenium/webdriver/atoms/isDisplayed.js +76 -78
- data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
- data/lib/selenium/webdriver/chrome/driver.rb +26 -56
- data/lib/selenium/webdriver/chrome/features.rb +106 -0
- data/lib/selenium/webdriver/chrome/options.rb +127 -52
- data/lib/selenium/webdriver/chrome/profile.rb +8 -5
- data/lib/selenium/webdriver/chrome/service.rb +4 -6
- data/lib/selenium/webdriver/chrome.rb +10 -9
- data/lib/selenium/webdriver/common/driver.rb +110 -19
- 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_authentication.rb +89 -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 +43 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +144 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_logs.rb +30 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +136 -0
- 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/has_remote_status.rb +1 -0
- data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
- data/lib/selenium/webdriver/common/element.rb +79 -16
- data/lib/selenium/webdriver/common/error.rb +12 -0
- data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
- data/lib/selenium/webdriver/common/log_entry.rb +2 -2
- data/lib/selenium/webdriver/common/logger.rb +50 -15
- data/lib/selenium/webdriver/common/manager.rb +14 -14
- data/lib/selenium/webdriver/common/options.rb +186 -0
- data/lib/selenium/webdriver/common/platform.rb +6 -1
- data/lib/selenium/webdriver/common/port_prober.rb +4 -6
- data/lib/selenium/webdriver/common/profile_helper.rb +10 -2
- data/lib/selenium/webdriver/common/proxy.rb +6 -3
- data/lib/selenium/webdriver/common/search_context.rb +7 -3
- data/lib/selenium/webdriver/common/service.rb +23 -113
- data/lib/selenium/webdriver/common/service_manager.rb +151 -0
- data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
- data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
- data/lib/selenium/webdriver/common/takes_screenshot.rb +66 -0
- data/lib/selenium/webdriver/common/target_locator.rb +32 -4
- data/lib/selenium/webdriver/common/timeouts.rb +31 -4
- data/lib/selenium/webdriver/common/wait.rb +1 -1
- data/lib/selenium/webdriver/common/window.rb +0 -4
- data/lib/selenium/webdriver/common.rb +17 -2
- data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
- data/lib/selenium/webdriver/devtools/exception_event.rb +36 -0
- data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
- data/lib/selenium/webdriver/{chrome/bridge.rb → devtools/pinned_script.rb} +26 -17
- data/lib/selenium/webdriver/devtools/request.rb +67 -0
- data/lib/selenium/webdriver/devtools/response.rb +66 -0
- data/lib/selenium/webdriver/devtools.rb +182 -0
- data/lib/selenium/webdriver/edge/driver.rb +5 -31
- data/lib/selenium/webdriver/edge/features.rb +44 -0
- data/lib/selenium/webdriver/edge/options.rb +11 -48
- data/lib/selenium/webdriver/edge/profile.rb +33 -0
- data/lib/selenium/webdriver/edge/service.rb +9 -24
- data/lib/selenium/webdriver/edge.rb +11 -13
- data/lib/selenium/webdriver/firefox/driver.rb +20 -30
- data/lib/selenium/webdriver/firefox/extension.rb +8 -0
- data/lib/selenium/webdriver/firefox/{bridge.rb → features.rb} +23 -4
- data/lib/selenium/webdriver/firefox/options.rb +70 -49
- data/lib/selenium/webdriver/firefox/profile.rb +16 -77
- data/lib/selenium/webdriver/firefox/service.rb +1 -5
- data/lib/selenium/webdriver/firefox.rb +22 -16
- data/lib/selenium/webdriver/ie/driver.rb +1 -34
- data/lib/selenium/webdriver/ie/options.rb +13 -44
- data/lib/selenium/webdriver/ie/service.rb +9 -11
- data/lib/selenium/webdriver/ie.rb +8 -7
- data/lib/selenium/webdriver/remote/bridge.rb +112 -86
- data/lib/selenium/webdriver/remote/capabilities.rb +120 -62
- data/lib/selenium/webdriver/remote/commands.rb +7 -0
- data/lib/selenium/webdriver/remote/driver.rb +15 -12
- data/lib/selenium/webdriver/remote/http/common.rb +0 -5
- data/lib/selenium/webdriver/remote/http/default.rb +17 -11
- data/lib/selenium/webdriver/remote/http/persistent.rb +11 -6
- data/lib/selenium/webdriver/remote.rb +15 -9
- data/lib/selenium/webdriver/safari/driver.rb +3 -34
- data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +6 -6
- data/lib/selenium/webdriver/safari/options.rb +10 -29
- data/lib/selenium/webdriver/safari/service.rb +0 -4
- data/lib/selenium/webdriver/safari.rb +16 -8
- data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
- 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/color.rb +2 -2
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
- data/lib/selenium/webdriver/support/guards/guard_condition.rb +52 -0
- data/lib/selenium/webdriver/support/guards.rb +95 -0
- data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
- data/lib/selenium/webdriver/support/select.rb +2 -2
- data/lib/selenium/webdriver/support.rb +1 -0
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +10 -8
- data/selenium-webdriver.gemspec +29 -13
- metadata +125 -51
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
- data/lib/selenium/webdriver/firefox/binary.rb +0 -110
- data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
|
@@ -17,20 +17,28 @@
|
|
|
17
17
|
# specific language governing permissions and limitations
|
|
18
18
|
# under the License.
|
|
19
19
|
|
|
20
|
-
require 'selenium/webdriver/safari/bridge'
|
|
21
|
-
require 'selenium/webdriver/safari/driver'
|
|
22
|
-
require 'selenium/webdriver/safari/options'
|
|
23
|
-
|
|
24
20
|
module Selenium
|
|
25
21
|
module WebDriver
|
|
26
22
|
module Safari
|
|
23
|
+
autoload :Features, 'selenium/webdriver/safari/features'
|
|
24
|
+
autoload :Driver, 'selenium/webdriver/safari/driver'
|
|
25
|
+
autoload :Options, 'selenium/webdriver/safari/options'
|
|
26
|
+
autoload :Service, 'selenium/webdriver/safari/service'
|
|
27
|
+
|
|
27
28
|
class << self
|
|
29
|
+
attr_accessor :use_technology_preview
|
|
30
|
+
|
|
28
31
|
def technology_preview
|
|
29
32
|
"/Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver"
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
def technology_preview!
|
|
33
36
|
Service.driver_path = technology_preview
|
|
37
|
+
@use_technology_preview = true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def technology_preview?
|
|
41
|
+
use_technology_preview
|
|
34
42
|
end
|
|
35
43
|
|
|
36
44
|
def path=(path)
|
|
@@ -48,18 +56,18 @@ module Selenium
|
|
|
48
56
|
|
|
49
57
|
def driver_path=(path)
|
|
50
58
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path=',
|
|
51
|
-
'Selenium::WebDriver::Safari::Service#driver_path='
|
|
59
|
+
'Selenium::WebDriver::Safari::Service#driver_path=',
|
|
60
|
+
id: :driver_path
|
|
52
61
|
Selenium::WebDriver::Safari::Service.driver_path = path
|
|
53
62
|
end
|
|
54
63
|
|
|
55
64
|
def driver_path
|
|
56
65
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path',
|
|
57
|
-
'Selenium::WebDriver::Safari::Service#driver_path'
|
|
66
|
+
'Selenium::WebDriver::Safari::Service#driver_path',
|
|
67
|
+
id: :driver_path
|
|
58
68
|
Selenium::WebDriver::Safari::Service.driver_path
|
|
59
69
|
end
|
|
60
70
|
end
|
|
61
71
|
end # Safari
|
|
62
72
|
end # WebDriver
|
|
63
73
|
end # Selenium
|
|
64
|
-
|
|
65
|
-
require 'selenium/webdriver/safari/service'
|
|
@@ -25,7 +25,7 @@ module Selenium
|
|
|
25
25
|
@callback = callback
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def method_missing(meth, *args) # rubocop:disable Style/
|
|
28
|
+
def method_missing(meth, *args) # rubocop:disable Style/MissingRespondToMissing
|
|
29
29
|
@callback.call meth, *args
|
|
30
30
|
end
|
|
31
31
|
end # BlockEventListener
|
|
@@ -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
|
|
@@ -72,7 +72,7 @@ module Selenium
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
def self.from_hsl(h, s, l, a) # rubocop:disable Naming/
|
|
75
|
+
def self.from_hsl(h, s, l, a) # rubocop:disable Naming/MethodParameterName
|
|
76
76
|
h = Float(h) / 360
|
|
77
77
|
s = Float(s) / 100
|
|
78
78
|
l = Float(l) / 100
|
|
@@ -138,7 +138,7 @@ module Selenium
|
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
def hex
|
|
141
|
-
format '
|
|
141
|
+
format '#%<red>02x%<green>02x%<blue>02x', red: red, green: green, blue: blue
|
|
142
142
|
end
|
|
143
143
|
end # Color
|
|
144
144
|
end # Support
|
|
@@ -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)
|
|
@@ -109,7 +109,7 @@ module Selenium
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def driver
|
|
112
|
-
@driver ||= Driver.new(self)
|
|
112
|
+
@driver ||= Driver.new(bridge: self)
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def dispatch(name, *args)
|
|
@@ -120,7 +120,7 @@ module Selenium
|
|
|
120
120
|
returned
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
-
def method_missing(meth, *args, &blk) # rubocop:disable Style/
|
|
123
|
+
def method_missing(meth, *args, &blk) # rubocop:disable Style/MissingRespondToMissing
|
|
124
124
|
@delegate.__send__(meth, *args, &blk)
|
|
125
125
|
end
|
|
126
126
|
end # EventFiringBridge
|
|
@@ -0,0 +1,89 @@
|
|
|
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
|
+
module Support
|
|
23
|
+
class Guards
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Guard derived from RSpec example metadata.
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
class Guard
|
|
31
|
+
|
|
32
|
+
attr_reader :guarded, :type, :messages, :reason
|
|
33
|
+
|
|
34
|
+
def initialize(guarded, type, guards = nil)
|
|
35
|
+
@guarded = guarded
|
|
36
|
+
@tracker = guards&.bug_tracker || ''
|
|
37
|
+
@messages = guards&.messages || {}
|
|
38
|
+
@messages[:unknown] = 'TODO: Investigate why this is failing and file a bug report'
|
|
39
|
+
@type = type
|
|
40
|
+
|
|
41
|
+
@reason = @guarded.delete(:reason)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def message
|
|
45
|
+
details = case @reason
|
|
46
|
+
when Integer
|
|
47
|
+
"Bug Filed: #{@tracker}/#{@reason}"
|
|
48
|
+
when Symbol
|
|
49
|
+
@messages[@reason]
|
|
50
|
+
when String
|
|
51
|
+
@reason
|
|
52
|
+
else
|
|
53
|
+
'no reason given'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
case @type
|
|
57
|
+
when :exclude
|
|
58
|
+
"Test not guarded because it breaks test run; #{details}"
|
|
59
|
+
when :exclusive
|
|
60
|
+
"Test does not apply to this configuration; #{details}"
|
|
61
|
+
else
|
|
62
|
+
"Test guarded; #{details}"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Bug is present on all configurations specified
|
|
67
|
+
def except?
|
|
68
|
+
@type == :except
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Bug is present on all configurations not specified
|
|
72
|
+
def only?
|
|
73
|
+
@type == :only
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Bug is present on all configurations specified, but test can not be run because it breaks other tests
|
|
77
|
+
def exclude?
|
|
78
|
+
@type == :exclude
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Test only applies to configurations specified
|
|
82
|
+
def exclusive?
|
|
83
|
+
@type == :exclusive
|
|
84
|
+
end
|
|
85
|
+
end # Guard
|
|
86
|
+
end # Guards
|
|
87
|
+
end # Support
|
|
88
|
+
end # WebDriver
|
|
89
|
+
end # Selenium
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
module Support
|
|
23
|
+
class Guards
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Guard derived from RSpec example metadata.
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
class GuardCondition
|
|
31
|
+
attr_accessor :name, :execution
|
|
32
|
+
|
|
33
|
+
def initialize(name, condition = nil, &blk)
|
|
34
|
+
@name = name
|
|
35
|
+
@execution = if block_given?
|
|
36
|
+
proc(&blk)
|
|
37
|
+
else
|
|
38
|
+
proc { |guarded| guarded.include?(condition) }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def satisfied?(guard)
|
|
43
|
+
list = Array(guard.guarded[@name])
|
|
44
|
+
|
|
45
|
+
list.empty? || @execution.call(list)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end # GuardCondition
|
|
49
|
+
end # Guards
|
|
50
|
+
end # Support
|
|
51
|
+
end # WebDriver
|
|
52
|
+
end # Selenium
|
|
@@ -0,0 +1,95 @@
|
|
|
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_relative 'guards/guard_condition'
|
|
21
|
+
require_relative 'guards/guard'
|
|
22
|
+
|
|
23
|
+
module Selenium
|
|
24
|
+
module WebDriver
|
|
25
|
+
module Support
|
|
26
|
+
class Guards
|
|
27
|
+
GUARD_TYPES = %i[except only exclude exclusive].freeze
|
|
28
|
+
|
|
29
|
+
attr_reader :messages
|
|
30
|
+
attr_accessor :bug_tracker
|
|
31
|
+
|
|
32
|
+
def initialize(example, bug_tracker: '', conditions: nil)
|
|
33
|
+
@example = example
|
|
34
|
+
@bug_tracker = bug_tracker
|
|
35
|
+
@guard_conditions = conditions || []
|
|
36
|
+
@guards = collect_example_guards
|
|
37
|
+
@messages = {}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_condition(name, condition = nil, &blk)
|
|
41
|
+
@guard_conditions << GuardCondition.new(name, condition, &blk)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_message(name, message)
|
|
45
|
+
@messages[name] = message
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def disposition
|
|
49
|
+
if !skipping_guard.nil?
|
|
50
|
+
[:skip, skipping_guard.message]
|
|
51
|
+
elsif !pending_guard.nil? && ENV['SKIP_PENDING']
|
|
52
|
+
[:skip, pending_guard.message]
|
|
53
|
+
elsif !pending_guard.nil?
|
|
54
|
+
[:pending, pending_guard.message]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def satisfied?(guard)
|
|
59
|
+
@guard_conditions.all? { |condition| condition.satisfied?(guard) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def collect_example_guards
|
|
65
|
+
guards = []
|
|
66
|
+
|
|
67
|
+
GUARD_TYPES.each do |guard_type|
|
|
68
|
+
example_group = @example.metadata[:example_group]
|
|
69
|
+
example_guards = [@example.metadata[guard_type], example_group[guard_type]]
|
|
70
|
+
while example_group[:parent_example_group]
|
|
71
|
+
example_group = example_group[:parent_example_group]
|
|
72
|
+
example_guards << example_group[guard_type]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
example_guards.flatten.uniq.compact.each do |example_guard|
|
|
76
|
+
guards << Guard.new(example_guard, guard_type, self)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
guards
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def skipping_guard
|
|
84
|
+
@guards.select(&:exclusive?).find { |guard| !satisfied?(guard) } ||
|
|
85
|
+
@guards.select(&:exclude?).find { |guard| satisfied?(guard) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def pending_guard
|
|
89
|
+
@guards.select(&:except?).find { |guard| satisfied?(guard) } ||
|
|
90
|
+
@guards.select(&:only?).find { |guard| !satisfied?(guard) }
|
|
91
|
+
end
|
|
92
|
+
end # Guards
|
|
93
|
+
end # Support
|
|
94
|
+
end # WebDriver
|
|
95
|
+
end # Selenium
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
module Support
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
26
|
+
#
|
|
27
|
+
|
|
28
|
+
class RelativeLocator
|
|
29
|
+
KEYS = %w[above below left right near distance].freeze
|
|
30
|
+
|
|
31
|
+
def initialize(locator)
|
|
32
|
+
@filters, @root = locator.partition { |how, _| KEYS.include?(how) }.map(&:to_h)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def as_json
|
|
36
|
+
{
|
|
37
|
+
relative: {
|
|
38
|
+
root: @root,
|
|
39
|
+
filters: @filters.map do |kind, filter|
|
|
40
|
+
{
|
|
41
|
+
kind: kind,
|
|
42
|
+
args: [filter]
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -31,7 +31,7 @@ module Selenium
|
|
|
31
31
|
raise ArgumentError, "unexpected tag name #{tag_name.inspect}" unless tag_name.casecmp('select').zero?
|
|
32
32
|
|
|
33
33
|
@element = element
|
|
34
|
-
@multi = ![nil, 'false'].include?(element.
|
|
34
|
+
@multi = ![nil, 'false'].include?(element.dom_attribute(:multiple))
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
#
|
|
@@ -258,7 +258,7 @@ module Selenium
|
|
|
258
258
|
end
|
|
259
259
|
|
|
260
260
|
def find_by_index(index)
|
|
261
|
-
options.select { |option| option.
|
|
261
|
+
options.select { |option| option.dom_attribute(:index) == index.to_s }
|
|
262
262
|
end
|
|
263
263
|
|
|
264
264
|
def find_by_value(value)
|
data/lib/selenium/webdriver.rb
CHANGED
|
@@ -23,9 +23,10 @@ require 'fileutils'
|
|
|
23
23
|
require 'date'
|
|
24
24
|
require 'json'
|
|
25
25
|
require 'set'
|
|
26
|
+
require 'uri'
|
|
26
27
|
|
|
27
|
-
require 'selenium/webdriver/common'
|
|
28
28
|
require 'selenium/webdriver/atoms'
|
|
29
|
+
require 'selenium/webdriver/common'
|
|
29
30
|
require 'selenium/webdriver/version'
|
|
30
31
|
|
|
31
32
|
module Selenium
|
|
@@ -35,13 +36,14 @@ module Selenium
|
|
|
35
36
|
Rectangle = Struct.new(:x, :y, :width, :height)
|
|
36
37
|
Location = Struct.new(:latitude, :longitude, :altitude)
|
|
37
38
|
|
|
38
|
-
autoload :Chrome,
|
|
39
|
-
autoload :
|
|
40
|
-
autoload :
|
|
41
|
-
autoload :
|
|
42
|
-
autoload :
|
|
43
|
-
autoload :
|
|
44
|
-
autoload :
|
|
39
|
+
autoload :Chrome, 'selenium/webdriver/chrome'
|
|
40
|
+
autoload :DevTools, 'selenium/webdriver/devtools'
|
|
41
|
+
autoload :Edge, 'selenium/webdriver/edge'
|
|
42
|
+
autoload :Firefox, 'selenium/webdriver/firefox'
|
|
43
|
+
autoload :IE, 'selenium/webdriver/ie'
|
|
44
|
+
autoload :Remote, 'selenium/webdriver/remote'
|
|
45
|
+
autoload :Safari, 'selenium/webdriver/safari'
|
|
46
|
+
autoload :Support, 'selenium/webdriver/support'
|
|
45
47
|
|
|
46
48
|
# @api private
|
|
47
49
|
|