selenium-webdriver 3.142.7 → 4.0.3

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.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +350 -5
  3. data/Gemfile +3 -1
  4. data/LICENSE +1 -1
  5. data/NOTICE +2 -0
  6. data/README.md +4 -5
  7. data/lib/selenium/server.rb +69 -63
  8. data/lib/selenium/webdriver/atoms/findElements.js +122 -0
  9. data/lib/selenium/webdriver/atoms/getAttribute.js +100 -7
  10. data/lib/selenium/webdriver/atoms/isDisplayed.js +76 -78
  11. data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
  12. data/lib/selenium/webdriver/chrome/driver.rb +26 -83
  13. data/lib/selenium/webdriver/chrome/{bridge.rb → features.rb} +50 -12
  14. data/lib/selenium/webdriver/chrome/options.rb +129 -58
  15. data/lib/selenium/webdriver/chrome/profile.rb +6 -3
  16. data/lib/selenium/webdriver/chrome/service.rb +8 -15
  17. data/lib/selenium/webdriver/chrome.rb +10 -9
  18. data/lib/selenium/webdriver/common/action_builder.rb +97 -249
  19. data/lib/selenium/webdriver/common/driver.rb +112 -23
  20. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
  23. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/{has_touch_screen.rb → has_cdp.rb} +10 -8
  25. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
  26. data/lib/selenium/webdriver/{firefox/util.rb → common/driver_extensions/has_devtools.rb} +16 -19
  27. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
  28. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
  29. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +144 -0
  30. data/lib/selenium/webdriver/common/driver_extensions/has_logs.rb +30 -0
  31. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
  32. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
  33. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +136 -0
  34. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
  35. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
  36. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +1 -0
  37. data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
  38. data/lib/selenium/webdriver/common/element.rb +82 -22
  39. data/lib/selenium/webdriver/common/error.rb +32 -196
  40. data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
  41. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -5
  42. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +13 -13
  43. data/lib/selenium/webdriver/common/log_entry.rb +2 -2
  44. data/lib/selenium/webdriver/common/logger.rb +50 -15
  45. data/lib/selenium/webdriver/common/manager.rb +15 -15
  46. data/lib/selenium/webdriver/common/options.rb +154 -23
  47. data/lib/selenium/webdriver/common/platform.rb +6 -1
  48. data/lib/selenium/webdriver/common/port_prober.rb +4 -6
  49. data/lib/selenium/webdriver/common/profile_helper.rb +11 -9
  50. data/lib/selenium/webdriver/common/proxy.rb +6 -3
  51. data/lib/selenium/webdriver/common/search_context.rb +7 -3
  52. data/lib/selenium/webdriver/common/service.rb +17 -125
  53. data/lib/selenium/webdriver/common/service_manager.rb +151 -0
  54. data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
  55. data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
  56. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  57. data/lib/selenium/webdriver/common/takes_screenshot.rb +66 -0
  58. data/lib/selenium/webdriver/common/target_locator.rb +32 -4
  59. data/lib/selenium/webdriver/common/timeouts.rb +31 -4
  60. data/lib/selenium/webdriver/common/wait.rb +1 -1
  61. data/lib/selenium/webdriver/common/window.rb +0 -4
  62. data/lib/selenium/webdriver/common/zipper.rb +1 -9
  63. data/lib/selenium/webdriver/common.rb +23 -17
  64. data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
  65. data/lib/selenium/webdriver/devtools/exception_event.rb +36 -0
  66. data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
  67. data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
  68. data/lib/selenium/webdriver/devtools/request.rb +67 -0
  69. data/lib/selenium/webdriver/devtools/response.rb +66 -0
  70. data/lib/selenium/webdriver/devtools.rb +182 -0
  71. data/lib/selenium/webdriver/edge/driver.rb +7 -29
  72. data/lib/selenium/webdriver/edge/features.rb +44 -0
  73. data/lib/selenium/webdriver/edge/options.rb +11 -48
  74. data/lib/selenium/webdriver/{common/w3c_manager.rb → edge/profile.rb} +7 -19
  75. data/lib/selenium/webdriver/edge/service.rb +10 -26
  76. data/lib/selenium/webdriver/edge.rb +11 -14
  77. data/lib/selenium/webdriver/firefox/driver.rb +31 -19
  78. data/lib/selenium/webdriver/firefox/extension.rb +8 -0
  79. data/lib/selenium/webdriver/firefox/features.rb +66 -0
  80. data/lib/selenium/webdriver/firefox/options.rb +70 -49
  81. data/lib/selenium/webdriver/firefox/profile.rb +21 -71
  82. data/lib/selenium/webdriver/firefox/service.rb +5 -9
  83. data/lib/selenium/webdriver/firefox.rb +22 -20
  84. data/lib/selenium/webdriver/ie/driver.rb +1 -47
  85. data/lib/selenium/webdriver/ie/options.rb +13 -44
  86. data/lib/selenium/webdriver/ie/service.rb +13 -15
  87. data/lib/selenium/webdriver/ie.rb +8 -7
  88. data/lib/selenium/webdriver/remote/bridge.rb +558 -86
  89. data/lib/selenium/webdriver/remote/capabilities.rb +159 -123
  90. data/lib/selenium/webdriver/remote/commands.rb +163 -0
  91. data/lib/selenium/webdriver/remote/driver.rb +22 -12
  92. data/lib/selenium/webdriver/remote/http/common.rb +0 -5
  93. data/lib/selenium/webdriver/remote/http/default.rb +17 -20
  94. data/lib/selenium/webdriver/remote/http/persistent.rb +11 -6
  95. data/lib/selenium/webdriver/remote/response.rb +16 -47
  96. data/lib/selenium/webdriver/remote.rb +15 -13
  97. data/lib/selenium/webdriver/safari/driver.rb +3 -31
  98. data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -3
  99. data/lib/selenium/webdriver/safari/options.rb +10 -29
  100. data/lib/selenium/webdriver/safari/service.rb +4 -8
  101. data/lib/selenium/webdriver/safari.rb +17 -9
  102. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
  103. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
  104. data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
  105. data/lib/selenium/webdriver/support/color.rb +2 -2
  106. data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
  107. data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
  108. data/lib/selenium/webdriver/{firefox/marionette/bridge.rb → support/guards/guard_condition.rb} +22 -19
  109. data/lib/selenium/webdriver/support/guards.rb +95 -0
  110. data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
  111. data/lib/selenium/webdriver/support/select.rb +3 -3
  112. data/lib/selenium/webdriver/support.rb +1 -0
  113. data/lib/selenium/webdriver/version.rb +1 -1
  114. data/lib/selenium/webdriver.rb +12 -12
  115. data/selenium-webdriver.gemspec +28 -12
  116. metadata +128 -69
  117. data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
  118. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
  119. data/lib/selenium/webdriver/common/keyboard.rb +0 -70
  120. data/lib/selenium/webdriver/common/mouse.rb +0 -89
  121. data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -78
  122. data/lib/selenium/webdriver/common/touch_screen.rb +0 -123
  123. data/lib/selenium/webdriver/common/w3c_action_builder.rb +0 -212
  124. data/lib/selenium/webdriver/edge/bridge.rb +0 -76
  125. data/lib/selenium/webdriver/firefox/binary.rb +0 -187
  126. data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
  127. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  128. data/lib/selenium/webdriver/firefox/launcher.rb +0 -111
  129. data/lib/selenium/webdriver/firefox/legacy/driver.rb +0 -83
  130. data/lib/selenium/webdriver/firefox/marionette/driver.rb +0 -90
  131. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  132. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  133. data/lib/selenium/webdriver/remote/oss/bridge.rb +0 -594
  134. data/lib/selenium/webdriver/remote/oss/commands.rb +0 -223
  135. data/lib/selenium/webdriver/remote/w3c/bridge.rb +0 -605
  136. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +0 -310
  137. data/lib/selenium/webdriver/remote/w3c/commands.rb +0 -157
