selenium-webdriver 4.0.0.rc1 → 4.0.1

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +60 -0
  3. data/README.md +1 -1
  4. data/lib/selenium/server.rb +62 -48
  5. data/lib/selenium/webdriver/atoms/findElements.js +2 -2
  6. data/lib/selenium/webdriver/atoms/getAttribute.js +25 -25
  7. data/lib/selenium/webdriver/chrome/driver.rb +3 -0
  8. data/lib/selenium/webdriver/chrome/features.rb +44 -4
  9. data/lib/selenium/webdriver/chrome/options.rb +24 -1
  10. data/lib/selenium/webdriver/common/driver.rb +2 -0
  11. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
  12. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
  13. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
  14. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
  15. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
  16. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +87 -18
  17. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
  18. data/lib/selenium/webdriver/common/driver_extensions/prints_page.rb +1 -1
  19. data/lib/selenium/webdriver/common/log_entry.rb +2 -2
  20. data/lib/selenium/webdriver/common/manager.rb +3 -13
  21. data/lib/selenium/webdriver/common/options.rb +13 -5
  22. data/lib/selenium/webdriver/common/profile_helper.rb +1 -7
  23. data/lib/selenium/webdriver/common/socket_poller.rb +30 -19
  24. data/lib/selenium/webdriver/common/target_locator.rb +28 -0
  25. data/lib/selenium/webdriver/common/timeouts.rb +31 -4
  26. data/lib/selenium/webdriver/common/window.rb +0 -4
  27. data/lib/selenium/webdriver/common/zipper.rb +1 -9
  28. data/lib/selenium/webdriver/common.rb +4 -0
  29. data/lib/selenium/webdriver/devtools/request.rb +27 -17
  30. data/lib/selenium/webdriver/devtools/response.rb +66 -0
  31. data/lib/selenium/webdriver/devtools.rb +49 -12
  32. data/lib/selenium/webdriver/edge/features.rb +5 -0
  33. data/lib/selenium/webdriver/firefox/driver.rb +5 -0
  34. data/lib/selenium/webdriver/firefox/features.rb +14 -0
  35. data/lib/selenium/webdriver/firefox/options.rb +28 -1
  36. data/lib/selenium/webdriver/firefox.rb +0 -1
  37. data/lib/selenium/webdriver/remote/bridge.rb +9 -10
  38. data/lib/selenium/webdriver/remote/capabilities.rb +1 -0
  39. data/lib/selenium/webdriver/remote/commands.rb +1 -0
  40. data/lib/selenium/webdriver/remote/driver.rb +2 -1
  41. data/lib/selenium/webdriver/safari/driver.rb +1 -1
  42. data/lib/selenium/webdriver/safari/options.rb +7 -0
  43. data/lib/selenium/webdriver/version.rb +1 -1
  44. data/lib/selenium/webdriver.rb +1 -0
  45. data/selenium-webdriver.gemspec +2 -2
  46. metadata +14 -3
