selenium-webdriver 4.1.0 → 4.28.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.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +446 -1
  3. data/Gemfile +4 -0
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/README.md +3 -3
  7. data/bin/linux/selenium-manager +0 -0
  8. data/bin/macos/selenium-manager +0 -0
  9. data/bin/windows/selenium-manager.exe +0 -0
  10. data/lib/selenium/server.rb +41 -43
  11. data/lib/selenium/webdriver/atoms/findElements.js +52 -50
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +6 -100
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +24 -96
  14. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  15. data/lib/selenium/webdriver/atoms.rb +5 -3
  16. data/lib/selenium/webdriver/bidi/browsing_context.rb +100 -0
  17. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  19. data/lib/selenium/webdriver/{common/driver_extensions/has_location.rb → bidi/log/filter_by.rb} +14 -11
  20. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  21. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  22. data/lib/selenium/webdriver/bidi/log_handler.rb +65 -0
  23. data/lib/selenium/webdriver/bidi/log_inspector.rb +147 -0
  24. data/lib/selenium/webdriver/bidi/network.rb +82 -0
  25. data/lib/selenium/webdriver/bidi/session.rb +51 -0
  26. data/lib/selenium/webdriver/bidi/struct.rb +42 -0
  27. data/lib/selenium/webdriver/bidi.rb +67 -0
  28. data/lib/selenium/webdriver/chrome/driver.rb +9 -29
  29. data/lib/selenium/webdriver/chrome/features.rb +9 -67
  30. data/lib/selenium/webdriver/chrome/options.rb +3 -223
  31. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  32. data/lib/selenium/webdriver/chrome/service.rb +5 -19
  33. data/lib/selenium/webdriver/chrome.rb +0 -16
  34. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  35. data/lib/selenium/webdriver/chromium/features.rb +99 -0
  36. data/lib/selenium/webdriver/chromium/options.rb +243 -0
  37. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  38. data/lib/selenium/webdriver/chromium.rb +29 -0
  39. data/lib/selenium/webdriver/common/action_builder.rb +60 -22
  40. data/lib/selenium/webdriver/common/child_process.rb +136 -0
  41. data/lib/selenium/webdriver/common/driver.rb +54 -89
  42. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  43. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  44. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  47. data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +10 -5
  48. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
  49. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
  51. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb +55 -0
  54. data/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb +65 -0
  55. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  56. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +9 -3
  57. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  58. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +8 -68
  59. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  60. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
  61. data/lib/selenium/webdriver/common/driver_finder.rb +97 -0
  62. data/lib/selenium/webdriver/common/element.rb +8 -8
  63. data/lib/selenium/webdriver/common/error.rb +29 -4
  64. data/lib/selenium/webdriver/common/fedcm/account.rb +49 -0
  65. data/lib/selenium/webdriver/common/fedcm/dialog.rb +74 -0
  66. data/lib/selenium/webdriver/common/fedcm.rb +27 -0
  67. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  68. data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
  69. data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
  70. data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
  71. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
  72. data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
  73. data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
  74. data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
  75. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -71
  76. data/lib/selenium/webdriver/common/{driver_extensions/has_network_connection.rb → interactions/pointer_cancel.rb} +19 -11
  77. data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
  78. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
  79. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
  80. data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
  81. data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
  82. data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
  83. data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
  84. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +114 -0
  85. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
  86. data/lib/selenium/webdriver/common/keys.rb +1 -0
  87. data/lib/selenium/webdriver/common/local_driver.rb +53 -0
  88. data/lib/selenium/webdriver/common/logger.rb +93 -28
  89. data/lib/selenium/webdriver/common/manager.rb +2 -29
  90. data/lib/selenium/webdriver/common/network.rb +64 -0
  91. data/lib/selenium/webdriver/common/options.rb +19 -19
  92. data/lib/selenium/webdriver/common/platform.rb +12 -52
  93. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  94. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  95. data/lib/selenium/webdriver/common/proxy.rb +4 -4
  96. data/lib/selenium/webdriver/common/script.rb +45 -0
  97. data/lib/selenium/webdriver/common/search_context.rb +10 -8
  98. data/lib/selenium/webdriver/common/selenium_manager.rb +104 -0
  99. data/lib/selenium/webdriver/common/service.rb +24 -26
  100. data/lib/selenium/webdriver/common/service_manager.rb +9 -15
  101. data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
  102. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  103. data/lib/selenium/webdriver/common/socket_poller.rb +3 -3
  104. data/lib/selenium/webdriver/common/takes_screenshot.rb +6 -5
  105. data/lib/selenium/webdriver/common/target_locator.rb +5 -5
  106. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  107. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
  108. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
  109. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  110. data/lib/selenium/webdriver/common/wait.rb +1 -1
  111. data/lib/selenium/webdriver/common/websocket_connection.rb +176 -0
  112. data/lib/selenium/webdriver/common/window.rb +6 -6
  113. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  114. data/lib/selenium/webdriver/common.rb +27 -5
  115. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  116. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  117. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  118. data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
  119. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  120. data/lib/selenium/webdriver/devtools/request.rb +1 -3
  121. data/lib/selenium/webdriver/devtools/response.rb +1 -3
  122. data/lib/selenium/webdriver/devtools.rb +17 -114
  123. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  124. data/lib/selenium/webdriver/edge/features.rb +8 -4
  125. data/lib/selenium/webdriver/edge/options.rb +17 -5
  126. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  127. data/lib/selenium/webdriver/edge/service.rb +8 -7
  128. data/lib/selenium/webdriver/edge.rb +0 -2
  129. data/lib/selenium/webdriver/firefox/driver.rb +9 -2
  130. data/lib/selenium/webdriver/firefox/features.rb +11 -7
  131. data/lib/selenium/webdriver/firefox/options.rb +10 -16
  132. data/lib/selenium/webdriver/firefox/profile.rb +21 -17
  133. data/lib/selenium/webdriver/firefox/profiles_ini.rb +1 -1
  134. data/lib/selenium/webdriver/firefox/service.rb +1 -18
  135. data/lib/selenium/webdriver/firefox/util.rb +46 -0
  136. data/lib/selenium/webdriver/firefox.rb +1 -14
  137. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  138. data/lib/selenium/webdriver/ie/features.rb +34 -0
  139. data/lib/selenium/webdriver/ie/options.rb +6 -4
  140. data/lib/selenium/webdriver/ie/service.rb +1 -22
  141. data/lib/selenium/webdriver/ie.rb +4 -17
  142. data/lib/selenium/webdriver/remote/bidi_bridge.rb +66 -0
  143. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +22 -9
  144. data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
  145. data/lib/selenium/webdriver/remote/bridge.rb +158 -100
  146. data/lib/selenium/webdriver/remote/capabilities.rb +5 -55
  147. data/lib/selenium/webdriver/remote/driver.rb +35 -14
  148. data/lib/selenium/webdriver/remote/features.rb +75 -0
  149. data/lib/selenium/webdriver/remote/http/common.rb +26 -6
  150. data/lib/selenium/webdriver/remote/http/curb.rb +10 -6
  151. data/lib/selenium/webdriver/remote/http/default.rb +8 -14
  152. data/lib/selenium/webdriver/remote/response.rb +14 -22
  153. data/lib/selenium/webdriver/remote/server_error.rb +2 -2
  154. data/lib/selenium/webdriver/remote.rb +3 -2
  155. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  156. data/lib/selenium/webdriver/safari/features.rb +5 -3
  157. data/lib/selenium/webdriver/safari/options.rb +5 -1
  158. data/lib/selenium/webdriver/safari/service.rb +10 -4
  159. data/lib/selenium/webdriver/safari.rb +1 -15
  160. data/lib/selenium/webdriver/support/color.rb +22 -22
  161. data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
  162. data/lib/selenium/webdriver/support/guards/guard.rb +14 -14
  163. data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
  164. data/lib/selenium/webdriver/support/guards.rb +4 -4
  165. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  166. data/lib/selenium/webdriver/support/select.rb +3 -1
  167. data/lib/selenium/webdriver/version.rb +1 -1
  168. data/lib/selenium/webdriver.rb +7 -5
  169. data/selenium-webdriver.gemspec +22 -16
  170. metadata +137 -47
  171. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
  172. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  173. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -0,0 +1,65 @@
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 BiDi
23
+ class LogHandler
24
+ ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source, :method, :args)
25
+ JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source)
26
+
27
+ def initialize(bidi)
28
+ @bidi = bidi
29
+ @log_entry_subscribed = false
30
+ end
31
+
32
+ # @return [int] id of the handler
33
+ # steep:ignore:start
34
+ def add_message_handler(type)
35
+ subscribe_log_entry unless @log_entry_subscribed
36
+ @bidi.add_callback('log.entryAdded') do |params|
37
+ if params['type'] == type
38
+ log_entry_klass = type == 'console' ? ConsoleLogEntry : JavaScriptLogEntry
39
+ yield(log_entry_klass.new(**params))
40
+ end
41
+ end
42
+ end
43
+ # steep:ignore:end
44
+
45
+ # @param [int] id of the handler previously added
46
+ def remove_message_handler(id)
47
+ @bidi.remove_callback('log.entryAdded', id)
48
+ unsubscribe_log_entry if @log_entry_subscribed && @bidi.callbacks['log.entryAdded'].empty?
49
+ end
50
+
51
+ private
52
+
53
+ def subscribe_log_entry
54
+ @bidi.session.subscribe('log.entryAdded')
55
+ @log_entry_subscribed = true
56
+ end
57
+
58
+ def unsubscribe_log_entry
59
+ @bidi.session.unsubscribe('log.entryAdded')
60
+ @log_entry_subscribed = false
61
+ end
62
+ end # LogHandler
63
+ end # Bidi
64
+ end # WebDriver
65
+ end # Selenium
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ # This file is automatically generated. Any changes will be lost!
21
+
22
+ require_relative 'log/base_log_entry'
23
+ require_relative 'log/generic_log_entry'
24
+ require_relative 'log/console_log_entry'
25
+ require_relative 'log/javascript_log_entry'
26
+ require_relative 'log/filter_by'
27
+
28
+ module Selenium
29
+ module WebDriver
30
+ class BiDi
31
+ class LogInspector
32
+ EVENTS = {
33
+ entry_added: 'entryAdded'
34
+ }.freeze
35
+
36
+ LOG_LEVEL = {
37
+ DEBUG: 'debug',
38
+ ERROR: 'error',
39
+ INFO: 'info',
40
+ WARNING: 'warning'
41
+ }.freeze
42
+
43
+ def initialize(driver, browsing_context_ids = nil)
44
+ WebDriver.logger.deprecate('LogInspector class',
45
+ 'Script class with driver.script',
46
+ id: :log_inspector)
47
+
48
+ unless driver.capabilities.web_socket_url
49
+ raise Error::WebDriverError,
50
+ 'WebDriver instance must support BiDi protocol'
51
+ end
52
+
53
+ @bidi = driver.bidi
54
+ @bidi.session.subscribe('log.entryAdded', browsing_context_ids)
55
+ end
56
+
57
+ def on_console_entry(filter_by = nil, &block)
58
+ check_valid_filter(filter_by)
59
+
60
+ on_log do |params|
61
+ type = params['type']
62
+ console_log_events(params, filter_by, &block) if type.eql?('console')
63
+ end
64
+ end
65
+
66
+ def on_javascript_log(filter_by = nil, &block)
67
+ check_valid_filter(filter_by)
68
+
69
+ on_log do |params|
70
+ type = params['type']
71
+ javascript_log_events(params, filter_by, &block) if type.eql?('javascript')
72
+ end
73
+ end
74
+
75
+ def on_javascript_exception(&block)
76
+ on_log do |params|
77
+ type = params['type']
78
+ javascript_log_events(params, FilterBy.log_level('error'), &block) if type.eql?('javascript')
79
+ end
80
+ end
81
+
82
+ def on_log(filter_by = nil, &)
83
+ unless filter_by.nil?
84
+ check_valid_filter(filter_by)
85
+
86
+ on(:entry_added) do |params|
87
+ yield(params) if params['level'] == filter_by.level
88
+ end
89
+ return
90
+ end
91
+
92
+ on(:entry_added, &)
93
+ end
94
+
95
+ private
96
+
97
+ def on(event, &)
98
+ event = EVENTS[event] if event.is_a?(Symbol)
99
+ @bidi.add_callback("log.#{event}", &)
100
+ end
101
+
102
+ def check_valid_filter(filter_by)
103
+ return if filter_by.nil? || filter_by.instance_of?(FilterBy)
104
+
105
+ raise "Pass valid FilterBy object. Received: #{filter_by.inspect}"
106
+ end
107
+
108
+ def console_log_events(params, filter_by)
109
+ event = ConsoleLogEntry.new(
110
+ level: params['level'],
111
+ text: params['text'],
112
+ timestamp: params['timestamp'],
113
+ type: params['type'],
114
+ method: params['method'],
115
+ realm: params['realm'],
116
+ args: params['args'],
117
+ stack_trace: params['stackTrace']
118
+ )
119
+
120
+ unless filter_by.nil?
121
+ yield(event) if params['level'] == filter_by.level
122
+ return
123
+ end
124
+
125
+ yield(event)
126
+ end
127
+
128
+ def javascript_log_events(params, filter_by)
129
+ event = JavascriptLogEntry.new(
130
+ level: params['level'],
131
+ text: params['text'],
132
+ timestamp: params['timestamp'],
133
+ type: params['type'],
134
+ stack_trace: params['stackTrace']
135
+ )
136
+
137
+ unless filter_by.nil?
138
+ yield(event) if params['level'] == filter_by.level
139
+ return
140
+ end
141
+
142
+ yield(event)
143
+ end
144
+ end # LogInspector
145
+ end # Bidi
146
+ end # WebDriver
147
+ end # Selenium
@@ -0,0 +1,82 @@
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 BiDi
23
+ class Network
24
+ EVENTS = {
25
+ before_request: 'network.beforeRequestSent',
26
+ response_started: 'network.responseStarted',
27
+ response_completed: 'network.responseCompleted',
28
+ auth_required: 'network.authRequired',
29
+ fetch_error: 'network.fetchError'
30
+ }.freeze
31
+
32
+ PHASES = {
33
+ before_request: 'beforeRequestSent',
34
+ response_started: 'responseStarted',
35
+ auth_required: 'authRequired'
36
+ }.freeze
37
+
38
+ def initialize(bidi)
39
+ @bidi = bidi
40
+ end
41
+
42
+ def add_intercept(phases: [], contexts: nil, url_patterns: nil)
43
+ @bidi.send_cmd('network.addIntercept', phases: phases, contexts: contexts, urlPatterns: url_patterns)
44
+ end
45
+
46
+ def remove_intercept(intercept)
47
+ @bidi.send_cmd('network.removeIntercept', intercept: intercept)
48
+ end
49
+
50
+ def continue_with_auth(request_id, username, password)
51
+ @bidi.send_cmd(
52
+ 'network.continueWithAuth',
53
+ 'request' => request_id,
54
+ 'action' => 'provideCredentials',
55
+ 'credentials' => {
56
+ 'type' => 'password',
57
+ 'username' => username,
58
+ 'password' => password
59
+ }
60
+ )
61
+ end
62
+
63
+ def continue_with_request(**args)
64
+ @bidi.send_cmd(
65
+ 'network.continueWithRequest',
66
+ request: args[:request_id],
67
+ 'body' => args[:body],
68
+ 'cookies' => args[:cookies],
69
+ 'headers' => args[:headers],
70
+ 'method' => args[:method],
71
+ 'url' => args[:url]
72
+ )
73
+ end
74
+
75
+ def on(event, &)
76
+ event = EVENTS[event] if event.is_a?(Symbol)
77
+ @bidi.add_callback(event, &)
78
+ end
79
+ end # Network
80
+ end # BiDi
81
+ end # WebDriver
82
+ 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
+ class BiDi
23
+ class Session
24
+ Status = Struct.new(:ready, :message)
25
+
26
+ def initialize(bidi)
27
+ @bidi = bidi
28
+ end
29
+
30
+ def status
31
+ status = @bidi.send_cmd('session.status')
32
+ Status.new(**status)
33
+ end
34
+
35
+ def subscribe(events, browsing_contexts = nil)
36
+ opts = {events: Array(events)}
37
+ opts[:browsing_contexts] = Array(browsing_contexts) if browsing_contexts
38
+
39
+ @bidi.send_cmd('session.subscribe', **opts)
40
+ end
41
+
42
+ def unsubscribe(events, browsing_contexts = nil)
43
+ opts = {events: Array(events)}
44
+ opts[:browsing_contexts] = Array(browsing_contexts) if browsing_contexts
45
+
46
+ @bidi.send_cmd('session.unsubscribe', **opts)
47
+ end
48
+ end # Session
49
+ end # BiDi
50
+ end # WebDriver
51
+ end # Selenium
@@ -0,0 +1,42 @@
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 BiDi
23
+ class Struct < ::Struct
24
+ class << self
25
+ def new(*args, &block)
26
+ super do
27
+ define_method(:initialize) do |**kwargs|
28
+ converted_kwargs = kwargs.transform_keys { |key| self.class.camel_to_snake(key.to_s).to_sym }
29
+ super(*converted_kwargs.values_at(*self.class.members))
30
+ end
31
+ class_eval(&block) if block
32
+ end
33
+ end
34
+
35
+ def camel_to_snake(camel_str)
36
+ camel_str.gsub(/([A-Z])/, '_\1').downcase
37
+ end
38
+ end
39
+ end
40
+ end # BiDi
41
+ end # WebDriver
42
+ 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 BiDi
23
+ autoload :Session, 'selenium/webdriver/bidi/session'
24
+ autoload :LogInspector, 'selenium/webdriver/bidi/log_inspector'
25
+ autoload :LogHandler, 'selenium/webdriver/bidi/log_handler'
26
+ autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'
27
+ autoload :Struct, 'selenium/webdriver/bidi/struct'
28
+ autoload :Network, 'selenium/webdriver/bidi/network'
29
+
30
+ def initialize(url:)
31
+ @ws = WebSocketConnection.new(url: url)
32
+ end
33
+
34
+ def close
35
+ @ws.close
36
+ end
37
+
38
+ def callbacks
39
+ @ws.callbacks
40
+ end
41
+
42
+ def add_callback(event, &)
43
+ @ws.add_callback(event, &)
44
+ end
45
+
46
+ def remove_callback(event, id)
47
+ @ws.remove_callback(event, id)
48
+ end
49
+
50
+ def session
51
+ @session ||= Session.new(self)
52
+ end
53
+
54
+ def send_cmd(method, **params)
55
+ data = {method: method, params: params.compact}
56
+ message = @ws.send_cmd(**data)
57
+ raise Error::WebDriverError, error_message(message) if message['error']
58
+
59
+ message['result']
60
+ end
61
+
62
+ def error_message(message)
63
+ "#{message['error']}: #{message['message']}\n#{message['stacktrace']}"
64
+ end
65
+ end # BiDi
66
+ end # WebDriver
67
+ end # Selenium
@@ -17,31 +17,23 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/driver'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
23
-
24
25
  #
