selenium-webdriver 4.0.0.beta4 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +70 -0
  3. data/README.md +1 -1
  4. data/lib/selenium/webdriver/atoms/getAttribute.js +25 -25
  5. data/lib/selenium/webdriver/chrome/driver.rb +4 -0
  6. data/lib/selenium/webdriver/chrome/features.rb +44 -4
  7. data/lib/selenium/webdriver/chrome/options.rb +24 -1
  8. data/lib/selenium/webdriver/common/driver.rb +5 -1
  9. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
  10. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
  11. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
  12. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
  13. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -6
  14. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
  15. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +87 -18
  16. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
  17. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
  18. data/lib/selenium/webdriver/common/driver_extensions/prints_page.rb +1 -1
  19. data/lib/selenium/webdriver/common/element.rb +17 -8
  20. data/lib/selenium/webdriver/common/error.rb +12 -0
  21. data/lib/selenium/webdriver/common/log_entry.rb +2 -2
  22. data/lib/selenium/webdriver/common/manager.rb +3 -13
  23. data/lib/selenium/webdriver/common/options.rb +13 -5
  24. data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
  25. data/lib/selenium/webdriver/common/socket_poller.rb +30 -19
  26. data/lib/selenium/webdriver/common/target_locator.rb +28 -0
  27. data/lib/selenium/webdriver/common/timeouts.rb +31 -4
  28. data/lib/selenium/webdriver/common/window.rb +0 -4
  29. data/lib/selenium/webdriver/common.rb +6 -0
  30. data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
  31. data/lib/selenium/webdriver/devtools/request.rb +27 -17
  32. data/lib/selenium/webdriver/devtools/response.rb +66 -0
  33. data/lib/selenium/webdriver/devtools.rb +50 -12
  34. data/lib/selenium/webdriver/edge/features.rb +5 -0
  35. data/lib/selenium/webdriver/firefox/driver.rb +5 -0
  36. data/lib/selenium/webdriver/firefox/features.rb +14 -0
  37. data/lib/selenium/webdriver/firefox/options.rb +28 -1
  38. data/lib/selenium/webdriver/firefox.rb +0 -1
  39. data/lib/selenium/webdriver/ie/options.rb +3 -1
  40. data/lib/selenium/webdriver/ie/service.rb +1 -1
  41. data/lib/selenium/webdriver/remote/bridge.rb +39 -23
  42. data/lib/selenium/webdriver/remote/capabilities.rb +3 -2
  43. data/lib/selenium/webdriver/remote/commands.rb +4 -0
  44. data/lib/selenium/webdriver/remote/driver.rb +3 -1
  45. data/lib/selenium/webdriver/remote.rb +1 -1
  46. data/lib/selenium/webdriver/safari/driver.rb +1 -1
  47. data/lib/selenium/webdriver/safari/options.rb +7 -0
  48. data/lib/selenium/webdriver/support/event_firing_bridge.rb +2 -2
  49. data/lib/selenium/webdriver/version.rb +1 -1
  50. data/lib/selenium/webdriver.rb +1 -0
  51. data/selenium-webdriver.gemspec +3 -2
  52. metadata +31 -3
@@ -44,6 +44,34 @@ module Selenium
44
44
  @bridge.switch_to_parent_frame
45
45
  end
46
46
 
47
+ #
48
+ # Switch to a new top-level browsing context
49
+ #
50
+ # @param type either :tab or :window
51
+ #
52
+
53
+ def new_window(type = :window)
54
+ unless %i[window tab].include?(type)
55
+ raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}"
56
+ end
57
+
58
+ handle = @bridge.new_window(type)['handle']
59
+
60
+ if block_given?
61
+ execute_and_close = proc do
62
+ yield(self)
63
+ begin
64
+ @bridge.close
65
+ rescue Error::NoSuchWindowError
66
+ # window already closed
67
+ end
68
+ end
69
+ window(handle, &execute_and_close)
70
+ else
71
+ window(handle)
72
+ end
73
+ end
74
+
47
75
  #