@@ -0,0 +1,77 @@
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
+ module DriverExtensions
23
+ module HasCasting
24
+
25
+ #
26
+ # What devices ("sinks") are available to be cast to.
27
+ #
28
+ # @return [Array] list of sinks available for casting with id and name values
29
+ #
30
+
31
+ def cast_sinks
32
+ @bridge.cast_sinks
33
+ end
34
+
35
+ #
36
+ # Sets a specific sink, using its name, as a Cast session receiver target.
37
+ #
38
+ # @param [String] name the sink to use as the target
39
+ #
40
+
41
+ def cast_sink_to_use=(name)
42
+ @bridge.cast_sink_to_use = name
43
+ end
44
+
45
+ #
46
+ # Starts a tab mirroring session on a specific receiver target.
47
+ #
48
+ # @param [String] name the sink to use as the target
49
+ #
50
+
51
+ def start_cast_tab_mirroring(name)
52
+ @bridge.start_cast_tab_mirroring(name)
53
+ end
54
+
55
+ #
56
+ # Gets error messages when there is any issue in a Cast session.
57
+ #
58
+ # @return [String] the error message
59
+ #
60
+
61
+ def cast_issue_message
62
+ @bridge.cast_issue_message
63
+ end
64
+
65
+ #
66
+ # Stops the existing Cast session on a specific receiver target.
67
+ #
68
+ # @param [String] name the sink to stop the Cast session
69
+ #
70
+
71
+ def stop_casting(name)
72
+ @bridge.stop_casting(name)
73
+ end
74
+ end # HasCasting
75
+ end # DriverExtensions
76
+ end # WebDriver
77
+ end # Selenium
@@ -0,0 +1,45 @@
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
+ module DriverExtensions
23
+ module HasContext
24
+
25
+ #
26
+ # Sets the context that Selenium commands are running in using
27
+ # a `with` statement. The state of the context on the server is
28
+ # saved before entering the block, and restored upon exiting it.
29
+ #
30
+ # @param [String] name which permission to set
31
+ # @param [String] value what to set the permission to
32
+ #
33
+
34
+ def context=(value)
35
+ @bridge.context = value
36
+ end
37
+
38
+ def context
39
+ @bridge.context
40
+ end
41
+
42
+ end # HasContext
43
+ end # DriverExtensions
44
+ end # WebDriver
45
+ end # Selenium
@@ -0,0 +1,38 @@
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
+ module DriverExtensions
23
+ module HasLaunching
24
+
25
+ #
26
+ # Launches Chromium app specified by id.
27
+ #
28
+ # @param [String] id
29
+ #
30
+
31
+ def launch_app(id)
32
+ @bridge.launch_app(id)
33
+ end
34
+
35
+ end # HasLaunching
36
+ end # DriverExtensions
37
+ end # WebDriver
38
+ end # Selenium
@@ -38,13 +38,30 @@ 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
 
57
+ #
58
+ # Resets Chromium network emulation settings.
59
+ #
60
+
61
+ def delete_network_conditions
62
+ @bridge.delete_network_conditions
63
+ end
64
+
48
65
  end # HasNetworkConditions
49
66
  end # DriverExtensions
50
67
  end # WebDriver
@@ -28,39 +28,108 @@ module Selenium
28
28
  # a stubbed response instead.
29
29
  #
30
30
  # @example Log requests and pass through
31
- # driver.intercept do |request|
31
+ # driver.intercept do |request, &continue|
32
32
  # puts "#{request.method} #{request.url}"
33
- # request.continue
33
+ # continue.call(request)
34
34
  # end
35
35
  #
36
- # @example Stub response for image requests
37
- # driver.intercept do |request|
36
+ # @example Stub requests for images
37
+ # driver.intercept do |request, &continue|
38
38
  # if request.url.match?(/\.png$/)
39
- # request.respond(body: File.read('myfile.png'))
40
- # else
41
- # request.continue
39
+ # request.url = 'https://upload.wikimedia.org/wikipedia/commons/d/d5/Selenium_Logo.png'
42
40
  # end
41
+ # continue.call(request)
43
42
  # end
44
43
  #
45
- # @param [#call] block which is called when request is interecepted
46
- # @yieldparam [DevTools::Request]
44
+ # @example Log responses and pass through
45
+ # driver.intercept do |request, &continue|
46
+ # continue.call(request) do |response|
47
+ # puts "#{response.code} #{response.body}"
48
+ # end
49
+ # end
50
+ #
51
+ # @example Mutate specific response
52
+ # driver.intercept do |request, &continue|
53
+ # continue.call(request) do |response|
54
+ # response.body << 'Added by Selenium!' if request.url.include?('/myurl')
55
+ # end
56
+ # end
57
+ #
58
+ # @param [Proc] block which is called when request is intercepted
59
+ # @yieldparam [DevTools::Request] request
60
+ # @yieldparam [Proc] continue block which proceeds with the request and optionally yields response
47
61
  #