25
26
  # Driver implementation for Chrome.
26
27
  # @api private
27
28
  #
28
29
 
29
- class Driver < WebDriver::Driver
30
- EXTENSIONS = [DriverExtensions::HasCDP,
31
- DriverExtensions::HasCasting,
32
- DriverExtensions::HasNetworkConditions,
33
- DriverExtensions::HasNetworkInterception,
34
- DriverExtensions::HasWebStorage,
35
- DriverExtensions::HasLaunching,
36
- DriverExtensions::HasLocation,
37
- DriverExtensions::HasPermissions,
38
- DriverExtensions::DownloadsFiles,
39
- DriverExtensions::HasDevTools,
40
- DriverExtensions::HasAuthentication,
41
- DriverExtensions::HasLogs,
42
- DriverExtensions::HasLogEvents,
43
- DriverExtensions::HasPinnedScripts,
44
- DriverExtensions::PrintsPage].freeze
30
+ class Driver < Chromium::Driver
31
+ include LocalDriver
32
+
33
+ def initialize(options: nil, service: nil, url: nil, **opts)
34
+ caps, url = initialize_local_driver(options, service, url)
35
+ super(caps: caps, url: url, **opts)
36
+ end
45
37
 
46
38
  def browser
47
39
  :chrome
@@ -49,21 +41,9 @@ module Selenium
49
41
 
