puppeteer-ruby 0.0.6 → 0.0.8

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/docs/Puppeteer.html +53 -43
  4. data/docs/Puppeteer/AsyncAwaitBehavior.html +1 -1
  5. data/docs/Puppeteer/Browser.html +1 -1
  6. data/docs/Puppeteer/BrowserContext.html +1 -1
  7. data/docs/Puppeteer/BrowserFetcher.html +1 -1
  8. data/docs/Puppeteer/BrowserRunner.html +1 -1
  9. data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +1 -1
  10. data/docs/Puppeteer/CDPSession.html +1 -1
  11. data/docs/Puppeteer/CDPSession/Error.html +1 -1
  12. data/docs/Puppeteer/ConcurrentRubyUtils.html +1 -1
  13. data/docs/Puppeteer/Connection.html +1 -1
  14. data/docs/Puppeteer/Connection/MessageCallback.html +1 -1
  15. data/docs/Puppeteer/Connection/ProtocolError.html +1 -1
  16. data/docs/Puppeteer/Connection/RequestDebugPrinter.html +1 -1
  17. data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +1 -1
  18. data/docs/Puppeteer/ConsoleMessage.html +1 -1
  19. data/docs/Puppeteer/ConsoleMessage/Location.html +1 -1
  20. data/docs/Puppeteer/DOMWorld.html +116 -19
  21. data/docs/Puppeteer/DOMWorld/DetachedError.html +1 -1
  22. data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +1 -1
  23. data/docs/Puppeteer/DebugPrint.html +1 -1
  24. data/docs/Puppeteer/Device.html +1 -1
  25. data/docs/Puppeteer/Devices.html +1 -1
  26. data/docs/Puppeteer/ElementHandle.html +565 -141
  27. data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +5 -5
  28. data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +5 -5
  29. data/docs/Puppeteer/ElementHandle/Point.html +21 -21
  30. data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +1 -1
  31. data/docs/Puppeteer/EmulationManager.html +1 -1
  32. data/docs/Puppeteer/EventCallbackable.html +1 -1
  33. data/docs/Puppeteer/EventCallbackable/EventListeners.html +1 -1
  34. data/docs/Puppeteer/ExecutionContext.html +114 -11
  35. data/docs/Puppeteer/ExecutionContext/EvaluationError.html +1 -1
  36. data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +1 -1
  37. data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +1 -1
  38. data/docs/Puppeteer/FileChooser.html +455 -0
  39. data/docs/Puppeteer/Frame.html +1 -1
  40. data/docs/Puppeteer/FrameManager.html +1 -1
  41. data/docs/Puppeteer/FrameManager/NavigationError.html +1 -1
  42. data/docs/Puppeteer/IfPresent.html +1 -1
  43. data/docs/Puppeteer/JSHandle.html +1 -1
  44. data/docs/Puppeteer/Keyboard.html +1 -1
  45. data/docs/Puppeteer/Keyboard/KeyDefinition.html +1 -1
  46. data/docs/Puppeteer/Keyboard/KeyDescription.html +1 -1
  47. data/docs/Puppeteer/Launcher.html +1 -1
  48. data/docs/Puppeteer/Launcher/Base.html +1 -1
  49. data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +1 -1
  50. data/docs/Puppeteer/Launcher/BrowserOptions.html +1 -1
  51. data/docs/Puppeteer/Launcher/Chrome.html +64 -23
  52. data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +1 -1
  53. data/docs/Puppeteer/Launcher/ChromeArgOptions.html +1 -1
  54. data/docs/Puppeteer/Launcher/LaunchOptions.html +1 -1
  55. data/docs/Puppeteer/LifecycleWatcher.html +1 -1
  56. data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +1 -1
  57. data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +1 -1
  58. data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +1 -1
  59. data/docs/Puppeteer/Mouse.html +1 -1
  60. data/docs/Puppeteer/Mouse/Button.html +1 -1
  61. data/docs/Puppeteer/NetworkManager.html +1 -1
  62. data/docs/Puppeteer/NetworkManager/Credentials.html +1 -1
  63. data/docs/Puppeteer/Page.html +841 -349
  64. data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
  65. data/docs/Puppeteer/Page/ScreenshotOptions.html +1 -1
  66. data/docs/Puppeteer/Page/ScriptTag.html +24 -24
  67. data/docs/Puppeteer/Page/StyleTag.html +19 -19
  68. data/docs/Puppeteer/Page/TargetCrashedError.html +1 -1
  69. data/docs/Puppeteer/RemoteObject.html +68 -3
  70. data/docs/Puppeteer/Target.html +1 -1
  71. data/docs/Puppeteer/Target/InitializeFailure.html +1 -1
  72. data/docs/Puppeteer/Target/TargetInfo.html +1 -1
  73. data/docs/Puppeteer/TimeoutError.html +1 -1
  74. data/docs/Puppeteer/TimeoutSettings.html +1 -1
  75. data/docs/Puppeteer/TouchScreen.html +1 -1
  76. data/docs/Puppeteer/Viewport.html +1 -1
  77. data/docs/Puppeteer/WaitTask.html +1 -1
  78. data/docs/Puppeteer/WaitTask/TerminatedError.html +1 -1
  79. data/docs/Puppeteer/WaitTask/TimeoutError.html +1 -1
  80. data/docs/Puppeteer/WebSocket.html +1 -1
  81. data/docs/Puppeteer/WebSocket/DriverImpl.html +1 -1
  82. data/docs/Puppeteer/WebSocketTransport.html +1 -1
  83. data/docs/Puppeteer/WebSocktTransportError.html +1 -1
  84. data/docs/_index.html +19 -5
  85. data/docs/class_list.html +1 -1
  86. data/docs/file.README.html +5 -3
  87. data/docs/index.html +5 -3
  88. data/docs/method_list.html +644 -508
  89. data/docs/top-level-namespace.html +1 -1
  90. data/lib/puppeteer.rb +7 -1
  91. data/lib/puppeteer/browser_runner.rb +1 -1
  92. data/lib/puppeteer/dom_world.rb +9 -12
  93. data/lib/puppeteer/element_handle.rb +82 -61
  94. data/lib/puppeteer/execution_context.rb +13 -0
  95. data/lib/puppeteer/file_chooser.rb +29 -0
  96. data/lib/puppeteer/frame_manager.rb +0 -2
  97. data/lib/puppeteer/launcher/chrome.rb +48 -2
  98. data/lib/puppeteer/page.rb +85 -52
  99. data/lib/puppeteer/remote_object.rb +6 -1
  100. data/lib/puppeteer/version.rb +1 -1
  101. metadata +5 -2
