selenium-webdriver 4.0.0.rc2 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4481c4b877188aa5f972209d98ad2f6387ecdeac3e4a61f1e4758f09eb1bab28
4
- data.tar.gz: bc3e42035ed3a22b444fbe1a03d43d08e2e8558a4fd498950d23666606919148
3
+ metadata.gz: 93644f0cd4cba43ac1e48314eba504907059c877e5269ade70629427cc03f8e5
4
+ data.tar.gz: 640c8f580d87606e83ca42209ea4672eb8adae9f81ce77993af9cc3cad469255
5
5
  SHA512:
6
- metadata.gz: 7d43469e0863264b60306fda4c035eb86112f14e119ef371d53aeef45765a540b76a844bbc482d78940b8a7349c5e91b0f5ac8acc3aa9cbaf78b3db12ef62f6d
7
- data.tar.gz: 0b5dc50ae4fc05a89da9a547cba5f0d5fcdcbc4f233095087ef5a75fd98c34745ac7a30e616792bc853993c708f66babe186fbb4cc68415296cdaab0aa264a9b
6
+ metadata.gz: e50651efe20b569e9400d3276969341de5fc6feb042ec344ee600318449f7b6d2012a4cd474dc22da1ec4592cfc8d880efa00dde3e3022b734e919ca6e2d21ec
7
+ data.tar.gz: e0b78655050282f75e72b2abf8094dc3674d1470ea60517114fc64d978c1f7a28255b13b3db13a2471b796969a73bd6e5e560653051a25f3492b844f67ec02be
data/CHANGES CHANGED
@@ -1,3 +1,36 @@
1
+ 4.0.2 (2021-10-19)
2
+ =========================
3
+
4
+ Server:
5
+ * Fixed bug in new download code.
6
+
7
+ 4.0.1 (2021-10-19)
8
+ =========================
9
+
10
+ Server:
11
+ * Fixed download by pointing to new storage location.
12
+ - Only supports Selenium 4 versions
13
+ * Added default value for Server::get and Server::download to use the latest server version
14
+
15
+ 4.0.0 (2021-10-13)
16
+ =========================
17
+
18
+ Ruby:
19
+ * Updated minimum required Ruby version to 2.6
20
+ * Updated minimum required rexml gem version due to vulnerability
21
+
22
+ Chrome:
23
+ * Added default values for Network Conditions so no longer need to specify everything
24
+
25
+ Firefox:
26
+ * Fixed bug where Firefox prefs were converting snake case to camel case
27
+
28
+ 4.0.0.rc3 (2021-10-08)
29
+ =========================
30
+
31
+ Ruby:
32
+ * Added support for getting timeout values from the driver
33
+
1
34
  4.0.0.rc2 (2021-09-30)
2
35
  =========================
3
36
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # selenium-webdriver
2
2
 
3
- This gem provides Ruby bindings for Selenium and supports MRI > 2.5
3
+ This gem provides Ruby bindings for Selenium and supports MRI >= 2.6
4
4
 
5
5
  ## Install
6
6
 
@@ -57,45 +57,39 @@ module Selenium
57
57
 
58
58
  CL_RESET = WebDriver::Platform.windows? ? '' : "\r\e[0K"
59
59
 
60
- def self.get(required_version, opts = {})
61
- new(download(required_version), opts)
62
- end
60
+ class << self
61
+ #
62
+ # Download the given version of the selenium-server jar and return instance
63
+ #
64
+ # @param [String, Symbol] required_version X.Y.Z defaults to ':latest'
65
+ # @param [Hash] opts
66
+ # @return [Selenium::Server]
67
+ #
63
68
 
64
- #
65
- # Download the given version of the selenium-server-standalone jar.
66
- #
69
+ def get(required_version = :latest, opts = {})
70
+ new(download(required_version), opts)
71
+ end
67
72
 
68
- class << self
69
- def download(required_version)
73
+ #
74
+ # Download the given version of the selenium-server jar and return location
75
+ #
76
+ # @param [String, Symbol] required_version X.Y.Z defaults to ':latest'
77
+ # @return [String] location of downloaded file
78
+ #
79
+
80
+ def download(required_version = :latest)
70
81
  required_version = latest if required_version == :latest
