selenium-webdriver 2.45.0 → 3.142.7

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 (172) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +795 -3
  3. data/Gemfile +2 -0
  4. data/{COPYING → LICENSE} +1 -3
  5. data/README.md +13 -9
  6. data/lib/selenium/server.rb +93 -71
  7. data/lib/selenium/webdriver/atoms/getAttribute.js +7 -0
  8. data/lib/selenium/webdriver/atoms/isDisplayed.js +102 -0
  9. data/lib/selenium/webdriver/atoms.rb +37 -0
  10. data/lib/selenium/webdriver/chrome/bridge.rb +47 -99
  11. data/lib/selenium/webdriver/chrome/driver.rb +127 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +190 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +40 -20
  14. data/lib/selenium/webdriver/chrome/service.rb +46 -62
  15. data/lib/selenium/webdriver/chrome.rb +34 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +69 -56
  17. data/lib/selenium/webdriver/common/alert.rb +25 -8
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +35 -20
  19. data/lib/selenium/webdriver/common/driver.rb +90 -63
  20. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +42 -0
  23. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +26 -11
  24. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +58 -0
  26. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +23 -6
  28. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +19 -2
  29. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +24 -7
  30. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +19 -3
  31. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +23 -7
  32. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +26 -5
  33. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +20 -6
  34. data/lib/selenium/webdriver/common/element.rb +79 -37
  35. data/lib/selenium/webdriver/common/error.rb +282 -106
  36. data/lib/selenium/webdriver/common/file_reaper.rb +23 -12
  37. data/lib/selenium/webdriver/common/html5/local_storage.rb +29 -12
  38. data/lib/selenium/webdriver/common/html5/session_storage.rb +29 -12
  39. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +29 -18
  40. data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
  41. data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
  42. data/lib/selenium/webdriver/common/interactions/interactions.rb +43 -0
  43. data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
  44. data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
  45. data/lib/selenium/webdriver/common/interactions/none_input.rb +36 -0
  46. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
  47. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
  48. data/lib/selenium/webdriver/common/keyboard.rb +27 -12
  49. data/lib/selenium/webdriver/common/keys.rb +118 -81
  50. data/lib/selenium/webdriver/common/log_entry.rb +27 -8
  51. data/lib/selenium/webdriver/common/logger.rb +115 -0
  52. data/lib/selenium/webdriver/common/logs.rb +24 -7
  53. data/lib/selenium/webdriver/common/manager.rb +177 -0
  54. data/lib/selenium/webdriver/common/mouse.rb +29 -12
  55. data/lib/selenium/webdriver/common/navigation.rb +21 -4
  56. data/lib/selenium/webdriver/common/options.rb +43 -126
  57. data/lib/selenium/webdriver/common/platform.rb +101 -97
  58. data/lib/selenium/webdriver/common/port_prober.rb +24 -17
  59. data/lib/selenium/webdriver/common/profile_helper.rb +27 -11
  60. data/lib/selenium/webdriver/common/proxy.rb +86 -73
  61. data/lib/selenium/webdriver/common/search_context.rb +49 -33
  62. data/lib/selenium/webdriver/common/service.rb +219 -0
  63. data/lib/selenium/webdriver/common/socket_lock.rb +82 -0
  64. data/lib/selenium/webdriver/common/socket_poller.rb +47 -26
  65. data/lib/selenium/webdriver/common/target_locator.rb +35 -14
  66. data/lib/selenium/webdriver/common/timeouts.rb +23 -6
  67. data/lib/selenium/webdriver/common/touch_action_builder.rb +25 -11
  68. data/lib/selenium/webdriver/common/touch_screen.rb +42 -24
  69. data/lib/selenium/webdriver/common/w3c_action_builder.rb +212 -0
  70. data/lib/selenium/webdriver/common/w3c_manager.rb +45 -0
  71. data/lib/selenium/webdriver/common/wait.rb +34 -14
  72. data/lib/selenium/webdriver/common/window.rb +75 -16
  73. data/lib/selenium/webdriver/common/zipper.rb +26 -11
  74. data/lib/selenium/webdriver/common.rb +40 -7
  75. data/lib/selenium/webdriver/edge/bridge.rb +76 -0
  76. data/lib/selenium/webdriver/edge/driver.rb +66 -0
  77. data/lib/selenium/webdriver/edge/options.rb +80 -0
  78. data/lib/selenium/webdriver/edge/service.rb +52 -0
  79. data/lib/selenium/webdriver/edge.rb +44 -0
  80. data/lib/selenium/webdriver/firefox/binary.rb +70 -48
  81. data/lib/selenium/webdriver/firefox/driver.rb +50 -0
  82. data/lib/selenium/webdriver/firefox/extension/prefs.json +14 -13
  83. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  84. data/lib/selenium/webdriver/firefox/extension.rb +50 -19
  85. data/lib/selenium/webdriver/firefox/launcher.rb +33 -28
  86. data/lib/selenium/webdriver/firefox/legacy/driver.rb +83 -0
  87. data/lib/selenium/webdriver/firefox/marionette/bridge.rb +49 -0
  88. data/lib/selenium/webdriver/firefox/marionette/driver.rb +90 -0
  89. data/lib/selenium/webdriver/firefox/options.rb +162 -0
  90. data/lib/selenium/webdriver/firefox/profile.rb +66 -48
  91. data/lib/selenium/webdriver/firefox/profiles_ini.rb +28 -16
  92. data/lib/selenium/webdriver/firefox/service.rb +52 -0
  93. data/lib/selenium/webdriver/firefox/util.rb +19 -2
  94. data/lib/selenium/webdriver/firefox.rb +46 -10
  95. data/lib/selenium/webdriver/ie/driver.rb +85 -0
  96. data/lib/selenium/webdriver/ie/options.rb +138 -0
  97. data/lib/selenium/webdriver/ie/service.rb +54 -0
  98. data/lib/selenium/webdriver/ie.rb +32 -10
  99. data/lib/selenium/webdriver/remote/bridge.rb +117 -572
  100. data/lib/selenium/webdriver/remote/capabilities.rb +116 -99
  101. data/lib/selenium/webdriver/remote/driver.rb +51 -0
  102. data/lib/selenium/webdriver/remote/http/common.rb +54 -23
  103. data/lib/selenium/webdriver/remote/http/curb.rb +30 -12
  104. data/lib/selenium/webdriver/remote/http/default.rb +85 -42
  105. data/lib/selenium/webdriver/remote/http/persistent.rb +29 -7
  106. data/lib/selenium/webdriver/remote/oss/bridge.rb +594 -0
  107. data/lib/selenium/webdriver/remote/oss/commands.rb +223 -0
  108. data/lib/selenium/webdriver/remote/response.rb +68 -30
  109. data/lib/selenium/webdriver/remote/server_error.rb +22 -5
  110. data/lib/selenium/webdriver/remote/w3c/bridge.rb +605 -0
  111. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +310 -0
  112. data/lib/selenium/webdriver/remote/w3c/commands.rb +157 -0
  113. data/lib/selenium/webdriver/remote.rb +27 -13
  114. data/lib/selenium/webdriver/safari/bridge.rb +38 -107
  115. data/lib/selenium/webdriver/safari/driver.rb +68 -0
  116. data/lib/selenium/webdriver/safari/options.rb +56 -75
  117. data/lib/selenium/webdriver/safari/service.rb +38 -0
  118. data/lib/selenium/webdriver/safari.rb +49 -31
  119. data/lib/selenium/webdriver/support/abstract_event_listener.rb +40 -6
  120. data/lib/selenium/webdriver/support/block_event_listener.rb +24 -7
  121. data/lib/selenium/webdriver/support/color.rb +82 -46
  122. data/lib/selenium/webdriver/support/escaper.rb +43 -0
  123. data/lib/selenium/webdriver/support/event_firing_bridge.rb +56 -39
  124. data/lib/selenium/webdriver/support/select.rb +66 -89
  125. data/lib/selenium/webdriver/support.rb +20 -0
  126. data/lib/selenium/webdriver/version.rb +24 -0
  127. data/lib/selenium/webdriver.rb +55 -25
  128. data/lib/selenium-webdriver.rb +19 -0
  129. data/selenium-webdriver.gemspec +42 -29
  130. metadata +331 -260
  131. data/Gemfile.lock +0 -48
  132. data/lib/selenium/client/base.rb +0 -132
  133. data/lib/selenium/client/driver.rb +0 -10
  134. data/lib/selenium/client/errors.rb +0 -9
  135. data/lib/selenium/client/extensions.rb +0 -118
  136. data/lib/selenium/client/idiomatic.rb +0 -488
  137. data/lib/selenium/client/javascript_expression_builder.rb +0 -116
  138. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -13
  139. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -13
  140. data/lib/selenium/client/legacy_driver.rb +0 -1720
  141. data/lib/selenium/client/protocol.rb +0 -104
  142. data/lib/selenium/client/selenium_helper.rb +0 -34
  143. data/lib/selenium/client.rb +0 -38
  144. data/lib/selenium/rake/server_task.rb +0 -157
  145. data/lib/selenium/webdriver/android/bridge.rb +0 -49
  146. data/lib/selenium/webdriver/android.rb +0 -9
  147. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -9
  148. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -42
  149. data/lib/selenium/webdriver/common/core_ext/string.rb +0 -5
  150. data/lib/selenium/webdriver/common/driver_extensions/has_browser_connection.rb +0 -17
  151. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +0 -39
  152. data/lib/selenium/webdriver/common/html5/location.rb +0 -0
  153. data/lib/selenium/webdriver/common/json_helper.rb +0 -34
  154. data/lib/selenium/webdriver/firefox/bridge.rb +0 -70
  155. data/lib/selenium/webdriver/firefox/socket_lock.rb +0 -61
  156. data/lib/selenium/webdriver/ie/bridge.rb +0 -69
  157. data/lib/selenium/webdriver/ie/server.rb +0 -90
  158. data/lib/selenium/webdriver/iphone/bridge.rb +0 -45
  159. data/lib/selenium/webdriver/iphone.rb +0 -9
  160. data/lib/selenium/webdriver/opera/bridge.rb +0 -112
  161. data/lib/selenium/webdriver/opera/service.rb +0 -49
  162. data/lib/selenium/webdriver/opera.rb +0 -24
  163. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -59
  164. data/lib/selenium/webdriver/phantomjs/service.rb +0 -90
  165. data/lib/selenium/webdriver/phantomjs.rb +0 -22
  166. data/lib/selenium/webdriver/remote/commands.rb +0 -192
  167. data/lib/selenium/webdriver/safari/browser.rb +0 -20
  168. data/lib/selenium/webdriver/safari/extensions.rb +0 -170
  169. data/lib/selenium/webdriver/safari/resources/SafariDriver.safariextz +0 -0
  170. data/lib/selenium/webdriver/safari/resources/client.js +0 -6903
  171. data/lib/selenium/webdriver/safari/server.rb +0 -145
  172. data/lib/selenium-client.rb +0 -2