@@ -116,7 +116,7 @@
116
116
  </div>
117
117
 
118
118
  <div id="footer">
119
- Generated on Mon May 25 23:22:48 2020 by
119
+ Generated on Thu Jun 4 23:54:40 2020 by
120
120
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
121
121
  0.9.24 (ruby-2.6.3).
122
122
  </div>
data/lib/puppeteer.rb CHANGED
@@ -25,6 +25,7 @@ require 'puppeteer/devices'
25
25
  require 'puppeteer/dom_world'
26
26
  require 'puppeteer/emulation_manager'
27
27
  require 'puppeteer/execution_context'
28
+ require 'puppeteer/file_chooser'
28
29
  require 'puppeteer/frame'
29
30
  require 'puppeteer/frame_manager'
30
31
  require 'puppeteer/js_handle'
@@ -142,7 +143,12 @@ class Puppeteer
142
143
  default_viewport: default_viewport,
143
144
  slow_mo: slow_mo,
144
145
  }.compact
145
- launcher.connect(options)
146
+ browser = launcher.connect(options)
147
+ if block_given?
148
+ yield(browser)
149
+ else
150
+ browser
151
+ end
146
152
  end
147
153
 
148
154
  # @return {string}
@@ -147,7 +147,7 @@ class Puppeteer::BrowserRunner
147
147
  end
148
148
 
149
149
  private def wait_for_ws_endpoint(browser_process, timeout, preferred_revision)
150
- Timeout.timeout(timeout / 1000) do
150
+ Timeout.timeout(timeout / 1000.0) do
151
151
  loop do