48
62
 
49
- def intercept
63
+ def intercept(&block)
50
64
  devtools.network.set_cache_disabled(cache_disabled: true)
51
65
  devtools.fetch.on(:request_paused) do |params|
52
- request = DevTools::Request.new(
53
- devtools: devtools,
54
- id: params['requestId'],
55
- url: params.dig('request', 'url'),
56
- method: params.dig('request', 'method'),
57
- headers: params.dig('request', 'headers')
66
+ id = params['requestId']
67
+ if params.key?('responseStatusCode') || params.key?('responseErrorReason')
68
+ intercept_response(id, params, &pending_response_requests.delete(id))
69
+ else
70
+ intercept_request(id, params, &block)
71
+ end
72
+ end
73
+ devtools.fetch.enable(patterns: [{requestStage: 'Request'}, {requestStage: 'Response'}])
74
+ end
75
+
76
+ private
77
+
78
+ def pending_response_requests
79
+ @pending_response_requests ||= {}
80
+ end
81
+
82
+ def intercept_request(id, params, &block)
83
+ original = DevTools::Request.from(id, params)
84
+ mutable = DevTools::Request.from(id, params)
85
+
86
+ block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall
87
+ pending_response_requests[id] = continue
88
+
89
+ if original == mutable
90
+ devtools.fetch.continue_request(request_id: id)
91
+ else
92
+ devtools.fetch.continue_request(
93
+ request_id: id,
94
+ url: mutable.url,
95
+ method: mutable.method,
96
+ post_data: mutable.post_data,
97
+ headers: mutable.headers.map do |k, v|
98
+ {name: k, value: v}
99
+ end
100
+ )
101
+ end
102
+ end
103
+ end
104
+
105
+ def intercept_response(id, params)
106
+ return devtools.fetch.continue_request(request_id: id) unless block_given?
107
+
108
+ body = fetch_response_body(id)
109
+ original = DevTools::Response.from(id, body, params)
110
+ mutable = DevTools::Response.from(id, body, params)
111
+ yield mutable
112
+
113
+ if original == mutable
114
+ devtools.fetch.continue_request(request_id: id)
115
+ else
116
+ devtools.fetch.fulfill_request(
117
+ request_id: id,
118
+ body: (Base64.strict_encode64(mutable.body) if mutable.body),
119
+ response_code: mutable.code,
120
+ response_headers: mutable.headers.map do |k, v|
121
+ {name: k, value: v}
122
+ end
58
123
  )
59
- yield request
60
124
  end
61
- devtools.fetch.enable
62
125
  end
63
126
 
127
+ def fetch_response_body(id)
128
+ devtools.fetch.get_response_body(request_id: id).dig('result', 'body')
129
+ rescue Error::WebDriverError
130
+ # CDP fails to get body on certain responses (301) and raises:
131
+ # Can only get response body on requests captured after headers received.
132
+ end
64
133
  end # HasNetworkInterception
65
134
  end # DriverExtensions
66
135
  end # WebDriver
@@ -23,26 +23,26 @@ module Selenium
23
23
  module HasPermissions
24
24
 
25
25
  #
26
- # Returns permissions.
26
+ # Set one permission.
27
27
  #
28
- # @return [Hash]
28
+ # @param [String] name which permission to set
29
+ # @param [String] value what to set the permission to
29
30
  #
30
31
 
31
- def permissions
32
- @bridge.permissions
32
+ def add_permission(name, value)
33
+ @bridge.set_permission(name, value)
33
34
  end
34
35
 
35
36
  #
36
- # Sets permissions.
37
+ # Set multiple permissions.
37
38
  #
38
- # @example
39
- # driver.permissions = {'getUserMedia' => true}
40
- #
41
- # @param [Hash<Symbol, Boolean>] permissions
39
+ # @param [Hash] opt key/value pairs to set permissions
42
40
  #
43
41
 
44
- def permissions=(permissions)
45
- @bridge.permissions = permissions
42
+ def add_permissions(opt)
43
+ opt.each do |key, value|
44
+ @bridge.set_permission(key, value)
45
+ end
46
46
  end
47
47
 
48
48
  end # HasPermissions
@@ -34,7 +34,7 @@ module Selenium
34
34
 
35
35
  def save_print_page(path, **options)
36
36
  File.open(path, 'wb') do |file|
37
- content = Base64.decode64 print_page(options)
37
+ content = Base64.decode64 print_page(**options)
38
38
  file << content
39
39
  end
40
40
  end
@@ -30,14 +30,14 @@ module Selenium
30
30
 
31
31
  def as_json(*)
32
32
  {
33
- 'level' => level,
34
33
  'timestamp' => timestamp,
34
+ 'level' => level,
35
35
  'message' => message
36
36
  }
37
37
  end
38
38
 
39
39
  def to_s
40
- "#{level} #{time}: #{message}"
40
+ "#{time} #{level}: #{message}"
41
41
  end
42
42
 
43
43
  def time
@@ -104,25 +104,19 @@ module Selenium
104
104
  @timeouts ||= Timeouts.new(@bridge)
105
105
  end
106
106
 
107
- #
108
- # @api beta This API may be changed or removed in a future release.
109
- #
110
-
111
107
  def logs
112
108
  WebDriver.logger.deprecate('Manager#logs', 'Chrome::Driver#logs')
113
109
  @logs ||= Logs.new(@bridge)
114
110
  end
115
111
 
116
112
  #
117
- # Create a new top-level browsing context
118
- # https://w3c.github.io/webdriver/#new-window
119
113
  # @param type [Symbol] Supports two values: :tab and :window.
120
- # Use :tab if you'd like the new window to share an OS-level window
121
- # with the current browsing context.
122
- # Use :window otherwise
123
114
  # @return [String] The value of the window handle
124
115
  #
125
116
  def new_window(type = :tab)
117
+ WebDriver.logger.deprecate('Manager#new_window', 'TargetLocator#new_window', id: :new_window) do
118
+ 'e.g., `driver.switch_to.new_window(:tab)`'
119
+ end
126
120
  case type
127
121
  when :tab, :window
128
122
  result = @bridge.new_window(type)
@@ -137,10 +131,6 @@ module Selenium
137
131
  end
138
132
  end
139
133
 
140
- #
141
- # @api beta This API may be changed or removed in a future release.
142
- #
143
-
144
134
  def window
145
135
  @window ||= Window.new(@bridge)
146
136
  end
@@ -21,7 +21,8 @@ module Selenium
21
21
  module WebDriver
22
22
  class Options
23
23
  W3C_OPTIONS = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy
24
- set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability].freeze
24
+ set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
25
+ web_socket_url].freeze
25
26
 