@@ -1,6 +1,24 @@
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
+
1
20
  module Selenium
2
21
  module WebDriver
3
-
4
22
  #
5
23
  # @api private
6
24
  #
@@ -9,27 +27,26 @@ module Selenium
9
27
  #
10
28
 
11
29
  module ProfileHelper
12
-
13
30
  def self.included(base)
14
31
  base.extend ClassMethods
15
32
  end
16
33
 
17
- def as_json(opts = nil)
18
- {'zip' => Zipper.zip(layout_on_disk)}
34
+ def as_json(*)
35
+ {"zip" => Zipper.zip(layout_on_disk)}
19
36
  end
20
37
 
21
- def to_json(*args)
22
- WebDriver.json_dump as_json
38
+ def to_json(*)
39
+ JSON.generate as_json
23
40
  end
24
41
 
25
42
  private
26
43
 
27
44
  def create_tmp_copy(directory)
28
- tmp_directory = Dir.mktmpdir("webdriver-rb-profilecopy")
45
+ tmp_directory = Dir.mktmpdir('webdriver-rb-profilecopy')
29
46
 
30
47
  # TODO: must be a better way..
31
48
  FileUtils.rm_rf tmp_directory
32
- FileUtils.mkdir_p File.dirname(tmp_directory), :mode => 0700
49
+ FileUtils.mkdir_p File.dirname(tmp_directory), mode: 0o700
33
50
  FileUtils.cp_r directory, tmp_directory