152
152
  line = browser_process.stderr.readline
153
153
  /^DevTools listening on (ws:\/\/.*)$/.match(line) do |m|
@@ -355,18 +355,15 @@ class Puppeteer::DOMWorld
355
355
  # await handle.dispose();
356
356
  # }
357
357
 
358
- # /**
359
- # * @param {string} selector
360
- # * @param {!Array<string>} values
361
- # * @return {!Promise<!Array<string>>}
362
- # */
363
- # async select(selector, ...values) {
364
- # const handle = await this.$(selector);
365
- # assert(handle, 'No node found for selector: ' + selector);
366
- # const result = await handle.select(...values);
367
- # await handle.dispose();
368
- # return result;
369
- # }
358
+ # @param selector [String]
359
+ # @return [Array<String>]
360
+ def select(selector, *values)
361
+ handle = S(selector)
362
+ result = handle.select(*values)
363
+ handle.dispose
364
+
365
+ result
366
+ end
370
367
 
371
368
  # @param selector [String]
372
369
  def tap(selector)
@@ -1,3 +1,5 @@
1
+ require 'mime/types'
2
+
1
3
  class Puppeteer::ElementHandle < Puppeteer::JSHandle
2
4
  include Puppeteer::IfPresent
3
5
  using Puppeteer::AsyncAwaitBehavior
@@ -155,74 +157,77 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
155
157
  click(delay: delay, button: button, click_count: click_count)
156
158
  end
157
159
 
158
- # /**
159
- # * @param {!Array<string>} values
160
- # * @return {!Promise<!Array<string>>}
161
- # */
162
- # async select(...values) {
163
- # for (const value of values)
164
- # assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
165
- # return this.evaluate((element, values) => {
166
- # if (element.nodeName.toLowerCase() !== 'select')
167
- # throw new Error('Element is not a <select> element.');
168
-
169
- # const options = Array.from(element.options);
170
- # element.value = undefined;
171
- # for (const option of options) {
172
- # option.selected = values.includes(option.value);
173
- # if (option.selected && !element.multiple)
174
- # break;
175
- # }
176
- # element.dispatchEvent(new Event('input', { bubbles: true }));
177
- # element.dispatchEvent(new Event('change', { bubbles: true }));
178
- # return options.filter(option => option.selected).map(option => option.value);
179
- # }, values);
180
- # }
160
+ # @return [Array<String>]
161
+ def select(*values)
162
+ if nonstring = values.find { |value| !value.is_a?(String) }
163
+ raise ArgumentError.new("Values must be strings. Found value \"#{nonstring}\" of type \"#{nonstring.class}\"")
164
+ end
181
165
 