@@ -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
@@ -0,0 +1,67 @@
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 Request
24
+
25
+ attr_accessor :url, :method, :headers, :post_data
26
+ attr_reader :id
27
+
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:)
44
+ @id = id
45
+ @url = url
46
+ @method = method
47
+ @headers = headers
48
+ @post_data = post_data
49
+ end
50
+
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
58
+ end
59
+
60
+ def inspect
61
+ %(#<#{self.class.name} @id="#{id}" @method="#{method}" @url="#{url}")
62
+ end
63
+
64
+ end # Request
65
+ end # DevTools
66
+ end # WebDriver
67
+ end # Selenium
@@ -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
@@ -0,0 +1,182 @@
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
+ RESPONSE_WAIT_TIMEOUT = 30
24
+ RESPONSE_WAIT_INTERVAL = 0.1
25
+
26
+ autoload :ConsoleEvent, 'selenium/webdriver/devtools/console_event'
27
+ autoload :ExceptionEvent, 'selenium/webdriver/devtools/exception_event'
28
+ autoload :MutationEvent, 'selenium/webdriver/devtools/mutation_event'
29
+ autoload :PinnedScript, 'selenium/webdriver/devtools/pinned_script'
30
+ autoload :Request, 'selenium/webdriver/devtools/request'
31
+ autoload :Response, 'selenium/webdriver/devtools/response'
32
+
33
+ def initialize(url:)
34
+ @callback_threads = ThreadGroup.new
35
+
36
+ @messages = []
37
+ @session_id = nil
38
+ @url = url
39
+
40
+ process_handshake
41
+ @socket_thread = attach_socket_listener
42
+ start_session
43
+ end
44
+
45
+ def close
46
+ @callback_threads.list.each(&:exit)
47
+ @socket_thread.exit
48
+ socket.close
49
+ end
50
+
51
+ def callbacks
52
+ @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] }
53
+ end
54
+
55
+ def send_cmd(method, **params)
56
+ id = next_id
57
+ data = {id: id, method: method, params: params.reject { |_, v| v.nil? }}
58
+ data[:sessionId] = @session_id if @session_id
59
+ data = JSON.generate(data)
60
+ WebDriver.logger.debug "DevTools -> #{data}"
61
+
62
+ out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text')
63
+ socket.write(out_frame.to_s)
64
+
65
+ message = wait.until do
66
+ @messages.find { |m| m['id'] == id }
67
+ end
68
+
69
+ raise Error::WebDriverError, error_message(message['error']) if message['error']
70
+
71
+ message
72
+ end
73
+
74
+ def method_missing(method, *_args)
75
+ desired_class = "Selenium::DevTools::V#{Selenium::DevTools.version}::#{method.capitalize}"
76
+ return unless Object.const_defined?(desired_class)
77
+
78
+ self.class.class_eval do
79
+ define_method(method) do
80
+ Object.const_get(desired_class).new(self)
81
+ end
82
+ end
83
+
84
+ send(method)
85
+ end
86
+
87
+ def respond_to_missing?(method, *_args)
88
+ desired_class = "Selenium::DevTools::V#{Selenium::DevTools.version}::#{method.capitalize}"
89
+ Object.const_defined?(desired_class)
90
+ end
91
+
92
+ private
93
+
94
+ def process_handshake
95
+ socket.print(ws.to_s)
96
+ ws << socket.readpartial(1024)
97
+ end
98
+
99
+ def attach_socket_listener
100
+ Thread.new do
101
+ Thread.current.abort_on_exception = true
102
+ Thread.current.report_on_exception = false
103
+
104
+ until socket.eof?
105
+ incoming_frame << socket.readpartial(1024)
106
+
107
+ while (frame = incoming_frame.next)
108
+ message = process_frame(frame)
109
+ next unless message['method']
110
+
111
+ params = message['params']
112
+ callbacks[message['method']].each do |callback|
113
+ @callback_threads.add(callback_thread(params, &callback))
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def start_session
121
+ targets = target.get_targets.dig('result', 'targetInfos')
122
+ page_target = targets.find { |target| target['type'] == 'page' }
123
+ session = target.attach_to_target(target_id: page_target['targetId'], flatten: true)
124
+ @session_id = session.dig('result', 'sessionId')
125
+ end
126
+
127
+ def incoming_frame
128
+ @incoming_frame ||= WebSocket::Frame::Incoming::Client.new(version: ws.version)
129
+ end
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
+
159
+ def wait
160
+ @wait ||= Wait.new(timeout: RESPONSE_WAIT_TIMEOUT, interval: RESPONSE_WAIT_INTERVAL)
161
+ end
162
+
163
+ def socket
164
+ @socket ||= TCPSocket.new(ws.host, ws.port)
165
+ end
166
+
167
+ def ws
168
+ @ws ||= WebSocket::Handshake::Client.new(url: @url)
169
+ end
170
+
171
+ def next_id
172
+ @id ||= 0
173
+ @id += 1
174
+ end
175
+
176
+ def error_message(error)
177
+ [error['code'], error['message'], error['data']].join(': ')
178
+ end
179
+
180
+ end # DevTools
181
+ end # WebDriver
182
+ end # Selenium
@@ -17,6 +17,8 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chrome/driver'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Edge
@@ -26,40 +28,16 @@ module Selenium
26
28
  # @api private