34
51
 
35
52
  tmp_directory
@@ -46,14 +63,14 @@ module Selenium
46
63
 
47
64
  module ClassMethods
48
65
  def from_json(json)
49
- data = WebDriver.json_load(json).fetch('zip')
66
+ data = JSON.parse(json).fetch('zip')
50
67
 
51
68
  # can't use Tempfile here since it doesn't support File::BINARY mode on 1.8
52
69
  # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
53
70
  tmp_dir = Dir.mktmpdir
54
71
  begin
55
72
  zip_path = File.join(tmp_dir, "webdriver-profile-duplicate-#{json.hash}.zip")
56
- File.open(zip_path, "wb") { |zip_file| zip_file << Base64.decode64(data) }
73
+ File.open(zip_path, 'wb') { |zip_file| zip_file << Base64.decode64(data) }
57
74
 
58
75
  new Zipper.unzip(zip_path)
59
76
  ensure
@@ -61,7 +78,6 @@ module Selenium
61
78
  end
62
79
  end
63
80
  end # ClassMethods
64
-
65
81
  end # ProfileHelper
66
82
  end # WebDriver
67
83
  end # Selenium
@@ -1,46 +1,78 @@
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
+
1
20
  module Selenium
2
21
  module WebDriver
3
22
  class Proxy