182
- # /**
183
- # * @param {!Array<string>} filePaths
184
- # */
185
- # async uploadFile(...filePaths) {
186
- # const isMultiple = await this.evaluate(element => element.multiple);
187
- # assert(filePaths.length <= 1 || isMultiple, 'Multiple file uploads only work with <input type=file multiple>');
188
- # // These imports are only needed for `uploadFile`, so keep them
189
- # // scoped here to avoid paying the cost unnecessarily.
190
- # const path = require('path');
191
- # const mime = require('mime-types');
192
- # const fs = require('fs');
193
- # const readFileAsync = helper.promisify(fs.readFile);
194
-
195
- # const promises = filePaths.map(filePath => readFileAsync(filePath));
196
- # const files = [];
197
- # for (let i = 0; i < filePaths.length; i++) {
198
- # const buffer = await promises[i];
199
- # const filePath = path.basename(filePaths[i]);
200
- # const file = {
201
- # name: filePath,
202
- # content: buffer.toString('base64'),
203
- # mimeType: mime.lookup(filePath),
204
- # };
205
- # files.push(file);
206
- # }
207
- # await this.evaluateHandle(async(element, files) => {
208
- # const dt = new DataTransfer();
209
- # for (const item of files) {
210
- # const response = await fetch(`data:${item.mimeType};base64,${item.content}`);
211
- # const file = new File([await response.blob()], item.name);
212
- # dt.items.add(file);
213
- # }
214
- # element.files = dt.files;
215
- # element.dispatchEvent(new Event('input', { bubbles: true }));
216
- # element.dispatchEvent(new Event('change', { bubbles: true }));
217
- # }, files);
218
- # }
166
+ fn = <<~JAVASCRIPT
167
+ (element, values) => {
168
+ if (element.nodeName.toLowerCase() !== 'select') {
169
+ throw new Error('Element is not a <select> element.');
170
+ }
171
+
172
+ const options = Array.from(element.options);
173
+ element.value = undefined;
174
+ for (const option of options) {
175
+ option.selected = values.includes(option.value);
176
+ if (option.selected && !element.multiple) {
177
+ break;
178
+ }
179
+ }
180
+ element.dispatchEvent(new Event('input', { bubbles: true }));
181
+ element.dispatchEvent(new Event('change', { bubbles: true }));
182
+ return options.filter(option => option.selected).map(option => option.value);
183
+ }
184
+ JAVASCRIPT
185
+ evaluate(fn, values)
186
+ end
187
+
188
+ # @param file_paths [Array<String>]
189
+ def upload_file(*file_paths)
190
+ is_multiple = evaluate("el => el.multiple")
191
+ if !is_multiple && file_paths.length >= 2
192
+ raise ArgumentError.new('Multiple file uploads only work with <input type=file multiple>')
193
+ end
194
+
195
+ if error_path = file_paths.find { |file_path| !File.exist?(file_path) }
196
+ raise ArgmentError.new("#{error_path} does not exist or is not readable")
197
+ end
198
+
199
+ backend_node_id = @remote_object.node_info(@client)["node"]["backendNodeId"]
200
+
201
+ # The zero-length array is a special case, it seems that DOM.setFileInputFiles does
202
+ # not actually update the files in that case, so the solution is to eval the element
203
+ # value to a new FileList directly.
204
+ if file_paths.empty?
205
+ fn = <<~JAVASCRIPT
206
+ (element) => {
207
+ element.files = new DataTransfer().files;
208
+
209
+ // Dispatch events for this case because it should behave akin to a user action.
210
+ element.dispatchEvent(new Event('input', { bubbles: true }));
211
+ element.dispatchEvent(new Event('change', { bubbles: true }));
212
+ }
213
+ JAVASCRIPT
214
+ await this.evaluate(fn)
215
+ else
216
+ @remote_object.set_file_input_files(@client, file_paths, backend_node_id)
217
+ end
218
+ end
219
+
220
+ def tap(&block)
221
+ return super(&block) if block
219
222
 
220
- def tap
221
223
  scroll_into_view_if_needed
222
224
  point = clickable_point
223
225
  @page.touchscreen.tap(point.x, point.y)
224
226
  end
225
227
 
228
+ async def async_tap
229
+ tap
230
+ end
226
231
 
227
232
  def focus
228
233
  evaluate('element => element.focus()')
@@ -393,6 +398,14 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
393
398
  result
394
399
  end
395
400
 
401
+ # `$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
402
+ # @param selector [String]
403
+ # @param page_function [String]
404
+ # @return [Object]
405
+ async def async_Seval(selector, page_function, *args)
406
+ Seval(selector, page_function, *args)
407
+ end
408
+
396
409
  # `$$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
397
410
  # @param selector [String]
398
411
  # @param page_function [String]
@@ -408,6 +421,14 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
408
421
  result
409
422
  end
410
423
 
424
+ # `$$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
425
+ # @param selector [String]
426
+ # @param page_function [String]
427
+ # @return [Object]
428
+ async def async_SSeval(selector, page_function, *args)
429
+ SSeval(selector, page_function, *args)
430
+ end
431
+
411
432
  # `$x()` in JavaScript. $ is not allowed to use as a method name in Ruby.
412
433
  # @param expression [String]
413
434
  # @return [Array<ElementHandle>]
@@ -216,6 +216,19 @@ class Puppeteer::ExecutionContext
216
216
  # return createJSHandle(this, response.objects);
217
217
  # }
218
218
 