26
27
  class << self
27
28
  attr_reader :driver_path
@@ -90,7 +91,8 @@ module Selenium
90
91
  # @param [Boolean, String, Integer] value Value of the option
91
92
  #
92
93
 
93
- def add_option(name, value)
94
+ def add_option(name, value = nil)
95
+ @options[name.keys.first] = name.values.first if value.nil? && name.is_a?(Hash)
94
96
  @options[name] = value
95
97
  end
96
98
 
@@ -123,10 +125,14 @@ module Selenium
123
125
 
124
126
  private
125
127
 
128
+ def w3c?(key)
129
+ W3C_OPTIONS.include?(key) || key.to_s.include?(':')
130
+ end
131
+
126
132
  def process_w3c_options(options)
127
- w3c_options = options.select { |key, _val| W3C_OPTIONS.include?(key) }
133
+ w3c_options = options.select { |key, _val| w3c?(key) }
128
134
  w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
129
- options.delete_if { |key, _val| W3C_OPTIONS.include?(key) }
135
+ options.delete_if { |key, _val| w3c?(key) }
130
136
  w3c_options
131
137
  end
132
138
 
@@ -173,6 +179,8 @@ module Selenium
173
179
  def camel_case(str)
174
180
  str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
175
181
  end
176
- end # Options
182
+ end
183
+
184
+ # Options
177
185
  end # WebDriver