4
23
  TYPES = {
5
- :direct => "DIRECT", # Direct connection, no proxy (default on Windows).
6
- :manual => "MANUAL", # Manual proxy settings (e.g., for httpProxy).
7
- :pac => "PAC", # Proxy autoconfiguration from URL.
8
- :auto_detect => "AUTODETECT", # Proxy autodetection (presumably with WPAD).
9
- :system => "SYSTEM" # Use system settings (default on Linux).
10
- }
11
-
12
- attr_reader :type,
13
- :ftp,
14
- :http,
15
- :socks,
16
- :socks_username,
17
- :socks_password,
18
- :no_proxy,
19
- :pac,
20
- :ssl,
21
- :auto_detect
24
+ direct: 'DIRECT', # Direct connection, no proxy (default on Windows).
25
+ manual: 'MANUAL', # Manual proxy settings (e.g., for httpProxy).
26
+ pac: 'PAC', # Proxy autoconfiguration from URL.
27
+ auto_detect: 'AUTODETECT', # Proxy autodetection (presumably with WPAD).
28
+ system: 'SYSTEM' # Use system settings (default on Linux).
29
+ }.freeze
30
+
31
+ ALLOWED = {type: 'proxyType',
32
+ ftp: 'ftpProxy',
33
+ http: 'httpProxy',
34
+ no_proxy: 'noProxy',
35
+ pac: 'proxyAutoconfigUrl',
36
+ ssl: 'sslProxy',
37
+ auto_detect: 'autodetect',
38
+ socks: 'socksProxy',
39
+ socks_username: 'socksUsername',
40
+ socks_password: 'socksPassword',
41
+ socks_version: 'socksVersion'}.freeze
42
+
43
+ ALLOWED.each_key { |t| attr_reader t }
44
+
45
+ def self.json_create(data)
46
+ data['proxyType'] = data['proxyType'].downcase.to_sym
47
+ return if data['proxyType'] == :unspecified
48
+
49
+ proxy = new
50
+
51
+ ALLOWED.each do |k, v|
52
+ proxy.send("#{k}=", data[v]) if data.key?(v)
53
+ end
54
+
55
+ proxy
56
+ end
22
57
 