219
+ # @param backend_node_id [Integer]
220
+ # @return [Puppeteer::ElementHandle]
221
+ def adopt_backend_node_id(backend_node_id)
222
+ response = @client.send_message('DOM.resolveNode',
223
+ backendNodeId: backend_node_id,
224
+ executionContextId: @context_id,
225
+ )
226
+ Puppeteer::JSHandle.create(
227
+ context: self,
228
+ remote_object: Puppeteer::RemoteObject.new(response["object"]),
229
+ )
230
+ end
231
+
219
232
  # @param element_handle [Puppeteer::ElementHandle]
220
233
  # @return [Puppeteer::ElementHandle]
221
234
  def adopt_element_handle(element_handle)
@@ -0,0 +1,29 @@
1
+ class Puppeteer::FileChooser
2
+ # @param element [Puppeteer::ElementHandle]
3
+ # @param event [Hash]
4
+ def initialize(element, event)
5
+ @element = element
6
+ @multiple = event['mode'] != 'selectSingle'
7
+ @handled = false
8
+ end
9
+
10
+ def multiple?
11
+ @multiple
12
+ end
13
+
14
+ # @param file_paths [Array<String>]
15
+ def accept(file_paths)
16
+ if @handled
17
+ raise 'Cannot accept FileChooser which is already handled!'
18
+ end
19
+ @handled = true
20
+ @element.upload_file(*file_paths)
21
+ end
22
+
23
+ def cancel
24
+ if @handled
25
+ raise 'Cannot cancel FileChooser which is already handled!'
26
+ end
27
+ @handled = true
28
+ end
29
+ end
@@ -285,8 +285,6 @@ class Puppeteer::FrameManager
285
285
  frame.navigated_within_document(url)
286
286
  emit_event 'Events.FrameManager.FrameNavigatedWithinDocument', frame
287
287
  emit_event 'Events.FrameManager.FrameNavigated', frame
288
- handle_frame_manager_frame_navigated_within_document(frame)
289
- handle_frame_manager_frame_navigated(frame)
290
288
  end
291
289
 
292
290
  # @param frame_id [String]
@@ -149,8 +149,54 @@ module Puppeteer::Launcher
149
149
 
150
150
  # @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport})} options
151
151
  # @return {!Promise<!Browser>}
152
- def connect(options)
153
- raise NotImplementedError.new('Puppeteer.connect is not implemented yet')
152
+ def connect(options = {})
153
+ @browser_options = BrowserOptions.new(options)
154
+ browser_ws_endpoint = options[:browser_ws_endpoint]
155
+ browser_url = options[:browser_url]
156
+ transport = options[:transport]
157
+
158
+ connection =
159
+ if browser_ws_endpoint && browser_url.nil? && transport.nil?
160
+ connect_with_browser_ws_endpoint(browser_ws_endpoint)
161
+ elsif browser_ws_endpoint.nil? && browser_url && transport.nil?
162
+ connect_with_browser_url(browser_url)
163
+ elsif browser_ws_endpoint.nil? && browser_url.nil? && transport
164
+ connect_with_transport(transport)
165
+ else
166
+ raise ArgumentError.new("Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect")
167
+ end
168
+
169
+ result = connection.send_message('Target.getBrowserContexts')
170
+ browser_context_ids = result['browserContextIds']
171
+
172
+ Puppeteer::Browser.create(
173
+ connection: connection,
174
+ context_ids: browser_context_ids,
175
+ ignore_https_errors: @browser_options.ignore_https_errors?,
176
+ default_viewport: @browser_options.default_viewport,
177
+ process: nil,
178
+ close_callback: -> { connection.send_message('Browser.close') },
179
+ )
180
+ end
181
+
182
+ # @return [Puppeteer::Connection]
183
+ private def connect_with_browser_ws_endpoint(browser_ws_endpoint)
184
+ transport = Puppeteer::WebSocketTransport.create(browser_ws_endpoint)
185
+ Puppeteer::Connection.new(browser_ws_endpoint, transport, @browser_options.slow_mo)
186
+ end
187
+
188
+ # @return [Puppeteer::Connection]
189
+ private def connect_with_browser_url(browser_url)
190
+ raise NotImplementedError.new('Puppeteer#connect with browserUrl is not implemented yet.')
191
+ # const connectionURL = await getWSEndpoint(browserURL);
192
+ # const connectionTransport = await WebSocketTransport.create(
193
+ # connectionURL
194
+ # );
195
+ end
196
+
197
+ # @return [Puppeteer::Connection]
198
+ private def connect_with_transport(transport)
199
+ Puppeteer::Connection.new('', transport, @browser_options.slow_mo)
154
200
  end