71
- download_file_name = "selenium-server-standalone-#{required_version}.jar"
82
+ download_file_name = "selenium-server-#{required_version}.jar"
72
83
 
73
84
  return download_file_name if File.exist? download_file_name
74
85
 
75
86
  begin
76
- File.open(download_file_name, 'wb') do |destination|
77
- net_http_start('selenium-release.storage.googleapis.com') do |http|
78
- resp = http.request_get("/#{required_version[/(\d+\.\d+)\./, 1]}/#{download_file_name}") do |response|
79
- total = response.content_length
80
- progress = 0
81
- segment_count = 0
82
-
83
- response.read_body do |segment|
84
- progress += segment.length
85
- segment_count += 1
87
+ server = 'https://github.com/seleniumhq/selenium/releases/download'
88
+ released = Net::HTTP.get_response(URI.parse("#{server}/selenium-#{required_version}/#{download_file_name}"))
89
+ redirected = URI.parse released.header['location']
86
90
 
87
- if (segment_count % 15).zero?
88
- percent = progress.fdiv(total) * 100
89
- print "#{CL_RESET}Downloading #{download_file_name}: #{percent.to_i}% (#{progress} / #{total})"
90
- segment_count = 0
91
- end
92
-
93
- destination.write(segment)
94
- end
95
- end
96
-
97
- raise Error, "#{resp.code} for #{download_file_name}" unless resp.is_a? Net::HTTPSuccess
98
- end
91
+ File.open(download_file_name, 'wb') do |destination|
92
+ download_server(redirected, destination)
99
93
  end
100
94
  rescue StandardError
101
95
  FileUtils.rm download_file_name if File.exist? download_file_name
@@ -106,30 +100,57 @@ module Selenium
106
100
  end
107
101
 
108
102
  #
109
- # Ask Google Code what the latest selenium-server-standalone version is.
103
+ # Ask GitHub what the latest selenium-server version is.
110
104
  #
111
105
 
112
106
  def latest
113
- require 'rexml/document'
114
- net_http_start('selenium-release.storage.googleapis.com') do |http|
115
- versions = REXML::Document.new(http.get('/').body).root.get_elements('//Contents/Key').map do |e|
116
- e.text[/selenium-server-standalone-(\d+\.\d+\.\d+)\.jar/, 1]
107
+ @latest ||= begin
108
+ net_http_start('api.github.com') do |http|
109
+ json = http.get('/repos/seleniumhq/selenium/releases').body
110
+ all_assets = JSON.parse(json).map { |release| release['assets'] }.flatten
111
+ server_assets = all_assets.map { |asset| asset['name'][/selenium-server-(\d+\.\d+\.\d+)\.jar/, 1] }.compact
112
+ server_assets.map { |version| Gem::Version.new(version) }.max.version
117
113
  end
118
-
119
- versions.compact.map { |version| Gem::Version.new(version) }.max.version
120
114
  end
121
115
  end
122
116
 
117
+ # @api private
118
+
123
119
  def net_http_start(address, &block)
124
120
  http_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
125
-
126
121
  if http_proxy
127
122
  http_proxy = "http://#{http_proxy}" unless http_proxy.start_with?('http://')
128
123
  uri = URI.parse(http_proxy)
129
124
 
130
125
  Net::HTTP.start(address, nil, uri.host, uri.port, &block)
131
126
  else