23
58
  def initialize(opts = {})
24
- opts = opts.dup
25
-
26
- self.type = opts.delete(:type) if opts.has_key? :type
27
- self.ftp = opts.delete(:ftp) if opts.has_key? :ftp
28
- self.http = opts.delete(:http) if opts.has_key? :http
29
- self.no_proxy = opts.delete(:no_proxy) if opts.has_key? :no_proxy
30
- self.ssl = opts.delete(:ssl) if opts.has_key? :ssl
31
- self.pac = opts.delete(:pac) if opts.has_key? :pac
32
- self.auto_detect = opts.delete(:auto_detect) if opts.has_key? :auto_detect
33
- self.socks = opts.delete(:socks) if opts.has_key? :socks
34
- self.socks_username = opts.delete(:socks_username) if opts.has_key? :socks_username
35
- self.socks_password = opts.delete(:socks_password) if opts.has_key? :socks_password
36
-
37
- unless opts.empty?
38
- raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
59
+ not_allowed = []
60
+
61
+ opts.each do |k, v|
62
+ if ALLOWED.key?(k)
63
+ send("#{k}=", v)
64
+ else
65
+ not_allowed << k
66
+ end
39
67
  end
68
+
69
+ return if not_allowed.empty?
70
+
71
+ raise ArgumentError, "unknown option#{'s' if not_allowed.size != 1}: #{not_allowed.inspect}"
40
72
  end
41
73
 
42
74
  def ==(other)
43
- other.kind_of?(self.class) && as_json == other.as_json
75
+ other.is_a?(self.class) && as_json == other.as_json
44
76
  end
45
77
  alias_method :eql?, :==
46
78
 
@@ -89,10 +121,13 @@ module Selenium
89
121
  @socks_password = value
90
122
  end
91
123
 
124
+ def socks_version=(value)
125
+ self.type = :manual
126
+ @socks_version = value
127
+ end
128
+
92
129
  def type=(type)
93
- unless TYPES.has_key? type
94
- raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
95
- end
130
+ raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}" unless TYPES.key? type
96
131
 
97
132
  if defined?(@type) && type != @type
98
133
  raise ArgumentError, "incompatible proxy type #{type.inspect} (already set to #{@type.inspect})"
@@ -101,49 +136,27 @@ module Selenium
101
136
  @type = type
102
137
  end
103
138
 
104
- def as_json(opts = nil)
139
+ def as_json(*)
105
140
  json_result = {
106
- "proxyType" => TYPES[type]
107
- }
108
-
109
- json_result["ftpProxy"] = ftp if ftp
110
- json_result["httpProxy"] = http if http
111
- json_result["noProxy"] = no_proxy if no_proxy
112
- json_result["proxyAutoconfigUrl"] = pac if pac
113
- json_result["sslProxy"] = ssl if ssl
114
- json_result["autodetect"] = auto_detect if auto_detect
115
- json_result["socksProxy"] = socks if socks
116
- json_result["socksUsername"] = socks_username if socks_username
117
- json_result["socksPassword"] = socks_password if socks_password
141
+ 'proxyType' => TYPES[type],
142
+ 'ftpProxy' => ftp,
143
+ 'httpProxy' => http,
144
+ 'noProxy' => no_proxy,
145
+ 'proxyAutoconfigUrl' => pac,
146
+ 'sslProxy' => ssl,
147
+ 'autodetect' => auto_detect,
148
+ 'socksProxy' => socks,
149
+ 'socksUsername' => socks_username,
150
+ 'socksPassword' => socks_password,
151
+ 'socksVersion' => socks_version
152
+ }.delete_if { |_k, v| v.nil? }
118
153
 
119
154
  json_result if json_result.length > 1
120
155
  end
121
156
 
122
- def to_json(*args)
123
- WebDriver.json_dump as_json
157
+ def to_json(*)
158
+ JSON.generate as_json
124
159
  end