155
201
 
156
202
  # @return {string}
@@ -88,8 +88,8 @@ class Puppeteer::Page
88
88
  network_manager.on_event 'Events.NetworkManager.RequestFinished' do |event|
89
89
  emit_event 'Events.Page.RequestFinished', event
90
90
  end
91
- # this._fileChooserInterceptionIsDisabled = false;
92
- # this._fileChooserInterceptors = new Set();
91
+ @file_chooser_interception_is_disabled = false
92
+ @file_chooser_interceptors = Set.new
93
93
 
94
94
  @client.on_event 'Page.domContentEventFired' do |event|
95
95
  emit_event 'Events.Page.DOMContentLoaded'
@@ -106,7 +106,9 @@ class Puppeteer::Page
106
106
  @client.on_event 'Log.entryAdded' do |event|
107
107
  handle_log_entry_added(event)
108
108
  end
109
- # client.on('Page.fileChooserOpened', event => this._onFileChooser(event));
109
+ @client.on_event 'Page.fileChooserOpened' do |event|
110
+ handle_file_chooser(event)
111
+ end
110
112
  @target.on_close do
111
113
  emit_event 'Events.Page.Close'
112
114
  @closed = true
@@ -122,41 +124,53 @@ class Puppeteer::Page
122
124
  )
123
125
  end
124
126
 
125
- # /**
126
- # * @param {!Protocol.Page.fileChooserOpenedPayload} event
127
- # */
128
- # async _onFileChooser(event) {
129
- # if (!this._fileChooserInterceptors.size)
130
- # return;
131
- # const frame = this._frameManager.frame(event.frameId);
132
- # const context = await frame.executionContext();
133
- # const element = await context._adoptBackendNodeId(event.backendNodeId);
134
- # const interceptors = Array.from(this._fileChooserInterceptors);
135
- # this._fileChooserInterceptors.clear();
136
- # const fileChooser = new FileChooser(this._client, element, event);
137
- # for (const interceptor of interceptors)
138
- # interceptor.call(null, fileChooser);
139
- # }
127
+ def handle_file_chooser(event)
128
+ return if @file_chooser_interceptors.empty?
129
+
130
+ frame = @frame_manager.frame(event['frameId'])
131
+ context = frame.execution_context
132
+ element = context.adopt_backend_node_id(event['backendNodeId'])
133
+ interceptors = @file_chooser_interceptors.to_a
134
+ @file_chooser_interceptors.clear
135
+ file_chooser = Puppeteer::FileChooser.new(element, event)
136
+ interceptors.each do |promise|
137
+ promise.fulfill(file_chooser)
138
+ end
139
+ end
140
140
 
141
- # /**
142
- # * @param {!{timeout?: number}=} options
143
- # * @return !Promise<!FileChooser>}
144
- # */
145
- # async waitForFileChooser(options = {}) {
146
- # if (!this._fileChooserInterceptors.size)
147
- # await this._client.send('Page.setInterceptFileChooserDialog', {enabled: true});
141
+ class FileChooserTimeoutError < StandardError
142
+ def initialize(timeout:)
143
+ super("waiting for filechooser failed: timeout #{timeout}ms exceeded")
144
+ end
145
+ end
148
146
 