48
76
  # switch to the given window handle
49
77
  #
@@ -24,22 +24,49 @@ module Selenium
24
24
  @bridge = bridge
25
25
  end
26
26
 
27
+ #
28
+ # Gets the amount of time the driver should wait when searching for elements.
29
+ #
30
+
31
+ def implicit_wait
32
+ Float(@bridge.timeouts['implicit']) / 1000
33
+ end
34
+
27
35
  #
28
36
  # Set the amount of time the driver should wait when searching for elements.
29
37
  #
30
38
 
31
39
  def implicit_wait=(seconds)
32
- @bridge.implicit_wait_timeout = Integer(seconds * 1000)
40
+ @bridge.timeouts = {'implicit' => Integer(seconds * 1000)}
33
41
  end
34
42
 
43
+ #
44
+ # Gets the amount of time to wait for an asynchronous script to finish
45
+ # execution before throwing an error.
46
+ #
47
+
48
+ def script
49
+ Float(@bridge.timeouts['script']) / 1000
50
+ end
51
+ alias_method :script_timeout, :script
52
+
35
53
  #
36
54
  # Sets the amount of time to wait for an asynchronous script to finish
37
55
  # execution before throwing an error. If the timeout is negative, then the
38
56
  # script will be allowed to run indefinitely.
39
57
  #
40
58
 
41
- def script_timeout=(seconds)
42
- @bridge.script_timeout = Integer(seconds * 1000)
59
+ def script=(seconds)
60
+ @bridge.timeouts = {'script' => Integer(seconds * 1000)}
61
+ end
62
+ alias_method :script_timeout=, :script=
63
+
64
+ #
65
+ # Gets the amount of time to wait for a page load to complete before throwing an error.
66
+ #
67
+
68
+ def page_load
69
+ Float(@bridge.timeouts['pageLoad']) / 1000
43
70
  end
44
71
 
45
72
  #
@@ -48,7 +75,7 @@ module Selenium
48
75
  #
49
76
 
50
77
  def page_load=(seconds)
51
- @bridge.timeout 'page load', Integer(seconds * 1000)
78
+ @bridge.timeouts = {'pageLoad' => Integer(seconds * 1000)}
52
79
  end
53
80
  end # Timeouts
54
81
  end # WebDriver
@@ -19,10 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- #
23
- # @api beta This API may be changed or removed in a future release.
24
- #
25
-
26
22
  class Window
27
23
  #
28
24
  # @api private
@@ -58,8 +58,10 @@ require 'selenium/webdriver/common/driver_extensions/has_remote_status'
58
58
  require 'selenium/webdriver/common/driver_extensions/has_network_conditions'
59
59
  require 'selenium/webdriver/common/driver_extensions/has_network_connection'
60
60
  require 'selenium/webdriver/common/driver_extensions/has_network_interception'
61
+ require 'selenium/webdriver/common/driver_extensions/has_apple_permissions'
61
62
  require 'selenium/webdriver/common/driver_extensions/has_permissions'
62
63
  require 'selenium/webdriver/common/driver_extensions/has_debugger'
64
+ require 'selenium/webdriver/common/driver_extensions/has_context'
63
65
  require 'selenium/webdriver/common/driver_extensions/prints_page'
64
66
  require 'selenium/webdriver/common/driver_extensions/uploads_files'
65
67
  require 'selenium/webdriver/common/driver_extensions/full_page_screenshot'
@@ -68,10 +70,14 @@ require 'selenium/webdriver/common/driver_extensions/has_devtools'
68
70
  require 'selenium/webdriver/common/driver_extensions/has_authentication'
69
71
  require 'selenium/webdriver/common/driver_extensions/has_logs'
70
72
  require 'selenium/webdriver/common/driver_extensions/has_log_events'
73
+ require 'selenium/webdriver/common/driver_extensions/has_pinned_scripts'
71
74
  require 'selenium/webdriver/common/driver_extensions/has_cdp'