125
-
126
- class << self
127
- def json_create(data)
128
- return if data['proxyType'] == 'UNSPECIFIED'
129
-
130
- proxy = new
131
-
132
- proxy.type = data['proxyType'].downcase.to_sym if data.has_key? 'proxyType'
133
- proxy.ftp = data['ftpProxy'] if data.has_key? 'ftpProxy'
134
- proxy.http = data['httpProxy'] if data.has_key? 'httpProxy'
135
- proxy.no_proxy = data['noProxy'] if data.has_key? 'noProxy'
136
- proxy.pac = data['proxyAutoconfigUrl'] if data.has_key? 'proxyAutoconfigUrl'
137
- proxy.ssl = data['sslProxy'] if data.has_key? 'sslProxy'
138
- proxy.auto_detect = data['autodetect'] if data.has_key? 'autodetect'
139
- proxy.socks = data['socksProxy'] if data.has_key? 'socksProxy'
140
- proxy.socks_username = data['socksUsername'] if data.has_key? 'socksUsername'
141
- proxy.socks_password = data['socksPassword'] if data.has_key? 'socksPassword'
142
-
143
- proxy
144
- end
145
- end # class << self
146
-
147
160
  end # Proxy
148
161
  end # WebDriver
149
162
  end # Selenium
@@ -1,45 +1,68 @@
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
+
1
20
  module Selenium
2
21
  module WebDriver
3
22
  module SearchContext
4
-
5
23
  # @api private
6
24
  FINDERS = {
7
- :class => 'class name',
8
- :class_name => 'class name',
9
- :css => 'css selector',
10
- :id => 'id',
11
- :link => 'link text',
12
- :link_text => 'link text',
13
- :name => 'name',
14
- :partial_link_text => 'partial link text',
15
- :tag_name => 'tag name',
16
- :xpath => 'xpath',
17
- }
25
+ class: 'class name',
26
+ class_name: 'class name',
27
+ css: 'css selector',
28
+ id: 'id',
29
+ link: 'link text',
30
+ link_text: 'link text',
31
+ name: 'name',
32
+ partial_link_text: 'partial link text',
33
+ tag_name: 'tag name',
34
+ xpath: 'xpath'
35
+ }.freeze
18
36
 
19
37
  #
20
- # Find the first element matching the given arguments.
38
+ # Find the first element matching the given arguments
21
39
  #
22
40
  # When using Element#find_element with :xpath, be aware that webdriver
23
41
  # follows standard conventions: a search prefixed with "//" will search
24
42
  # the entire document, not just the children of this current node. Use
25
43
  # ".//" to limit your search to the children of the receiving Element.
26
44
  #
27
- # @param [:class, :class_name, :css, :id, :link_text, :link, :partial_link_text, :name, :tag_name, :xpath] how
28
- # @param [String] what
45
+ # @overload find_element(how, what)
46
+ # @param [Symbol, String] how The method to find the element by
47
+ # @param [String] what The locator to use
48
+ # @overload find_element(opts)
49
+ # @param [Hash] opts Find options
50
+ # @option opts [Symbol] :how Key named after the method to find the element by, containing the locator
29
51
  # @return [Element]
30
52
  #
31
53
  # @raise [Error::NoSuchElementError] if the element doesn't exist
32
54
  #
33
- #
34
55
 
35
56
  def find_element(*args)
36
57
  how, what = extract_args(args)
37
58
 
38
- unless by = FINDERS[how.to_sym]
39
- raise ArgumentError, "cannot find element by #{how.inspect}"
40
- end
59
+ by = FINDERS[how.to_sym]
60
+ raise ArgumentError, "cannot find element by #{how.inspect}" unless by
41
61
 
42
62
  bridge.find_element_by by, what.to_s, ref
63
+ rescue Selenium::WebDriver::Error::TimeoutError
64
+ # Implicit Wait times out in Edge
65
+ raise Selenium::WebDriver::Error::NoSuchElementError
43
66
  end
44
67
 
45
68
  #
@@ -47,19 +70,17 @@ module Selenium
47
70
  #