50
42
  private
51
43
 
52
- def devtools_url
53
- uri = URI(devtools_address)
54
- response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
55
-
56
- JSON.parse(response)['webSocketDebuggerUrl']
57
- end
58
-
59
- def devtools_version
60
- Integer(capabilities.browser_version.split('.').first)
61
- end
62
-
63
44
  def devtools_address
64
45
  "http://#{capabilities['goog:chromeOptions']['debuggerAddress']}"
65
46
  end
66
-
67
47
  end # Driver
68
48
  end # Chrome
69
49
  end # WebDriver
@@ -17,88 +17,30 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/features'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
23
25
  module Features
26
+ include WebDriver::Chromium::Features
24
27
 
25
28
  CHROME_COMMANDS = {
26
- launch_app: [:post, 'session/:session_id/chromium/launch_app'],
27
29
  get_cast_sinks: [:get, 'session/:session_id/goog/cast/get_sinks'],
28
30
  set_cast_sink_to_use: [:post, 'session/:session_id/goog/cast/set_sink_to_use'],
29
31
  start_cast_tab_mirroring: [:post, 'session/:session_id/goog/cast/start_tab_mirroring'],
32
+ start_cast_desktop_mirroring: [:post, 'session/:session_id/goog/cast/start_desktop_mirroring'],
30
33
  get_cast_issue_message: [:get, 'session/:session_id/goog/cast/get_issue_message'],
31
34
  stop_casting: [:post, 'session/:session_id/goog/cast/stop_casting'],
32
- get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
33
- set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
34
- delete_network_conditions: [:delete, 'session/:session_id/chromium/network_conditions'],
35
- set_permission: [:post, 'session/:session_id/permissions'],
36
- send_command: [:post, 'session/:session_id/goog/cdp/execute'],
37
- get_available_log_types: [:get, 'session/:session_id/se/log/types'],
38
- get_log: [:post, 'session/:session_id/se/log']
35
+ send_command: [:post, 'session/:session_id/goog/cdp/execute']
39
36
  }.freeze