149
- # const {
150
- # timeout = this._timeoutSettings.timeout(),
151
- # } = options;
152
- # let callback;
153
- # const promise = new Promise(x => callback = x);
154
- # this._fileChooserInterceptors.add(callback);
155
- # return helper.waitWithTimeout(promise, 'waiting for file chooser', timeout).catch(e => {
156
- # this._fileChooserInterceptors.delete(callback);
157
- # throw e;
158
- # });
159
- # }
147
+ # @param timeout [Integer]
148
+ # @return [Puppeteer::FileChooser]
149
+ def wait_for_file_chooser(timeout: nil)
150
+ if @file_chooser_interceptors.empty?
151
+ @client.send_message('Page.setInterceptFileChooserDialog', enabled: true)
152
+ end
153
+
154
+ option_timeout = timeout || @timeout_settings.timeout
155
+ promise = resolvable_future
156
+ @file_chooser_interceptors << promise
157
+
158
+ begin
159
+ Timeout.timeout(option_timeout / 1000.0) do
160
+ promise.value!
161
+ end
162
+ rescue Timeout::Error
163
+ raise FileChooserTimeoutError.new(timeout: option_timeout)
164
+ ensure
165
+ @file_chooser_interceptors.delete(promise)
166
+ end
167
+ end
168
+
169
+ # @param timeout [Integer]
170
+ # @return [Future<Puppeteer::FileChooser>]
171
+ async def async_wait_for_file_chooser(timeout: nil)
172
+ wait_for_file_chooser(timeout: timeout)
173
+ end
160
174
 
161
175
 
162
176
  # /**
@@ -275,23 +289,37 @@ class Puppeteer::Page
275
289
  end
276
290
 
277
291
  # `$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
278
- # @param {string} selector
279
- # @param {Function|string} pageFunction
280
- # @param {!Array<*>} args
281
- # @return {!Promise<(!Object|undefined)>}
292
+ # @param selector [String]
293
+ # @param page_function [String]
294
+ # @return [Object]
282
295
  def Seval(selector, page_function, *args)
283
296
  main_frame.Seval(selector, page_function, *args)
284
297
  end
285
298
 
299
+ # `$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
300
+ # @param selector [String]
301
+ # @param page_function [String]
302
+ # @return [Future]
303
+ async def async_Seval(selector, page_function, *args)
304
+ Seval(selector, page_function, *args)
305
+ end
306
+
286
307
  # `$$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
287
- # @param {string} selector
288
- # @param {Function|string} pageFunction
289
- # @param {!Array<*>} args
290
- # @return {!Promise<(!Object|undefined)>}
308
+ # @param selector [String]
309
+ # @param page_function [String]
310
+ # @return [Object]
291
311
  def SSeval(selector, page_function, *args)
292
312
  main_frame.SSeval(selector, page_function, *args)
293
313
  end
294
314
 
315
+ # `$$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
316
+ # @param selector [String]
317
+ # @param page_function [String]
318
+ # @return [Future]
319
+ async def async_SSeval(selector, page_function, *args)
320
+ SSeval(selector, page_function, *args)
321
+ end
322
+
295
323
  # `$x()` in JavaScript. $ is not allowed to use as a method name in Ruby.
296
324
  # @param {string} expression
297
325
  # @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
@@ -610,14 +638,14 @@ class Puppeteer::Page
610
638
  main_frame.goto(url, referer: referer, timeout: timeout, wait_until: wait_until)
611
639
  end
612
640
 
613
- # @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
614
- # @return {!Promise<?Puppeteer.Response>}
641
+ # @param timeout [number|nil]
642
+ # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
643
+ # @return [Puppeteer::Response]
615
644
  def reload(timeout: nil, wait_until: nil)
616
- # const [response] = await Promise.all([
617
- # this.waitForNavigation(options),
618
- # this._client.send('Page.reload')
619
- # ]);
620
- # return response;
645
+ await_all(
646
+ async_wait_for_navigation(timeout: timeout, wait_until: wait_until),
647
+ @client.async_send_message('Page.reload'),
648
+ ).first
621
649
  end
622
650
 
623
651
  # @param timeout [number|nil]
@@ -968,11 +996,16 @@ class Puppeteer::Page
968
996
  main_frame.select(selector, *values)
969
997
  end
970
998
 
971
- # @param {string} selector
999
+ # @param selector [String]
972
1000
  def tap(selector)
973
1001
  main_frame.tap(selector)
974
1002
  end
975
1003
 
1004
+ # @param selector [String]
1005
+ async def async_tap(selector)
1006
+ tap(selector)
1007
+ end
1008
+
976
1009
  # @param selector [String]
977
1010
  # @param text [String]
978
1011
  # @param delay [Number]