48
71
  # @see SearchContext#find_element
49
72
  #
50
- # @param [:class, :class_name, :css, :id, :link_text, :link, :partial_link_text, :name, :tag_name, :xpath] how
51
- # @param [String] what
52
- # @return [Array<Element>]
53
- #
54
73
 
55
74
  def find_elements(*args)
56
75
  how, what = extract_args(args)
57
76
 
58
- unless by = FINDERS[how.to_sym]
59
- raise ArgumentError, "cannot find elements by #{how.inspect}"
60
- end
77
+ by = FINDERS[how.to_sym]
78
+ raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
61
79
 
62
80
  bridge.find_elements_by by, what.to_s, ref
81
+ rescue Selenium::WebDriver::Error::TimeoutError
82
+ # Implicit Wait times out in Edge
83
+ []
63
84
  end
64
85
 
65
86
  private
@@ -71,22 +92,17 @@ module Selenium
71
92
  when 1
72
93
  arg = args.first
73
94
 
74
- unless arg.respond_to?(:shift)
75
- raise ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift"
76
- end
95
+ raise ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift" unless arg.respond_to?(:shift)
77
96
 
78
97
  # this will be a single-entry hash, so use #shift over #first or #[]
79
98
  arr = arg.dup.shift
80
- unless arr.size == 2
81
- raise ArgumentError, "expected #{arr.inspect} to have 2 elements"
82
- end
99
+ raise ArgumentError, "expected #{arr.inspect} to have 2 elements" unless arr.size == 2
83
100
 
84
101
  arr
85
102
  else
86
103
  raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
87
104
  end
88
105
  end
89
-
90
106
  end # SearchContext
91
107
  end # WebDriver
92
108
  end # Selenium