75
+ require 'selenium/webdriver/common/driver_extensions/has_casting'
76
+ require 'selenium/webdriver/common/driver_extensions/has_launching'
72
77
  require 'selenium/webdriver/common/keys'
73
78
  require 'selenium/webdriver/common/profile_helper'
74
79
  require 'selenium/webdriver/common/options'
75
80
  require 'selenium/webdriver/common/takes_screenshot'
76
81
  require 'selenium/webdriver/common/driver'
77
82
  require 'selenium/webdriver/common/element'
83
+ require 'selenium/webdriver/common/shadow_root'
@@ -0,0 +1,59 @@
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 DevTools
23
+ class PinnedScript
24
+
25
+ attr_accessor :key, :devtools_identifier, :script
26
+
27
+ def initialize(script)
28
+ @key = SecureRandom.alphanumeric
29
+ @script = script
30
+ end
31
+
32
+ #
33
+ # @api private
34
+ #
35
+
36
+ def callable
37
+ "function __webdriver_#{key}(arguments) { #{script} }"
38
+ end
39
+
40
+ #
41
+ # @api private
42
+ #
43
+
44
+ def to_json(*)
45
+ %{"return __webdriver_#{key}(arguments)"}
46
+ end
47
+
48
+ #
49
+ # @api private
50
+ #
51
+
52
+ def remove
53
+ "__webdriver_#{key} = undefined"
54
+ end
55
+
56
+ end # PinnedScript
57
+ end # DevTools
58
+ end # WebDriver
59
+ end # Selenium
@@ -22,33 +22,43 @@ module Selenium
22
22
  class DevTools
23
23
  class Request
24
24
 
25
- attr_reader :url, :method, :headers
25
+ attr_accessor :url, :method, :headers, :post_data
26
+ attr_reader :id
26
27
 
27
- def initialize(devtools:, id:, url:, method:, headers:)
28
- @devtools = devtools
28
+ #
29
+ # Creates request from DevTools message.
30
+ # @api private
31
+ #
32
+
33
+ def self.from(id, params)
34
+ new(
35
+ id: id,
36
+ url: params.dig('request', 'url'),
37
+ method: params.dig('request', 'method'),
38
+ headers: params.dig('request', 'headers'),
39
+ post_data: params.dig('request', 'postData')
40
+ )
41
+ end
42
+
43
+ def initialize(id:, url:, method:, headers:, post_data:)
29
44
  @id = id
30
45
  @url = url
31
46
  @method = method
32
47
  @headers = headers
48
+ @post_data = post_data
33
49
  end
34
50
 
35
- def continue
36
- @devtools.fetch.continue_request(request_id: @id)
37
- end
38
-
39
- def respond(code: 200, headers: {}, body: '')
40
- @devtools.fetch.fulfill_request(
41
- request_id: @id,
42
- body: Base64.strict_encode64(body),
43
- response_code: code,
44
- response_headers: headers.map do |k, v|
45
- {name: k, value: v}
46
- end
47
- )
51
+ def ==(other)
52
+ self.class == other.class &&
53
+ id == other.id &&
54
+ url == other.url &&
55
+ method == other.method &&
56
+ headers == other.headers &&
57
+ post_data == other.post_data
48
58
  end
49
59
 
50
60
  def inspect