27
29
  #
28
30
 
29
- class Driver < WebDriver::Driver
30
- include DriverExtensions::TakesScreenshot
31
-
32
- def initialize(opts = {})
33
- opts[:desired_capabilities] ||= Remote::Capabilities.edge
34
-
35
- opts[:url] ||= service_url(opts)
36
-
37
- listener = opts.delete(:listener)
38
-
39
- # Edge is mostly using W3C dialect, but a request to
40
- # create session responds with OSS-like body,
41
- # so we need to force W3C implementation.
42
- desired_capabilities = opts.delete(:desired_capabilities)
43
- bridge = Remote::Bridge.new(opts)
44
- capabilities = bridge.create_session(desired_capabilities)
45
-
46
- WebDriver.logger.info 'Forcing W3C dialect.'
47
- @bridge = Remote::W3C::Bridge.new(capabilities, bridge.session_id, **opts)
48
- @bridge.extend Edge::Bridge
49
-
50
- super(@bridge, listener: listener)
51
- end
52
-
31
+ class Driver < Selenium::WebDriver::Chrome::Driver
53
32
  def browser
54
33
  :edge
55
34
  end
56
35
 
57
- def quit
58
- super
59
- ensure
60
- @service&.stop
61
- end
36
+ private
62
37
 
38
+ def devtools_address
39
+ "http://#{capabilities['ms:edgeOptions']['debuggerAddress']}"
40
+ end
63
41
  end # Driver