@@ -0,0 +1,219 @@
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
+ #
23
+ # Base class implementing default behavior of service object,
24
+ # responsible for starting and stopping driver implementations.
25
+ #
26
+
27
+ class Service
28
+ START_TIMEOUT = 20
29
+ SOCKET_LOCK_TIMEOUT = 45
30
+ STOP_TIMEOUT = 20
31
+
32
+ @default_port = nil
33
+ @driver_path = nil
34
+ @executable = nil
35
+ @missing_text = nil
36
+
37
+ class << self
38
+ attr_reader :default_port, :driver_path, :executable, :missing_text, :shutdown_supported
39
+
40
+ def chrome(**opts)
41
+ Chrome::Service.new(**opts)
42
+ end
43
+
44
+ def firefox(**opts)
45
+ binary_path = Firefox::Binary.path
46
+ args = opts.delete(:args)
47
+ case args
48
+ when Hash
49
+ args[:binary] ||= binary_path
50
+ opts[:args] = args
51
+ when Array
52
+ opts[:args] = ["--binary=#{binary_path}"]
53
+ opts[:args] += args
54
+ else
55
+ opts[:args] = ["--binary=#{binary_path}"]
56
+ end
57
+
58
+ Firefox::Service.new(**opts)
59
+ end
60
+
61
+ def ie(**opts)
62
+ IE::Service.new(**opts)
63
+ end
64
+ alias_method :internet_explorer, :ie
65
+
66
+ def edge(**opts)
67
+ Edge::Service.new(**opts)
68
+ end
69
+
70
+ def safari(**opts)
71
+ Safari::Service.new(**opts)
72
+ end
73
+
74
+ def driver_path=(path)
75
+ Platform.assert_executable path if path.is_a?(String)
76
+ @driver_path = path
77
+ end
78
+ end
79
+
80
+ attr_accessor :host
81
+ attr_reader :executable_path
82
+
83
+ #
84
+ # End users should use a class method for the desired driver, rather than using this directly.
85
+ #
86
+ # @api private
87
+ #
88
+
89
+ def initialize(path: nil, port: nil, args: nil)
90
+ path ||= self.class.driver_path
91
+ port ||= self.class.default_port
92
+ args ||= []
93
+
94
+ @executable_path = binary_path(path)
95
+ @host = Platform.localhost
96
+ @port = Integer(port)
97
+
98
+ @extra_args = args.is_a?(Hash) ? extract_service_args(args) : args
99
+
100
+ raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
101
+ end
102
+
103
+ def start
104
+ raise "already started: #{uri.inspect} #{@executable_path.inspect}" if process_running?
105
+
106
+ Platform.exit_hook(&method(:stop)) # make sure we don't leave the server running
107
+
108
+ socket_lock.locked do
109
+ find_free_port
110
+ start_process
111
+ connect_until_stable
112
+ end
113
+ end
114
+
115
+ def stop
116
+ return unless self.class.shutdown_supported
117
+
118
+ stop_server
119
+ @process.poll_for_exit STOP_TIMEOUT
120
+ rescue ChildProcess::TimeoutError
121
+ nil # noop
122
+ ensure
123
+ stop_process
124
+ end
125
+
126
+ def uri
127
+ @uri ||= URI.parse("http://#{@host}:#{@port}")
128
+ end
129
+
130
+ private
131
+
132
+ def binary_path(path = nil)
133
+ path = path.call if path.is_a?(Proc)
134
+ path ||= Platform.find_binary(self.class.executable)
135
+
136
+ raise Error::WebDriverError, self.class.missing_text unless path
137
+
138
+ Platform.assert_executable path
139
+ path
140
+ end
141
+
142
+ def build_process(*command)
143
+ WebDriver.logger.debug("Executing Process #{command}")
144
+ @process = ChildProcess.build(*command)
145
+ if WebDriver.logger.debug?
146
+ @process.io.stdout = @process.io.stderr = WebDriver.logger.io
147
+ elsif Platform.jruby?
148
+ # Apparently we need to read the output of drivers on JRuby.
149
+ @process.io.stdout = @process.io.stderr = File.new(Platform.null_device, 'w')
150
+ end
151
+
152
+ @process
153
+ end
154
+
155
+ def connect_to_server
156
+ Net::HTTP.start(@host, @port) do |http|
157
+ http.open_timeout = STOP_TIMEOUT / 2
158
+ http.read_timeout = STOP_TIMEOUT / 2
159
+
160
+ yield http
161
+ end
162
+ end
163
+
164
+ def find_free_port
165
+ @port = PortProber.above(@port)
166
+ end
167
+
168
+ def start_process
169
+ @process = build_process(@executable_path, "--port=#{@port}", *@extra_args)
170
+ # Note: this is a bug only in Windows 7
171
+ @process.leader = true unless Platform.windows?
172
+ @process.start
173
+ end
174
+
175
+ def stop_process
176
+ return if process_exited?
177
+
178
+ @process.stop STOP_TIMEOUT
179
+ @process.io.stdout.close if Platform.jruby? && !WebDriver.logger.debug?
180
+ end
181
+
182
+ def stop_server
183
+ return if process_exited?
184
+
185
+ connect_to_server { |http| http.get('/shutdown') }
186
+ end
187
+
188
+ def process_running?
189
+ defined?(@process) && @process&.alive?
190
+ end
191
+
192
+ def process_exited?
193
+ @process.nil? || @process.exited?
194
+ end
195
+
196
+ def connect_until_stable
197
+ socket_poller = SocketPoller.new @host, @port, START_TIMEOUT
198
+ return if socket_poller.connected?
199
+
200
+ raise Error::WebDriverError, cannot_connect_error_text
201
+ end
202
+
203
+ def cannot_connect_error_text
204
+ "unable to connect to #{self.class.executable} #{@host}:#{@port}"
205
+ end
206
+
207
+ def socket_lock
208
+ @socket_lock ||= SocketLock.new(@port - 1, SOCKET_LOCK_TIMEOUT)
209
+ end
210
+
211
+ protected
212
+
213
+ def extract_service_args(driver_opts)
214
+ driver_opts.key?(:args) ? driver_opts.delete(:args) : []
215
+ end
216
+
217
+ end # Service
218
+ end # WebDriver
219
+ end # Selenium