132
- Net::HTTP.start(address, &block)
127
+ Net::HTTP.start(address, use_ssl: true, &block)
128
+ end
129
+ end
130
+
131
+ def download_server(uri, destination)
132
+ net_http_start('github-releases.githubusercontent.com') do |http|
133
+ request = Net::HTTP::Get.new uri
134
+ resp = http.request(request) do |response|
135
+ total = response.content_length
136
+ progress = 0
137
+ segment_count = 0
138
+
139
+ response.read_body do |segment|
140
+ progress += segment.length
141
+ segment_count += 1
142
+
143
+ if (segment_count % 15).zero?
144
+ percent = progress.fdiv(total) * 100
145
+ print "#{CL_RESET}Downloading #{destination.path}: #{percent.to_i}% (#{progress} / #{total})"
146
+ segment_count = 0
147
+ end
148
+
149
+ destination.write(segment)
150
+ end
151
+ end
152
+
153
+ raise Error, "#{resp.code} for #{destination.path}" unless resp.is_a? Net::HTTPSuccess
133
154
  end
134
155
  end
135
156
  end
@@ -200,10 +221,6 @@ module Selenium
200
221
 
201
222
  private
202
223
 
203
- def selenium4?
204
- @jar.match?(/[^.]4\./) || @jar.include?('deploy')
205
- end
206
-
207
224
  def stop_process
208
225
  return unless @process.alive?
209
226
 
@@ -222,10 +239,7 @@ module Selenium
222
239
  @process ||= begin
223
240
  # extract any additional_args that start with -D as options
224
241
  properties = @additional_args.dup - @additional_args.delete_if { |arg| arg[/^-D/] }
225
- args = ['-jar', @jar]
226
- args << @role if selenium4?
227
- args << (selenium4? ? '--port' : '-port')
228
- args << @port.to_s
242
+ args = ['-jar', @jar, @role, '--port', @port.to_s]
229
243
  server_command = ['java'] + properties + args + @additional_args
230
244
  cp = ChildProcess.build(*server_command)
231
245
  WebDriver.logger.debug("Executing Process #{server_command}")
@@ -108,8 +108,8 @@ function gd(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4
108
108
  function hd(a){return a.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,"")}function id(a){var b=[];Yc?jd(a,b):kd(a,b);a=qa(b,hd);return hd(a.join("\n")).replace(/\xa0/g," ")}
109
109
  function ld(a,b,c){if(S(a,"BR"))b.push("");else{var d=S(a,"TD"),e=V(a,"display"),f=!d&&!(0<=oa(md,e)),g=void 0!==a.previousElementSibling?a.previousElementSibling:gb(a.previousSibling);g=g?V(g,"display"):"";var h=V(a,"float")||V(a,"cssFloat")||V(a,"styleFloat");!f||"run-in"==g&&"none"==h||/^[\s\xa0]*$/.test(b[b.length-1]||"")||b.push("");var n=ed(a),u=null,p=null;n&&(u=V(a,"white-space"),p=V(a,"text-transform"));l(a.childNodes,function(G){c(G,b,n,u,p)});a=b[b.length-1]||"";!d&&"table-cell"!=e||!a||
110
110
  za(a)||(b[b.length-1]+=" ");f&&"run-in"!=e&&!/^[\s\xa0]*$/.test(a)&&b.push("")}}function kd(a,b){ld(a,b,function(c,d,e,f,g){3==c.nodeType&&e?nd(c,d,f,g):S(c)&&kd(c,d)})}var md="inline inline-block inline-table none table-cell table-column table-column-group".split(" ");
