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.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/docs/Puppeteer.html +53 -43
- data/docs/Puppeteer/AsyncAwaitBehavior.html +1 -1
- data/docs/Puppeteer/Browser.html +1 -1
- data/docs/Puppeteer/BrowserContext.html +1 -1
- data/docs/Puppeteer/BrowserFetcher.html +1 -1
- data/docs/Puppeteer/BrowserRunner.html +1 -1
- data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +1 -1
- data/docs/Puppeteer/CDPSession.html +1 -1
- data/docs/Puppeteer/CDPSession/Error.html +1 -1
- data/docs/Puppeteer/ConcurrentRubyUtils.html +1 -1
- data/docs/Puppeteer/Connection.html +1 -1
- data/docs/Puppeteer/Connection/MessageCallback.html +1 -1
- data/docs/Puppeteer/Connection/ProtocolError.html +1 -1
- data/docs/Puppeteer/Connection/RequestDebugPrinter.html +1 -1
- data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +1 -1
- data/docs/Puppeteer/ConsoleMessage.html +1 -1
- data/docs/Puppeteer/ConsoleMessage/Location.html +1 -1
- data/docs/Puppeteer/DOMWorld.html +116 -19
- data/docs/Puppeteer/DOMWorld/DetachedError.html +1 -1
- data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +1 -1
- data/docs/Puppeteer/DebugPrint.html +1 -1
- data/docs/Puppeteer/Device.html +1 -1
- data/docs/Puppeteer/Devices.html +1 -1
- data/docs/Puppeteer/ElementHandle.html +565 -141
- data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +5 -5
- data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +5 -5
- data/docs/Puppeteer/ElementHandle/Point.html +21 -21
- data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +1 -1
- data/docs/Puppeteer/EmulationManager.html +1 -1
- data/docs/Puppeteer/EventCallbackable.html +1 -1
- data/docs/Puppeteer/EventCallbackable/EventListeners.html +1 -1
- data/docs/Puppeteer/ExecutionContext.html +114 -11
- data/docs/Puppeteer/ExecutionContext/EvaluationError.html +1 -1
- data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +1 -1
- data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +1 -1
- data/docs/Puppeteer/FileChooser.html +455 -0
- data/docs/Puppeteer/Frame.html +1 -1
- data/docs/Puppeteer/FrameManager.html +1 -1
- data/docs/Puppeteer/FrameManager/NavigationError.html +1 -1
- data/docs/Puppeteer/IfPresent.html +1 -1
- data/docs/Puppeteer/JSHandle.html +1 -1
- data/docs/Puppeteer/Keyboard.html +1 -1
- data/docs/Puppeteer/Keyboard/KeyDefinition.html +1 -1
- data/docs/Puppeteer/Keyboard/KeyDescription.html +1 -1
- data/docs/Puppeteer/Launcher.html +1 -1
- data/docs/Puppeteer/Launcher/Base.html +1 -1
- data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +1 -1
- data/docs/Puppeteer/Launcher/BrowserOptions.html +1 -1
- data/docs/Puppeteer/Launcher/Chrome.html +64 -23
- data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +1 -1
- data/docs/Puppeteer/Launcher/ChromeArgOptions.html +1 -1
- data/docs/Puppeteer/Launcher/LaunchOptions.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +1 -1
- data/docs/Puppeteer/Mouse.html +1 -1
- data/docs/Puppeteer/Mouse/Button.html +1 -1
- data/docs/Puppeteer/NetworkManager.html +1 -1
- data/docs/Puppeteer/NetworkManager/Credentials.html +1 -1
- data/docs/Puppeteer/Page.html +841 -349
- data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
- data/docs/Puppeteer/Page/ScreenshotOptions.html +1 -1
- data/docs/Puppeteer/Page/ScriptTag.html +24 -24
- data/docs/Puppeteer/Page/StyleTag.html +19 -19
- data/docs/Puppeteer/Page/TargetCrashedError.html +1 -1
- data/docs/Puppeteer/RemoteObject.html +68 -3
- data/docs/Puppeteer/Target.html +1 -1
- data/docs/Puppeteer/Target/InitializeFailure.html +1 -1
- data/docs/Puppeteer/Target/TargetInfo.html +1 -1
- data/docs/Puppeteer/TimeoutError.html +1 -1
- data/docs/Puppeteer/TimeoutSettings.html +1 -1
- data/docs/Puppeteer/TouchScreen.html +1 -1
- data/docs/Puppeteer/Viewport.html +1 -1
- data/docs/Puppeteer/WaitTask.html +1 -1
- data/docs/Puppeteer/WaitTask/TerminatedError.html +1 -1
- data/docs/Puppeteer/WaitTask/TimeoutError.html +1 -1
- data/docs/Puppeteer/WebSocket.html +1 -1
- data/docs/Puppeteer/WebSocket/DriverImpl.html +1 -1
- data/docs/Puppeteer/WebSocketTransport.html +1 -1
- data/docs/Puppeteer/WebSocktTransportError.html +1 -1
- data/docs/_index.html +19 -5
- data/docs/class_list.html +1 -1
- data/docs/file.README.html +5 -3
- data/docs/index.html +5 -3
- data/docs/method_list.html +644 -508
- data/docs/top-level-namespace.html +1 -1
- data/lib/puppeteer.rb +7 -1
- data/lib/puppeteer/browser_runner.rb +1 -1
- data/lib/puppeteer/dom_world.rb +9 -12
- data/lib/puppeteer/element_handle.rb +82 -61
- data/lib/puppeteer/execution_context.rb +13 -0
- data/lib/puppeteer/file_chooser.rb +29 -0
- data/lib/puppeteer/frame_manager.rb +0 -2
- data/lib/puppeteer/launcher/chrome.rb +48 -2
- data/lib/puppeteer/page.rb +85 -52
- data/lib/puppeteer/remote_object.rb +6 -1
- data/lib/puppeteer/version.rb +1 -1
- metadata +5 -2
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
</div>
|
|
117
117
|
|
|
118
118
|
<div id="footer">
|
|
119
|
-
Generated on
|
|
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|
|
data/lib/puppeteer/dom_world.rb
CHANGED
|
@@ -355,18 +355,15 @@ class Puppeteer::DOMWorld
|
|
|
355
355
|
# await handle.dispose();
|
|
356
356
|
# }
|
|
357
357
|
|
|
358
|
-
#
|
|
359
|
-
#
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
#
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
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}
|
data/lib/puppeteer/page.rb
CHANGED
|
@@ -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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
#
|
|
150
|
-
#
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
|
279
|
-
# @param
|
|
280
|
-
# @
|
|
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
|
|
288
|
-
# @param
|
|
289
|
-
# @
|
|
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
|
|
614
|
-
# @
|
|
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
|
-
|
|
617
|
-
|
|
618
|
-
|
|
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
|
|
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]
|