64
42
  end # Edge
65
43
  end # WebDriver
@@ -0,0 +1,44 @@
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 'selenium/webdriver/chrome/features'
21
+
22
+ module Selenium
23
+ module WebDriver
24
+ module Edge
25
+ module Features
26
+
27
+ include WebDriver::Chrome::Features
28
+
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'],
35
+ send_command: [:post, 'session/:session_id/ms/cdp/execute']
36
+ }.freeze
37
+
38
+ def commands(command)
39
+ EDGE_COMMANDS[command] || Chrome::Features::CHROME_COMMANDS[command] || self.class::COMMANDS[command]
40
+ end
41
+ end # Bridge
42
+ end # Edge
43
+ end # WebDriver
44
+ end # Selenium
@@ -17,62 +17,25 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chrome/options'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Edge
23
- class Options
24
- attr_accessor :in_private, :start_page
25
- attr_reader :extension_paths
25
+ class Options < Selenium::WebDriver::Chrome::Options
26
+ KEY = 'ms:edgeOptions'
27
+ BROWSER = 'MicrosoftEdge'
26
28
 
27
- #
28
- # Create a new Options instance for Edge.
29
- #
30
- # @example
31
- # options = Selenium::WebDriver::Edge::Options.new(in_private: true)
32
- # driver = Selenium::WebDriver.for :edge, options: options
33
- #
34
- # @param [Hash] opts the pre-defined options to create the Edge::Options with
35
- # @option opts [Boolean] :in_private Start in private mode. Default is false
36
- # @option opts [Array<String>] :extension_paths A list of full paths to extensions to install on startup
37
- # @option opts [String] :start_page Default page to start with
38
- #
39
- # @see https://docs.microsoft.com/en-us/microsoft-edge/webdriver
40
- #
29
+ protected
41
30
 
42
- def initialize(**opts)
43
- @in_private = opts.delete(:in_private) || false
44
- @extension_paths = opts.delete(:extension_paths) || []
45
- @start_page = opts.delete(:start_page)
31
+ def enable_logging(browser_options)
32
+ browser_options['ms:loggingPrefs'] = @logging_prefs
46
33
  end
47
34
 
48
- #
49
- # Add an extension by local path.
50
- #
51
- # @example
52
- # options = Selenium::WebDriver::Edge::Options.new
53
- # options.add_extension_path('C:\path\to\extension')
54
- #
55
- # @param [String] path The local path to the extension folder
56
- #
57
-
58
- def add_extension_path(path)
59
- raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.directory?(path)
60
-
61
- @extension_paths << path
62
- end
63
-
64
- #
65
- # @api private
66
- #
67
-
68
- def as_json(*)
69
- opts = {}
70
-
71
- opts['ms:inPrivate'] = true if @in_private
72
- opts['ms:extensionPaths'] = @extension_paths if @extension_paths.any?
73
- opts['ms:startPage'] = @start_page if @start_page
35
+ private
74
36
 