111
- function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",0)&&(a=a.substr(1));
112
- b.push(c+a)}function dd(a){if(Mc){if("relative"==V(a,"position"))return 1;a=V(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=V(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
111
+ function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(t?/(^|\s|\b)(\S)/g:/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",
112
+ 0)&&(a=a.substr(1));b.push(c+a)}function dd(a){if(Mc){if("relative"==V(a,"position"))return 1;a=V(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=V(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
113
113
  function pd(a,b,c,d,e){if(3==a.nodeType&&c)nd(a,b,d,e);else if(S(a))if(S(a,"CONTENT")||S(a,"SLOT")){for(var f=a;f.parentNode;)f=f.parentNode;f instanceof ShadowRoot?(a=S(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),l(a,function(g){pd(g,b,c,d,e)})):jd(a,b)}else if(S(a,"SHADOW")){for(f=a;f.parentNode;)f=f.parentNode;if(f instanceof ShadowRoot&&(a=f))for(a=a.olderShadowRoot;a;)l(a.childNodes,function(g){pd(g,b,c,d,e)}),a=a.olderShadowRoot}else jd(a,b)}
114
114
  function jd(a,b){a.shadowRoot&&l(a.shadowRoot.childNodes,function(c){pd(c,b,!0,null,null)});ld(a,b,function(c,d,e,f,g){var h=null;1==c.nodeType?h=c:3==c.nodeType&&(h=c);null!=h&&(null!=h.assignedSlot||h.getDestinationInsertionPoints&&0<h.getDestinationInsertionPoints().length)||pd(c,d,e,f,g)})};var qd={C:function(a,b){return!(!a.querySelectorAll||!a.querySelector)&&!/^\d.*/.test(b)},o:function(a,b){var c=eb(b),d="string"===typeof a?c.a.getElementById(a):a;return d?Uc(d,"id")==a&&b!=d&&hb(b,d)?d:ua(mb(c,"*"),function(e){return Uc(e,"id")==a&&b!=e&&hb(b,e)}):null},j:function(a,b){if(!a)return[];if(qd.C(b,a))try{return b.querySelectorAll("#"+qd.T(a))}catch(c){return[]}b=mb(eb(b),"*",null,b);return pa(b,function(c){return Uc(c,"id")==a})},T:function(a){return a.replace(/([\s'"\\#.:;,!?+<>=~*^$|%&@`{}\-\/\[\]\(\)])/g,
115
115
  "\\$1")}};var Y={},rd={};Y.N=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return ua(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.K=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return pa(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.o=function(a,b){return Y.N(a,b,!1)};Y.j=function(a,b){return Y.K(a,b,!1)};rd.o=function(a,b){return Y.N(a,b,!0)};
@@ -38,10 +38,19 @@ module Selenium
38
38
  # @param [Hash] conditions
39
39
  # @option conditions [Integer] :latency
40
40
  # @option conditions [Integer] :throughput
41
+ # @option conditions [Integer] :upload_throughput
42
+ # @option conditions [Integer] :download_throughput
41
43
  # @option conditions [Boolean] :offline
42
44
  #
43
45
 
44
46
  def network_conditions=(conditions)
47
+ conditions[:latency] ||= 0
48
+ unless conditions.key?(:throughput)
49
+ conditions[:download_throughput] ||= -1
50
+ conditions[:upload_throughput] ||= -1
51
+ end
52
+ conditions[:offline] = false unless conditions.key?(:offline)
53
+
45
54
  @bridge.network_conditions = conditions
46
55
  end
47
56
 
@@ -73,16 +73,10 @@ module Selenium
73
73
  def from_json(json)
74
74
  data = decoded(json)
75
75
 
76
- # can't use Tempfile here since it doesn't support File::BINARY mode on 1.8
77
- # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
78
- tmp_dir = Dir.mktmpdir
79
- begin
80
- zip_path = File.join(tmp_dir, "webdriver-profile-duplicate-#{json.hash}.zip")
76
+ Tempfile.create do |zip_path|
81
77
  File.open(zip_path, 'wb') { |zip_file| zip_file << Base64.decode64(data) }
82
78
 
83
79
  new Zipper.unzip(zip_path)
84
- ensure
85
- FileUtils.rm_rf tmp_dir
86
80
  end
87
81
  end
88
82
  end # ClassMethods
@@ -65,26 +65,37 @@ module Selenium
65
65
  arr << Errno::EALREADY if Platform.wsl?
66
66
  }.freeze
67
67
 
68
- def listening?
69
- addr = Socket.getaddrinfo(@host, @port, Socket::AF_INET, Socket::SOCK_STREAM)
70
- sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
71
- sockaddr = Socket.pack_sockaddr_in(@port, addr[0][3])
72
-
73
- begin
74
- sock.connect_nonblock sockaddr
75
- rescue Errno::EINPROGRESS
76
- retry if socket_writable?(sock) && conn_completed?(sock)
77
- raise Errno::ECONNREFUSED
78
- rescue *CONNECTED_ERRORS
79
- # yay!
68
+ if Platform.jruby?
69
+ # we use a plain TCPSocket here since JRuby has issues closing socket
70
+ # see https://github.com/jruby/jruby/issues/5709
71
+ def listening?
72
+ TCPSocket.new(@host, @port).close
73
+ true
74
+ rescue *NOT_CONNECTED_ERRORS
75
+ false
76
+ end
77
+ else
78
+ def listening?
79
+ addr = Socket.getaddrinfo(@host, @port, Socket::AF_INET, Socket::SOCK_STREAM)
80
+ sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
81
+ sockaddr = Socket.pack_sockaddr_in(@port, addr[0][3])
82
+
83
+ begin
84
+ sock.connect_nonblock sockaddr
85
+ rescue Errno::EINPROGRESS
86
+ retry if socket_writable?(sock) && conn_completed?(sock)
87
+ raise Errno::ECONNREFUSED
88
+ rescue *CONNECTED_ERRORS
89
+ # yay!
90
+ end
91
+
92
+ sock.close
93
+ true
94
+ rescue *NOT_CONNECTED_ERRORS
95
+ sock&.close
96
+ WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
97
+ false
80
98
  end
81
-
82
- sock.close
83
- true
84
- rescue *NOT_CONNECTED_ERRORS
85
- sock&.close
86
- WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
87
- false
88
99
  end
89
100
 
90
101
  def socket_writable?(sock)
@@ -24,22 +24,49 @@ module Selenium
24
24
  @bridge = bridge
25
25
  end
26
26
 
27
+ #
28
+ # Gets the amount of time the driver should wait when searching for elements.
29
+ #
30
+
31
+ def implicit_wait
32
+ Float(@bridge.timeouts['implicit']) / 1000
33
+ end
34
+
27
35
  #
28
36
  # Set the amount of time the driver should wait when searching for elements.
29
37
  #
30
38
 
31
39
  def implicit_wait=(seconds)
32
- @bridge.implicit_wait_timeout = Integer(seconds * 1000)
40
+ @bridge.timeouts = {'implicit' => Integer(seconds * 1000)}
33
41
  end
34
42
 
43
+ #
44
+ # Gets the amount of time to wait for an asynchronous script to finish
45
+ # execution before throwing an error.
46
+ #
47
+
48
+ def script
49
+ Float(@bridge.timeouts['script']) / 1000
50
+ end
51
+ alias_method :script_timeout, :script
52
+
35
53
  #
36
54
  # Sets the amount of time to wait for an asynchronous script to finish
37
55
  # execution before throwing an error. If the timeout is negative, then the
38
56
  # script will be allowed to run indefinitely.
39
57
  #
40
58
 
41
- def script_timeout=(seconds)
42
- @bridge.script_timeout = Integer(seconds * 1000)
59
+ def script=(seconds)
60
+ @bridge.timeouts = {'script' => Integer(seconds * 1000)}
61
+ end
62
+ alias_method :script_timeout=, :script=
63
+
64
+ #
65
+ # Gets the amount of time to wait for a page load to complete before throwing an error.
66
+ #
67
+
68
+ def page_load
69
+ Float(@bridge.timeouts['pageLoad']) / 1000
43
70
  end
44
71
 
45
72
  #
@@ -48,7 +75,7 @@ module Selenium
48
75
  #
49
76
 
50
77
  def page_load=(seconds)
51
- @bridge.timeout 'page load', Integer(seconds * 1000)
78
+ @bridge.timeouts = {'pageLoad' => Integer(seconds * 1000)}
52
79
  end
53
80
  end # Timeouts
54
81
  end # WebDriver
@@ -72,16 +72,8 @@ module Selenium
72
72
  private
73
73
 
74
74
  def with_tmp_zip(&blk)
75
- # can't use Tempfile here since it doesn't support File::BINARY mode on 1.8
76
- # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
77
- tmp_dir = Dir.mktmpdir
78
- zip_path = File.join(tmp_dir, 'webdriver-zip')
79
-
80
- begin
75
+ Tempfile.create do |zip_path|
81
76
  Zip::File.open(zip_path, Zip::File::CREATE, &blk)
82
- ensure
83
- FileUtils.rm_rf tmp_dir
84
- FileUtils.rm_rf zip_path
85
77
  end
86
78
  end
87
79
 
@@ -173,6 +173,10 @@ module Selenium
173
173
  Profile.from_name(profile)
174
174
  end
175
175
  end
176
+
177
+ def camelize?(key)
178
+ key != :prefs
179
+ end
176
180
  end # Options
177
181
  end # Firefox
178
182
  end # WebDriver
@@ -93,17 +93,16 @@ module Selenium
93
93
  execute :get, {}, {url: url}
94
94
  end
95
95
 
96
- def implicit_wait_timeout=(milliseconds)
97
- timeout('implicit', milliseconds)
98
- end
96
+ #
97
+ # timeouts
98
+ #
99
99
 
100
- def script_timeout=(milliseconds)
101
- timeout('script', milliseconds)
100
+ def timeouts
101
+ execute :get_timeouts, {}
102
102
  end
103
103
 
104
- def timeout(type, milliseconds)
105
- type = 'pageLoad' if type == 'page load'
106
- execute :set_timeout, {}, {type => milliseconds}
104
+ def timeouts=(timeouts)
105
+ execute :set_timeout, {}, timeouts
107
106
  end
108
107
 
109
108
  #
@@ -658,7 +657,7 @@ module Selenium
658
657
  # @see https://mathiasbynens.be/notes/css-escapes
659
658
  def escape_css(string)
660
659
  string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
661
- string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..-1]}" if string[0]&.match?(/[[:digit:]]/)
660
+ string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
662
661
 
663
662
  string
664
663
  end
@@ -114,6 +114,7 @@ module Selenium
114
114
  # timeouts
115
115
  #
116
116
 
117
+ get_timeouts: [:get, 'session/:session_id/timeouts'],
117
118
  set_timeout: [:post, 'session/:session_id/timeouts'],
118
119
 
119
120
  #
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.0.0.rc2'
22
+ VERSION = '4.0.2'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  }
29
29
 
30
30
  s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
31
- s.required_ruby_version = Gem::Requirement.new('>= 2.5')
31
+ s.required_ruby_version = Gem::Requirement.new('>= 2.6')
32
32
 
33
33
  s.files = [
34
34
  'CHANGES',
@@ -45,7 +45,7 @@ Gem::Specification.new do |s|
45
45
  s.require_paths = ['lib']
46
46
 
47
47
  s.add_runtime_dependency 'childprocess', ['>= 0.5', '< 5.0']
48
- s.add_runtime_dependency 'rexml', ['~> 3.2']
48
+ s.add_runtime_dependency 'rexml', ['~> 3.2', '>= 3.2.5']
49
49
  s.add_runtime_dependency 'rubyzip', ['>= 1.2.2']
50
50
 
51
51
  # childprocess requires ffi on windows but doesn't declare it in its dependencies
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.rc2
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rodionov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-09-30 00:00:00.000000000 Z
13
+ date: 2021-10-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: childprocess
@@ -39,6 +39,9 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '3.2'
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 3.2.5
42
45
  type: :runtime
43
46
  prerelease: false
44
47
  version_requirements: !ruby/object:Gem::Requirement
@@ -46,6 +49,9 @@ dependencies:
46
49
  - - "~>"
47
50
  - !ruby/object:Gem::Version
48
51
  version: '3.2'
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.5
49
55
  - !ruby/object:Gem::Dependency
50
56
  name: rubyzip
51
57
  requirement: !ruby/object:Gem::Requirement
@@ -380,7 +386,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
380
386
  requirements:
381
387
  - - ">="
382
388
  - !ruby/object:Gem::Version
383
- version: '2.5'
389
+ version: '2.6'
384
390
  required_rubygems_version: !ruby/object:Gem::Requirement
385
391
  requirements:
386
392
  - - ">"