51
- %(#<#{self.class.name} @method="#{method}" @url="#{url}")
61
+ %(#<#{self.class.name} @id="#{id}" @method="#{method}" @url="#{url}")
52
62
  end
53
63
 
54
64
  end # Request
@@ -0,0 +1,66 @@
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 DevTools
23
+ class Response
24
+
25
+ attr_accessor :code, :body, :headers
26
+ attr_reader :id
27
+
28
+ #
29
+ # Creates response from DevTools message.
30
+ # @api private
31
+ #
32
+
33
+ def self.from(id, encoded_body, params)
34
+ new(
35
+ id: id,
36
+ code: params['responseStatusCode'],
37
+ body: (Base64.strict_decode64(encoded_body) if encoded_body),
38
+ headers: params['responseHeaders'].each_with_object({}) do |header, hash|
39
+ hash[header['name']] = header['value']
40
+ end
41
+ )
42
+ end
43
+
44
+ def initialize(id:, code:, body:, headers:)
45
+ @id = id
46
+ @code = code
47
+ @body = body
48
+ @headers = headers
49
+ end
50
+
51
+ def ==(other)
52
+ self.class == other.class &&
53
+ id == other.id &&
54
+ code == other.code &&
55
+ body == other.body &&
56
+ headers == other.headers
57
+ end
58
+
59
+ def inspect
60
+ %(#<#{self.class.name} @id="#{id}" @code="#{code}")
61
+ end
62
+
63
+ end # Response
64
+ end # DevTools
65
+ end # WebDriver
66
+ end # Selenium
@@ -20,21 +20,34 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class DevTools
23
+ RESPONSE_WAIT_TIMEOUT = 30
24
+ RESPONSE_WAIT_INTERVAL = 0.1
25
+
23
26
  autoload :ConsoleEvent, 'selenium/webdriver/devtools/console_event'
24
27
  autoload :ExceptionEvent, 'selenium/webdriver/devtools/exception_event'
25
28
  autoload :MutationEvent, 'selenium/webdriver/devtools/mutation_event'
29
+ autoload :PinnedScript, 'selenium/webdriver/devtools/pinned_script'
26
30
  autoload :Request, 'selenium/webdriver/devtools/request'
31
+ autoload :Response, 'selenium/webdriver/devtools/response'
27
32
 
28
33
  def initialize(url:)
34
+ @callback_threads = ThreadGroup.new
35
+
29
36
  @messages = []
30
37
  @session_id = nil
31
38
  @url = url
32
39
 
33
40
  process_handshake
34
- attach_socket_listener
41
+ @socket_thread = attach_socket_listener
35
42
  start_session
36
43
  end
37
44
 
45
+ def close
46
+ @callback_threads.list.each(&:exit)
47
+ @socket_thread.exit
48
+ socket.close
49
+ end
50
+
38
51
  def callbacks
39
52
  @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] }
40
53
  end
@@ -84,27 +97,24 @@ module Selenium
84
97
  end
85
98
 
86
99
  def attach_socket_listener
87
- socket_listener = Thread.new do
100
+ Thread.new do
101
+ Thread.current.abort_on_exception = true
102
+ Thread.current.report_on_exception = false
103
+
88
104
  until socket.eof?
89
105
  incoming_frame << socket.readpartial(1024)
90
106
 
91
107
  while (frame = incoming_frame.next)
92
- # Firefox will periodically fail on unparsable empty frame
93
- break if frame.to_s.empty?
94
-
95
- message = JSON.parse(frame.to_s)
96
- @messages << message
97
- WebDriver.logger.debug "DevTools <- #{message}"
108
+ message = process_frame(frame)
98
109
  next unless message['method']
99
110
 
111
+ params = message['params']
100
112
  callbacks[message['method']].each do |callback|
101
- params = message['params'] # take in current thread!
102
- Thread.new { callback.call(params) }
113
+ @callback_threads.add(callback_thread(params, &callback))
103
114
  end
104
115
  end
105
116
  end
106
117
  end
107
- socket_listener.abort_on_exception = true
108
118
  end
109
119
 
110
120
  def start_session
@@ -118,8 +128,36 @@ module Selenium
118
128
  @incoming_frame ||= WebSocket::Frame::Incoming::Client.new(version: ws.version)
119
129
  end
120
130
 
131
+ def process_frame(frame)
132
+ message = frame.to_s
133
+
134
+ # Firefox will periodically fail on unparsable empty frame
135
+ return {} if message.empty?
136
+
137
+ message = JSON.parse(message)
138
+ @messages << message
139
+ WebDriver.logger.debug "DevTools <- #{message}"
140
+
141
+ message
142
+ end
143
+
144
+ def callback_thread(params)
145
+ Thread.new do
146
+ Thread.current.abort_on_exception = true
147
+
148
+ # We might end up blocked forever when we have an error in event.
149
+ # For example, if network interception event raises error,
150
+ # the browser will keep waiting for the request to be proceeded
151
+ # before returning back to the original thread. In this case,
152
+ # we should at least print the error.
153
+ Thread.current.report_on_exception = true
154
+
155
+ yield params
156
+ end
157
+ end
158
+
121
159
  def wait
122
- @wait ||= Wait.new(timeout: 10, interval: 0.1)
160
+ @wait ||= Wait.new(timeout: RESPONSE_WAIT_TIMEOUT, interval: RESPONSE_WAIT_INTERVAL)
123
161
  end
124
162
 
125
163
  def socket
@@ -27,6 +27,11 @@ module Selenium
27
27
  include WebDriver::Chrome::Features
28
28
 
29
29
  EDGE_COMMANDS = {
30
+ get_cast_sinks: [:get, 'session/:session_id/ms/cast/get_sinks'],
31
+ set_cast_sink_to_use: [:post, 'session/:session_id/ms/cast/set_sink_to_use'],
32
+ start_cast_tab_mirroring: [:post, 'session/:session_id/ms/cast/start_tab_mirroring'],
33
+ get_cast_issue_message: [:get, 'session/:session_id/ms/cast/get_issue_message'],
34
+ stop_casting: [:post, 'session/:session_id/ms/cast/stop_casting'],
30
35
  send_command: [:post, 'session/:session_id/ms/cdp/execute']
31
36
  }.freeze
32
37
 
@@ -29,6 +29,7 @@ module Selenium
29
29
  class Driver < WebDriver::Driver
30
30
  EXTENSIONS = [DriverExtensions::HasAddons,
31
31
  DriverExtensions::FullPageScreenshot,
32
+ DriverExtensions::HasContext,
32
33
  DriverExtensions::HasDevTools,
33
34
  DriverExtensions::HasLogEvents,
34
35
  DriverExtensions::HasNetworkInterception,
@@ -42,6 +43,10 @@ module Selenium
42
43
  private
43
44
 
44
45
  def devtools_url
46
+ if capabilities['moz:debuggerAddress'].nil?
47
+ raise(Error::WebDriverError, "DevTools is not supported by this version of Firefox; use v85 or higher")
48
+ end
49
+
45
50
  uri = URI("http://#{capabilities['moz:debuggerAddress']}")
46
51
  response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
47
52
 
@@ -23,6 +23,8 @@ module Selenium
23
23
  module Features
24
24
 
25
25
  FIREFOX_COMMANDS = {
26
+ get_context: [:get, 'session/:session_id/moz/context'],
27
+ set_context: [:post, 'session/:session_id/moz/context'],
26
28
  install_addon: [:post, 'session/:session_id/moz/addon/install'],
27
29
  uninstall_addon: [:post, 'session/:session_id/moz/addon/uninstall'],
28
30
  full_page_screenshot: [:get, 'session/:session_id/moz/screenshot/full']
@@ -33,6 +35,11 @@ module Selenium
33
35
  end
34
36
 
35
37
  def install_addon(path, temporary)
38
+ if @file_detector
39
+ local_file = @file_detector.call(path)
40
+ path = upload(local_file) if local_file
41
+ end
42
+
36
43
  payload = {path: path}
37
44
  payload[:temporary] = temporary unless temporary.nil?
38
45
  execute :install_addon, {}, payload
@@ -46,6 +53,13 @@ module Selenium
46
53
  execute :full_page_screenshot
47
54
  end
48
55
 
56
+ def context=(context)
57
+ execute :set_context, {}, {context: context}
58
+ end
59
+
60
+ def context
61
+ execute :get_context
62
+ end
49
63
  end # Bridge
50
64
  end # Firefox
51
65
  end # WebDriver
@@ -29,7 +29,11 @@ module Selenium
29
29
  CAPABILITIES = {binary: 'binary',
30
30
  args: 'args',
31
31
  log: 'log',
32
- prefs: 'prefs'}.freeze
32
+ prefs: 'prefs',
33
+ android_package: 'androidPackage',
34
+ android_activity: 'androidActivity',
35
+ android_device_serial: 'androidDeviceSerial',
36
+ android_intent_arguments: 'androidIntentArguments'}.freeze
33
37
  BROWSER = 'firefox'
34
38
 
35
39
  # NOTE: special handling of 'profile' to validate when set instead of when used
@@ -131,6 +135,25 @@ module Selenium
131
135
  @options[:log] = {level: level}
132
136
  end
133
137
 
138
+ #
139
+ # Enables mobile browser use on Android.
140
+ #
141
+ # @see https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions#android
142
+ #
143
+ # @param [String] package The package name of the Chrome or WebView app.
144
+ # @param [String] serial_number The serial number of the device on which to launch the application.
145
+ # If not specified and multiple devices are attached, an error will be returned.
146
+ # @param [String] activity The fully qualified class name of the activity to be launched.
147
+ # @param [Array] intent_arguments Arguments to launch the intent with.
148
+ #
149
+
150
+ def enable_android(package: 'org.mozilla.firefox', serial_number: nil, activity: nil, intent_arguments: nil)
151
+ @options[:android_package] = package
152
+ @options[:android_activity] = activity unless activity.nil?
153
+ @options[:android_device_serial] = serial_number unless serial_number.nil?
154
+ @options[:android_intent_arguments] = intent_arguments unless intent_arguments.nil?
155
+ end
156
+
134
157
  private
135
158
 
136
159
  def process_browser_options(browser_options)
@@ -150,6 +173,10 @@ module Selenium
150
173
  Profile.from_name(profile)
151
174
  end
152
175
  end
176
+
177
+ def camelize?(key)
178
+ key != :prefs
179
+ end
153
180
  end # Options
154
181
  end # Firefox
155
182
  end # WebDriver
@@ -33,7 +33,6 @@ module Selenium
33
33
  autoload :Service, 'selenium/webdriver/firefox/service'
34
34
 
35
35
  DEFAULT_PORT = 7055
36
- DEFAULT_ENABLE_NATIVE_EVENTS = Platform.os == :windows
37
36
  DEFAULT_SECURE_SSL = false
38
37
  DEFAULT_ASSUME_UNTRUSTED_ISSUER = true
39
38
  DEFAULT_LOAD_NO_FOCUS_LIB = false
@@ -39,7 +39,9 @@ module Selenium
39
39
  persistent_hover: 'enablePersistentHover',
40
40
  require_window_focus: 'requireWindowFocus',
41
41
  use_per_process_proxy: 'ie.usePerProcessProxy',
42
- validate_cookie_document_type: 'ie.validateCookieDocumentType'
42
+ use_legacy_file_upload_dialog_handling: 'ie.useLegacyFileUploadDialogHandling',
43
+ attach_to_edge_chrome: 'ie.edgechromium',
44
+ edge_executable_path: 'ie.edgepath'
43
45
  }.freeze
44
46
  BROWSER = 'internet explorer'
45
47
 
@@ -25,7 +25,7 @@ module Selenium
25
25
  EXECUTABLE = 'IEDriverServer'
26
26
  MISSING_TEXT = <<~ERROR
27
27
  Unable to find IEDriverServer. Please download the server from
28
- http://selenium-release.storage.googleapis.com/index.html and place it somewhere on your PATH.
28
+ https://www.selenium.dev/downloads/ and place it somewhere on your PATH.
29
29
  More info at https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver.
30
30
  ERROR
31
31
  SHUTDOWN_SUPPORTED = true