75
- opts
37
+ def binary_path
38
+ Edge.path
76
39
  end
77
40
  end # Options
78
41
  end # Edge
@@ -17,29 +17,17 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chrome/profile'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
- class W3CManager < Manager
23
-
24
- #
25
- # Get the cookie with the given name
26
- #
27
- # @param [String] name the name of the cookie
28
- # @return [Hash, nil] the cookie, or nil if it wasn't found.
24
+ module Edge
29
25
  #
30
-
31
- def cookie_named(name)
32
- convert_cookie(@bridge.cookie(name))
33
- end
34
-
26
+ # @private
35
27
  #
36
- # Delete all cookies
37
- #
38
-
39
- def delete_all_cookies
40
- @bridge.delete_all_cookies
41
- end
42
28
 
43
- end # WC3Options
29
+ class Profile < Selenium::WebDriver::Chrome::Profile
30
+ end # Profile
31
+ end # Edge
44
32
  end # WebDriver
45
33
  end # Selenium
@@ -17,36 +17,20 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chrome/service'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Edge
23
- #
24
- # @api private
25
- #
26
-
27
- class Service < WebDriver::Service
28
- @default_port = 17556
29
- @executable = 'MicrosoftWebDriver'
30
- @missing_text = <<~ERROR
31
- Unable to find MicrosoftWebDriver. Please download the server from
32
- https://www.microsoft.com/en-us/download/details.aspx?id=48212 and place it somewhere on your PATH.
33
- More info at https://github.com/SeleniumHQ/selenium/wiki/MicrosoftWebDriver.
25
+ class Service < Selenium::WebDriver::Chrome::Service
26
+ DEFAULT_PORT = 9515
27
+ EXECUTABLE = 'msedgedriver'
28
+ MISSING_TEXT = <<~ERROR
29
+ Unable to find msedgedriver. Please download the server from
30
+ https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ and place it somewhere on your PATH.
34
31
  ERROR
35
- @shutdown_supported = true
36
-
37
- private
38
-
39
- # Note: This processing is deprecated
40
- def extract_service_args(driver_opts)
41
- driver_args = super
42
- driver_opts = driver_opts.dup
43
- driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key? :host
44
- driver_args << "--package=#{driver_opts[:package]}" if driver_opts.key? :package
45
- driver_args << "--silent" if driver_opts[:silent] == true
46
- driver_args << "--verbose" if driver_opts[:verbose] == true
47
- driver_args
48
- end
32
+ SHUTDOWN_SUPPORTED = true
49
33
  end # Service
50
34
  end # Edge
51
35
  end # WebDriver
52
- end # Service
36
+ end # Selenium
@@ -19,26 +19,23 @@
19
19
 
20
20
  require 'net/http'
21
21
 
22
- require 'selenium/webdriver/edge/bridge'
23
- require 'selenium/webdriver/edge/driver'
24
- require 'selenium/webdriver/edge/options'
25
-
26
22
  module Selenium
27
23
  module WebDriver
28
24
  module Edge
29
- def self.driver_path=(path)
30
- WebDriver.logger.deprecate 'Selenium::WebDriver::Edge#driver_path=',
31
- 'Selenium::WebDriver::Edge::Service#driver_path='
32
- Selenium::WebDriver::Edge::Service.driver_path = path
25
+ autoload :Features, 'selenium/webdriver/edge/features'
26
+ autoload :Driver, 'selenium/webdriver/edge/driver'
27
+ autoload :Profile, 'selenium/webdriver/edge/profile'
28
+ autoload :Options, 'selenium/webdriver/edge/options'
29
+ autoload :Service, 'selenium/webdriver/edge/service'
30
+
31
+ def self.path=(path)
32
+ Platform.assert_executable path
33
+ @path = path
33
34
  end
34
35
 
35
- def self.driver_path
36
- WebDriver.logger.deprecate 'Selenium::WebDriver::Edge#driver_path',
37
- 'Selenium::WebDriver::Edge::Service#driver_path'
38
- Selenium::WebDriver::Edge::Service.driver_path
36
+ def self.path
37
+ @path ||= nil
39
38
  end
40
39
  end # Edge
41
40
  end # WebDriver
42
41
  end # Selenium
43
-
44
- require 'selenium/webdriver/edge/service'