178
186
  end # Selenium
@@ -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)
@@ -44,6 +44,34 @@ module Selenium
44
44
  @bridge.switch_to_parent_frame
45
45
  end
46
46
 
47
+ #
48
+ # Switch to a new top-level browsing context
49
+ #
50
+ # @param type either :tab or :window
51
+ #
52
+
53
+ def new_window(type = :window)
54
+ unless %i[window tab].include?(type)
55
+ raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}"
56
+ end
57
+
58
+ handle = @bridge.new_window(type)['handle']
59
+
60
+ if block_given?
61
+ execute_and_close = proc do
62
+ yield(self)
63
+ begin
64
+ @bridge.close
65
+ rescue Error::NoSuchWindowError
66
+ # window already closed
67
+ end
68
+ end
69
+ window(handle, &execute_and_close)
70
+ else
71
+ window(handle)
72
+ end
73
+ end
74
+
47
75
  #
48
76
  # switch to the given window handle
49
77
  #
@@ -24,22 +24,49 @@ module Selenium
24
24
  @bridge = bridge
25
25
  end
26
26
 
27
+ #
28
+ # Gets the amount of time the driver should wait when searching for elements.
29
+ #
30
+
31
+ def implicit_wait
32
+ Float(@bridge.timeouts['implicit']) / 1000
33
+ end
34
+
27
35
  #
28
36
  # Set the amount of time the driver should wait when searching for elements.
29
37
  #
30
38
 
31
39
  def implicit_wait=(seconds)
32
- @bridge.implicit_wait_timeout = Integer(seconds * 1000)
40
+ @bridge.timeouts = {'implicit' => Integer(seconds * 1000)}
33
41
  end
34
42
 
43
+ #
44
+ # Gets the amount of time to wait for an asynchronous script to finish
45
+ # execution before throwing an error.
46
+ #
47
+
48
+ def script
49
+ Float(@bridge.timeouts['script']) / 1000
50
+ end
51
+ alias_method :script_timeout, :script
52
+
35
53
  #
36
54
  # Sets the amount of time to wait for an asynchronous script to finish
37
55
  # execution before throwing an error. If the timeout is negative, then the
38
56
  # script will be allowed to run indefinitely.
39
57
  #
40
58
 
41
- def script_timeout=(seconds)
42
- @bridge.script_timeout = Integer(seconds * 1000)
59
+ def script=(seconds)
60
+ @bridge.timeouts = {'script' => Integer(seconds * 1000)}
61
+ end
62
+ alias_method :script_timeout=, :script=
63
+
64
+ #
65
+ # Gets the amount of time to wait for a page load to complete before throwing an error.
66
+ #
67
+
68
+ def page_load
69
+ Float(@bridge.timeouts['pageLoad']) / 1000
43
70
  end
44
71
 
45
72
  #
@@ -48,7 +75,7 @@ module Selenium
48
75
  #
49
76
 
50
77
  def page_load=(seconds)
51
- @bridge.timeout 'page load', Integer(seconds * 1000)
78
+ @bridge.timeouts = {'pageLoad' => Integer(seconds * 1000)}
52
79
  end
53
80
  end # Timeouts
54
81
  end # WebDriver
@@ -19,10 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- #
23
- # @api beta This API may be changed or removed in a future release.
24
- #
25
-
26
22
  class Window
27
23
  #
28
24
  # @api private
@@ -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