40
37
 
41
- def commands(command)
42
- CHROME_COMMANDS[command] || self.class::COMMANDS[command]
43
- end
44
-
45
- def launch_app(id)
46
- execute :launch_app, {}, {id: id}
47
- end
48
-
49
- def cast_sinks
50
- execute :get_cast_sinks
51
- end
52
-
53
- def cast_sink_to_use=(name)
54
- execute :set_cast_sink_to_use, {}, {sinkName: name}
55
- end
56
-
57
- def cast_issue_message
58
- execute :cast_issue_message
59
- end
60
-
61
- def start_cast_tab_mirroring(name)
62
- execute :start_cast_tab_mirroring, {}, {sinkName: name}
63
- end
64
-
65
- def stop_casting(name)
66
- execute :stop_casting, {}, {sinkName: name}
38
+ def command_list
39
+ CHROME_COMMANDS.merge(CHROMIUM_COMMANDS).merge(self.class::COMMANDS)
67
40
  end
68
41
 
69
- def set_permission(name, value)
70
- execute :set_permission, {}, {descriptor: {name: name}, state: value}
71
- end
72
-
73
- def network_conditions
74
- execute :get_network_conditions
75
- end
76
-
77
- def network_conditions=(conditions)
78
- execute :set_network_conditions, {}, {network_conditions: conditions}
79
- end
80
-
81
- def delete_network_conditions
82
- execute :delete_network_conditions
83
- end
84
-
85
- def send_command(command_params)
86
- execute :send_command, {}, command_params
87
- end
88
-
89
- def available_log_types
90
- types = execute :get_available_log_types
91
- Array(types).map(&:to_sym)
92
- end
93
-
94
- def log(type)
95
- data = execute :get_log, {}, {type: type.to_s}
96
-
97
- Array(data).map do |l|
98
- LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
99
- rescue KeyError
100
- next
101
- end
42
+ def commands(command)
43
+ command_list[command]
102
44
  end
103
45
  end # Bridge
104
46
  end # Chrome