puppeteer-ruby 0.0.13 → 0.0.18
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/.circleci/config.yml +2 -14
- data/.github/workflows/docs.yml +45 -0
- data/.github/workflows/reviewdog.yml +15 -0
- data/.rubocop.yml +39 -3
- data/README.md +54 -1
- data/lib/puppeteer.rb +10 -2
- data/lib/puppeteer/browser.rb +53 -34
- data/lib/puppeteer/browser_context.rb +35 -5
- data/lib/puppeteer/cdp_session.rb +3 -19
- data/lib/puppeteer/concurrent_ruby_utils.rb +6 -0
- data/lib/puppeteer/connection.rb +9 -16
- data/lib/puppeteer/debug_print.rb +1 -1
- data/lib/puppeteer/define_async_method.rb +23 -0
- data/lib/puppeteer/dom_world.rb +84 -73
- data/lib/puppeteer/element_handle.rb +46 -63
- data/lib/puppeteer/emulation_manager.rb +2 -6
- data/lib/puppeteer/env.rb +18 -0
- data/lib/puppeteer/execution_context.rb +1 -6
- data/lib/puppeteer/frame.rb +46 -46
- data/lib/puppeteer/frame_manager.rb +7 -25
- data/lib/puppeteer/js_handle.rb +39 -38
- data/lib/puppeteer/keyboard.rb +9 -29
- data/lib/puppeteer/mouse.rb +20 -24
- data/lib/puppeteer/network_manager.rb +163 -5
- data/lib/puppeteer/page.rb +221 -181
- data/lib/puppeteer/page/pdf_options.rb +166 -0
- data/lib/puppeteer/remote_object.rb +18 -5
- data/lib/puppeteer/request.rb +330 -0
- data/lib/puppeteer/response.rb +113 -0
- data/lib/puppeteer/touch_screen.rb +2 -7
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +3 -5
- data/lib/puppeteer/web_socket.rb +7 -0
- data/puppeteer-ruby.gemspec +2 -1
- metadata +25 -103
- data/docs/Puppeteer.html +0 -2338
- data/docs/Puppeteer/AsyncAwaitBehavior.html +0 -105
- data/docs/Puppeteer/Browser.html +0 -2258
- data/docs/Puppeteer/BrowserContext.html +0 -809
- data/docs/Puppeteer/BrowserFetcher.html +0 -214
- data/docs/Puppeteer/BrowserRunner.html +0 -914
- data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +0 -477
- data/docs/Puppeteer/CDPSession.html +0 -813
- data/docs/Puppeteer/CDPSession/Error.html +0 -124
- data/docs/Puppeteer/ConcurrentRubyUtils.html +0 -438
- data/docs/Puppeteer/Connection.html +0 -964
- data/docs/Puppeteer/Connection/MessageCallback.html +0 -434
- data/docs/Puppeteer/Connection/ProtocolError.html +0 -216
- data/docs/Puppeteer/Connection/RequestDebugPrinter.html +0 -217
- data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +0 -244
- data/docs/Puppeteer/ConsoleMessage.html +0 -565
- data/docs/Puppeteer/ConsoleMessage/Location.html +0 -433
- data/docs/Puppeteer/DOMWorld.html +0 -2293
- data/docs/Puppeteer/DOMWorld/DetachedError.html +0 -124
- data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +0 -124
- data/docs/Puppeteer/DebugPrint.html +0 -233
- data/docs/Puppeteer/Device.html +0 -470
- data/docs/Puppeteer/Devices.html +0 -139
- data/docs/Puppeteer/ElementHandle.html +0 -2542
- data/docs/Puppeteer/ElementHandle/BoundingBox.html +0 -507
- data/docs/Puppeteer/ElementHandle/BoxModel.html +0 -404
- data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +0 -206
- data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +0 -206
- data/docs/Puppeteer/ElementHandle/Point.html +0 -492
- data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +0 -124
- data/docs/Puppeteer/EmulationManager.html +0 -454
- data/docs/Puppeteer/EventCallbackable.html +0 -499
- data/docs/Puppeteer/EventCallbackable/EventListeners.html +0 -435
- data/docs/Puppeteer/ExecutionContext.html +0 -998
- data/docs/Puppeteer/ExecutionContext/EvaluationError.html +0 -124
- data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +0 -357
- data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +0 -389
- data/docs/Puppeteer/FileChooser.html +0 -455
- data/docs/Puppeteer/Frame.html +0 -3835
- data/docs/Puppeteer/FrameManager.html +0 -2410
- data/docs/Puppeteer/FrameManager/NavigationError.html +0 -124
- data/docs/Puppeteer/IfPresent.html +0 -222
- data/docs/Puppeteer/JSHandle.html +0 -1352
- data/docs/Puppeteer/Keyboard.html +0 -1557
- data/docs/Puppeteer/Keyboard/KeyDefinition.html +0 -831
- data/docs/Puppeteer/Keyboard/KeyDescription.html +0 -603
- data/docs/Puppeteer/Launcher.html +0 -237
- data/docs/Puppeteer/Launcher/Base.html +0 -385
- data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +0 -124
- data/docs/Puppeteer/Launcher/BrowserOptions.html +0 -441
- data/docs/Puppeteer/Launcher/Chrome.html +0 -674
- data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +0 -382
- data/docs/Puppeteer/Launcher/ChromeArgOptions.html +0 -531
- data/docs/Puppeteer/Launcher/LaunchOptions.html +0 -893
- data/docs/Puppeteer/LifecycleWatcher.html +0 -834
- data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +0 -363
- data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +0 -206
- data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +0 -124
- data/docs/Puppeteer/Mouse.html +0 -1095
- data/docs/Puppeteer/Mouse/Button.html +0 -136
- data/docs/Puppeteer/NetworkManager.html +0 -901
- data/docs/Puppeteer/NetworkManager/Credentials.html +0 -385
- data/docs/Puppeteer/Page.html +0 -6173
- data/docs/Puppeteer/Page/FileChooserTimeoutError.html +0 -206
- data/docs/Puppeteer/Page/ScreenshotOptions.html +0 -845
- data/docs/Puppeteer/Page/ScriptTag.html +0 -555
- data/docs/Puppeteer/Page/StyleTag.html +0 -448
- data/docs/Puppeteer/Page/TargetCrashedError.html +0 -124
- data/docs/Puppeteer/RemoteObject.html +0 -1087
- data/docs/Puppeteer/Target.html +0 -1336
- data/docs/Puppeteer/Target/InitializeFailure.html +0 -124
- data/docs/Puppeteer/Target/TargetInfo.html +0 -729
- data/docs/Puppeteer/TimeoutError.html +0 -135
- data/docs/Puppeteer/TimeoutSettings.html +0 -496
- data/docs/Puppeteer/TouchScreen.html +0 -464
- data/docs/Puppeteer/Viewport.html +0 -837
- data/docs/Puppeteer/WaitTask.html +0 -637
- data/docs/Puppeteer/WaitTask/TerminatedError.html +0 -124
- data/docs/Puppeteer/WaitTask/TimeoutError.html +0 -206
- data/docs/Puppeteer/WebSocket.html +0 -673
- data/docs/Puppeteer/WebSocket/DriverImpl.html +0 -412
- data/docs/Puppeteer/WebSocket/TransportError.html +0 -124
- data/docs/Puppeteer/WebSocketTransport.html +0 -600
- data/docs/Puppeteer/WebSocktTransportError.html +0 -124
- data/docs/_index.html +0 -816
- data/docs/class_list.html +0 -51
- data/docs/css/common.css +0 -1
- data/docs/css/full_list.css +0 -58
- data/docs/css/style.css +0 -496
- data/docs/file.README.html +0 -125
- data/docs/file_list.html +0 -56
- data/docs/frames.html +0 -17
- data/docs/index.html +0 -125
- data/docs/js/app.js +0 -314
- data/docs/js/full_list.js +0 -216
- data/docs/js/jquery.js +0 -4
- data/docs/method_list.html +0 -4123
- data/docs/top-level-namespace.html +0 -126
- data/lib/puppeteer/async_await_behavior.rb +0 -38
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
class Puppeteer::BrowserContext
|
|
2
2
|
include Puppeteer::EventCallbackable
|
|
3
|
+
using Puppeteer::DefineAsyncMethod
|
|
3
4
|
|
|
4
5
|
# @param {!Puppeteer.Connection} connection
|
|
5
6
|
# @param {!Browser} browser
|
|
@@ -10,14 +11,38 @@ class Puppeteer::BrowserContext
|
|
|
10
11
|
@id = context_id
|
|
11
12
|
end
|
|
12
13
|
|
|
14
|
+
EVENT_MAPPINGS = {
|
|
15
|
+
disconnected: 'Events.BrowserContext.Disconnected',
|
|
16
|
+
targetcreated: 'Events.BrowserContext.TargetCreated',
|
|
17
|
+
targetchanged: 'Events.BrowserContext.TargetChanged',
|
|
18
|
+
targetdestroyed: 'Events.BrowserContext.TargetDestroyed',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# @param event_name [Symbol] either of :disconnected, :targetcreated, :targetchanged, :targetdestroyed
|
|
22
|
+
def on(event_name, &block)
|
|
23
|
+
unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
|
|
24
|
+
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
add_event_listener(EVENT_MAPPINGS[event_name.to_sym], &block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param event_name [Symbol]
|
|
31
|
+
def once(event_name, &block)
|
|
32
|
+
unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
|
|
33
|
+
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
observe_first(EVENT_MAPPINGS[event_name.to_sym], &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
13
39
|
# @return {!Array<!Target>} target
|
|
14
40
|
def targets
|
|
15
41
|
@browser.targets.select { |target| target.browser_context == self }
|
|
16
42
|
end
|
|
17
43
|
|
|
18
|
-
# @param
|
|
19
|
-
# @
|
|
20
|
-
# @return {!Promise<!Target>}
|
|
44
|
+
# @param predicate [Proc(Puppeteer::Target -> Boolean)]
|
|
45
|
+
# @return [Puppeteer::Target]
|
|
21
46
|
def wait_for_target(predicate:, timeout: nil)
|
|
22
47
|
@browser.wait_for_target(
|
|
23
48
|
predicate: ->(target) { target.browser_context == self && predicate.call(target) },
|
|
@@ -25,13 +50,18 @@ class Puppeteer::BrowserContext
|
|
|
25
50
|
)
|
|
26
51
|
end
|
|
27
52
|
|
|
53
|
+
# @!method async_wait_for_target(predicate:, timeout: nil)
|
|
54
|
+
#
|
|
55
|
+
# @param predicate [Proc(Puppeteer::Target -> Boolean)]
|
|
56
|
+
define_async_method :async_wait_for_target
|
|
57
|
+
|
|
28
58
|
# @return {!Promise<!Array<!Puppeteer.Page>>}
|
|
29
59
|
def pages
|
|
30
60
|
targets.select { |target| target.type == 'page' }.map(&:page).reject { |page| !page }
|
|
31
61
|
end
|
|
32
62
|
|
|
33
63
|
def incognito?
|
|
34
|
-
|
|
64
|
+
!!@id
|
|
35
65
|
end
|
|
36
66
|
|
|
37
67
|
# /**
|
|
@@ -82,7 +112,7 @@ class Puppeteer::BrowserContext
|
|
|
82
112
|
end
|
|
83
113
|
|
|
84
114
|
def close
|
|
85
|
-
|
|
115
|
+
unless @id
|
|
86
116
|
raise 'Non-incognito profiles cannot be closed!'
|
|
87
117
|
end
|
|
88
118
|
@browser.dispose_context(@id)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class Puppeteer::CDPSession
|
|
2
2
|
include Puppeteer::DebugPrint
|
|
3
3
|
include Puppeteer::EventCallbackable
|
|
4
|
-
using Puppeteer::
|
|
4
|
+
using Puppeteer::DefineAsyncMethod
|
|
5
5
|
|
|
6
6
|
class Error < StandardError; end
|
|
7
7
|
|
|
@@ -13,7 +13,6 @@ class Puppeteer::CDPSession
|
|
|
13
13
|
@connection = connection
|
|
14
14
|
@target_type = target_type
|
|
15
15
|
@session_id = session_id
|
|
16
|
-
@pending_messages = {}
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
attr_reader :connection
|
|
@@ -35,12 +34,7 @@ class Puppeteer::CDPSession
|
|
|
35
34
|
id = @connection.raw_send(message: { sessionId: @session_id, method: method, params: params })
|
|
36
35
|
promise = resolvable_future
|
|
37
36
|
callback = Puppeteer::Connection::MessageCallback.new(method: method, promise: promise)
|
|
38
|
-
|
|
39
|
-
debug_puts "Pending message (id: #{id}) is handled"
|
|
40
|
-
callback_with_message(callback, pending_message)
|
|
41
|
-
else
|
|
42
|
-
@callbacks[id] = callback
|
|
43
|
-
end
|
|
37
|
+
@callbacks[id] = callback
|
|
44
38
|
promise
|
|
45
39
|
end
|
|
46
40
|
|
|
@@ -50,17 +44,7 @@ class Puppeteer::CDPSession
|
|
|
50
44
|
if callback = @callbacks.delete(message['id'])
|
|
51
45
|
callback_with_message(callback, message)
|
|
52
46
|
else
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# RECV is often notified before SEND.
|
|
56
|
-
# Wait about 10 frames before throwing an error.
|
|
57
|
-
message_id = message['id']
|
|
58
|
-
@pending_messages[message_id] = message
|
|
59
|
-
Concurrent::Promises.schedule(0.16, message_id) do |id|
|
|
60
|
-
if @pending_messages.delete(id)
|
|
61
|
-
raise Error.new("unknown id: #{id}")
|
|
62
|
-
end
|
|
63
|
-
end
|
|
47
|
+
raise Error.new("unknown id: #{id}")
|
|
64
48
|
end
|
|
65
49
|
else
|
|
66
50
|
emit_event message['method'], message['params']
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# utility methods for Concurrent::Promises.
|
|
2
2
|
module Puppeteer::ConcurrentRubyUtils
|
|
3
|
+
# wait for all promises.
|
|
4
|
+
# REMARK: This method doesn't assure the order of calling.
|
|
5
|
+
# for example, await_all(async1, async2) calls calls2 -> calls1 often.
|
|
3
6
|
def await_all(*args)
|
|
4
7
|
if args.length == 1 && args[0].is_a?(Enumerable)
|
|
5
8
|
Concurrent::Promises.zip(*(args[0])).value!
|
|
@@ -8,6 +11,9 @@ module Puppeteer::ConcurrentRubyUtils
|
|
|
8
11
|
end
|
|
9
12
|
end
|
|
10
13
|
|
|
14
|
+
# wait for first promises.
|
|
15
|
+
# REMARK: This method doesn't assure the order of calling.
|
|
16
|
+
# for example, await_all(async1, async2) calls calls2 -> calls1 often.
|
|
11
17
|
def await_any(*args)
|
|
12
18
|
if args.length == 1 && args[0].is_a?(Enumerable)
|
|
13
19
|
Concurrent::Promises.any(*(args[0])).value!
|
data/lib/puppeteer/connection.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'json'
|
|
|
3
3
|
class Puppeteer::Connection
|
|
4
4
|
include Puppeteer::DebugPrint
|
|
5
5
|
include Puppeteer::EventCallbackable
|
|
6
|
-
using Puppeteer::
|
|
6
|
+
using Puppeteer::DefineAsyncMethod
|
|
7
7
|
|
|
8
8
|
class ProtocolError < StandardError
|
|
9
9
|
def initialize(method:, error_message:, error_data: nil)
|
|
@@ -49,13 +49,18 @@ class Puppeteer::Connection
|
|
|
49
49
|
async_handle_message(message)
|
|
50
50
|
end
|
|
51
51
|
@transport.on_close do |reason, code|
|
|
52
|
-
handle_close
|
|
52
|
+
handle_close
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
@sessions = {}
|
|
56
56
|
@closed = false
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
+
# used only in Browser#connected?
|
|
60
|
+
def closed?
|
|
61
|
+
@closed
|
|
62
|
+
end
|
|
63
|
+
|
|
59
64
|
private def sleep_before_handling_message(message)
|
|
60
65
|
# Puppeteer doesn't handle any Network monitoring responses.
|
|
61
66
|
# So we don't have to sleep.
|
|
@@ -210,9 +215,7 @@ class Puppeteer::Connection
|
|
|
210
215
|
end
|
|
211
216
|
end
|
|
212
217
|
|
|
213
|
-
private
|
|
214
|
-
handle_message(message)
|
|
215
|
-
end
|
|
218
|
+
private define_async_method :async_handle_message
|
|
216
219
|
|
|
217
220
|
private def handle_close
|
|
218
221
|
return if @closed
|
|
@@ -251,16 +254,6 @@ class Puppeteer::Connection
|
|
|
251
254
|
def create_session(target_info)
|
|
252
255
|
result = send_message('Target.attachToTarget', targetId: target_info.target_id, flatten: true)
|
|
253
256
|
session_id = result['sessionId']
|
|
254
|
-
|
|
255
|
-
# Target.attachedToTarget is often notified after the result of Target.attachToTarget.
|
|
256
|
-
# D, [2020-04-04T23:04:30.736311 #91875] DEBUG -- : RECV << {"id"=>2, "result"=>{"sessionId"=>"DA002F8A95B04710502CB40D8430B95A"}}
|
|
257
|
-
# D, [2020-04-04T23:04:30.736649 #91875] DEBUG -- : RECV << {"method"=>"Target.attachedToTarget", "params"=>{"sessionId"=>"DA002F8A95B04710502CB40D8430B95A", "targetInfo"=>{"targetId"=>"EBAB949A7DE63F12CB94268AD3A9976B", "type"=>"page", "title"=>"about:blank", "url"=>"about:blank", "attached"=>true, "browserContextId"=>"46D23767E9B79DD9E589101121F6DADD"}, "waitingForDebugger"=>false}}
|
|
258
|
-
# So we have to wait for "Target.attachedToTarget" a bit.
|
|
259
|
-
20.times do
|
|
260
|
-
if @sessions[session_id]
|
|
261
|
-
return @sessions[session_id]
|
|
262
|
-
end
|
|
263
|
-
sleep 0.1
|
|
264
|
-
end
|
|
257
|
+
@sessions[session_id]
|
|
265
258
|
end
|
|
266
259
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Puppeteer::DefineAsyncMethod
|
|
2
|
+
refine Class do
|
|
3
|
+
def define_async_method(async_method_name)
|
|
4
|
+
unless async_method_name.to_s.start_with?('async_')
|
|
5
|
+
raise ArgumentError.new('async method name should start with "async_"')
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
if method_defined?(async_method_name) || private_method_defined?(async_method_name)
|
|
9
|
+
raise ArgumentError.new("#{async_method_name} is already defined")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
original_method = instance_method(async_method_name[6..-1])
|
|
13
|
+
define_method(async_method_name) do |*args|
|
|
14
|
+
Concurrent::Promises.future do
|
|
15
|
+
original_method.bind(self).call(*args)
|
|
16
|
+
rescue => err
|
|
17
|
+
Logger.new(STDERR).warn(err)
|
|
18
|
+
raise err
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/puppeteer/dom_world.rb
CHANGED
|
@@ -2,7 +2,7 @@ require 'thread'
|
|
|
2
2
|
|
|
3
3
|
# https://github.com/puppeteer/puppeteer/blob/master/src/DOMWorld.js
|
|
4
4
|
class Puppeteer::DOMWorld
|
|
5
|
-
using Puppeteer::
|
|
5
|
+
using Puppeteer::DefineAsyncMethod
|
|
6
6
|
|
|
7
7
|
# @param {!Puppeteer.FrameManager} frameManager
|
|
8
8
|
# @param {!Puppeteer.Frame} frame
|
|
@@ -12,7 +12,6 @@ class Puppeteer::DOMWorld
|
|
|
12
12
|
@frame = frame
|
|
13
13
|
@timeout_settings = timeout_settings
|
|
14
14
|
@context_promise = resolvable_future
|
|
15
|
-
@pending_destroy = []
|
|
16
15
|
@wait_tasks = Set.new
|
|
17
16
|
@detached = false
|
|
18
17
|
end
|
|
@@ -24,22 +23,12 @@ class Puppeteer::DOMWorld
|
|
|
24
23
|
@wait_tasks
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
# @param
|
|
26
|
+
# @param context [Puppeteer::ExecutionContext]
|
|
28
27
|
def context=(context)
|
|
29
|
-
# D, [2020-04-12T22:45:03.938754 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextCreated", "params"=>{"context"=>{"id"=>3, "origin"=>"https://github.com", "name"=>"", "auxData"=>{"isDefault"=>true, "type"=>"default", "frameId"=>"3AD7F1E82BCBA88BFE31D03BC49FF6CB"}}}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
|
|
30
|
-
# D, [2020-04-12T22:45:03.938856 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextCreated", "params"=>{"context"=>{"id"=>4, "origin"=>"://", "name"=>"__puppeteer_utility_world__", "auxData"=>{"isDefault"=>false, "type"=>"isolated", "frameId"=>"3AD7F1E82BCBA88BFE31D03BC49FF6CB"}}}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
|
|
31
|
-
# D, [2020-04-12T22:45:03.938960 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextDestroyed", "params"=>{"executionContextId"=>1}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
|
|
32
|
-
# D, [2020-04-12T22:45:03.939110 #46154] DEBUG -- : RECV << {"method"=>"Page.frameNavigated", "params"=>{"frame"=>{"id"=>"3AD7F1E82BCBA88BFE31D03BC49FF6CB", "loaderId"=>"301B349884E582986C502CBE020966DF", "url"=>"https://github.com/", "securityOrigin"=>"https://github.com", "mimeType"=>"text/html"}}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
|
|
33
|
-
# D, [2020-04-12T22:45:03.939793 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextDestroyed", "params"=>{"executionContextId"=>2}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
|
|
34
|
-
# executionContextDestroyed is often notified after executionContextCreated.
|
|
35
|
-
|
|
36
28
|
if context
|
|
37
|
-
|
|
38
|
-
@
|
|
39
|
-
@document = nil
|
|
40
|
-
@context_promise = resolvable_future
|
|
29
|
+
unless @context_promise.resolved?
|
|
30
|
+
@context_promise.fulfill(context)
|
|
41
31
|
end
|
|
42
|
-
@context_promise.fulfill(context)
|
|
43
32
|
@wait_tasks.each(&:async_rerun)
|
|
44
33
|
else
|
|
45
34
|
raise ArgumentError.new("context should now be nil. Use #delete_context for clearing document.")
|
|
@@ -47,12 +36,8 @@ class Puppeteer::DOMWorld
|
|
|
47
36
|
end
|
|
48
37
|
|
|
49
38
|
def delete_context(execution_context_id)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
else
|
|
53
|
-
@document = nil
|
|
54
|
-
@context_promise = resolvable_future
|
|
55
|
-
end
|
|
39
|
+
@document = nil
|
|
40
|
+
@context_promise = resolvable_future
|
|
56
41
|
end
|
|
57
42
|
|
|
58
43
|
def has_context?
|
|
@@ -147,45 +132,48 @@ class Puppeteer::DOMWorld
|
|
|
147
132
|
document.SS(selector)
|
|
148
133
|
end
|
|
149
134
|
|
|
150
|
-
#
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
135
|
+
# @return [String]
|
|
136
|
+
def content
|
|
137
|
+
evaluate <<-JAVASCRIPT
|
|
138
|
+
() => {
|
|
139
|
+
let retVal = '';
|
|
140
|
+
if (document.doctype)
|
|
141
|
+
retVal = new XMLSerializer().serializeToString(document.doctype);
|
|
142
|
+
if (document.documentElement)
|
|
143
|
+
retVal += document.documentElement.outerHTML;
|
|
144
|
+
return retVal;
|
|
145
|
+
}
|
|
146
|
+
JAVASCRIPT
|
|
147
|
+
end
|
|
163
148
|
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
149
|
+
# @param html [String]
|
|
150
|
+
# @param timeout [Integer]
|
|
151
|
+
# @param wait_until [String|Array<String>]
|
|
152
|
+
def set_content(html, timeout: nil, wait_until: nil)
|
|
153
|
+
option_wait_until = [wait_until || 'load'].flatten
|
|
154
|
+
option_timeout = @timeout_settings.navigation_timeout
|
|
155
|
+
|
|
156
|
+
# We rely upon the fact that document.open() will reset frame lifecycle with "init"
|
|
157
|
+
# lifecycle event. @see https://crrev.com/608658
|
|
158
|
+
js = <<-JAVASCRIPT
|
|
159
|
+
(html) => {
|
|
160
|
+
document.open();
|
|
161
|
+
document.write(html);
|
|
162
|
+
document.close();
|
|
163
|
+
}
|
|
164
|
+
JAVASCRIPT
|
|
165
|
+
evaluate(js, html)
|
|
166
|
+
|
|
167
|
+
watcher = Puppeteer::LifecycleWatcher.new(@frame_manager, @frame, option_wait_until, option_timeout)
|
|
168
|
+
begin
|
|
169
|
+
await_any(
|
|
170
|
+
watcher.timeout_or_termination_promise,
|
|
171
|
+
watcher.lifecycle_promise,
|
|
172
|
+
)
|
|
173
|
+
ensure
|
|
174
|
+
watcher.dispose
|
|
175
|
+
end
|
|
176
|
+
end
|
|
189
177
|
|
|
190
178
|
# /**
|
|
191
179
|
# * @param {!{url?: string, path?: string, content?: string, type?: string}} options
|
|
@@ -326,25 +314,28 @@ class Puppeteer::DOMWorld
|
|
|
326
314
|
# }
|
|
327
315
|
# }
|
|
328
316
|
|
|
317
|
+
class ElementNotFoundError < StandardError
|
|
318
|
+
def initialize(selector)
|
|
319
|
+
super("No node found for selector: #{selector}")
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
329
323
|
# @param selector [String]
|
|
330
324
|
# @param delay [Number]
|
|
331
325
|
# @param button [String] "left"|"right"|"middle"
|
|
332
326
|
# @param click_count [Number]
|
|
333
327
|
def click(selector, delay: nil, button: nil, click_count: nil)
|
|
334
|
-
handle = S(selector)
|
|
328
|
+
handle = S(selector) or raise ElementNotFoundError.new(selector)
|
|
335
329
|
handle.click(delay: delay, button: button, click_count: click_count)
|
|
336
330
|
handle.dispose
|
|
337
331
|
end
|
|
338
332
|
|
|
339
|
-
#
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
# await handle.focus();
|
|
346
|
-
# await handle.dispose();
|
|
347
|
-
# }
|
|
333
|
+
# @param selector [String]
|
|
334
|
+
def focus(selector)
|
|
335
|
+
handle = S(selector) or raise ElementNotFoundError.new(selector)
|
|
336
|
+
handle.focus
|
|
337
|
+
handle.dispose
|
|
338
|
+
end
|
|
348
339
|
|
|
349
340
|
# /**
|
|
350
341
|
# * @param {string} selector
|
|
@@ -359,7 +350,7 @@ class Puppeteer::DOMWorld
|
|
|
359
350
|
# @param selector [String]
|
|
360
351
|
# @return [Array<String>]
|
|
361
352
|
def select(selector, *values)
|
|
362
|
-
handle = S(selector)
|
|
353
|
+
handle = S(selector) or raise ElementNotFoundError.new(selector)
|
|
363
354
|
result = handle.select(*values)
|
|
364
355
|
handle.dispose
|
|
365
356
|
|
|
@@ -368,7 +359,7 @@ class Puppeteer::DOMWorld
|
|
|
368
359
|
|
|
369
360
|
# @param selector [String]
|
|
370
361
|
def tap(selector)
|
|
371
|
-
handle = S(selector)
|
|
362
|
+
handle = S(selector) or raise ElementNotFoundError.new(selector)
|
|
372
363
|
handle.tap
|
|
373
364
|
handle.dispose
|
|
374
365
|
end
|
|
@@ -377,7 +368,7 @@ class Puppeteer::DOMWorld
|
|
|
377
368
|
# @param text [String]
|
|
378
369
|
# @param delay [Number]
|
|
379
370
|
def type_text(selector, text, delay: nil)
|
|
380
|
-
handle = S(selector)
|
|
371
|
+
handle = S(selector) or raise ElementNotFoundError.new(selector)
|
|
381
372
|
handle.type_text(text, delay: delay)
|
|
382
373
|
handle.dispose
|
|
383
374
|
end
|
|
@@ -411,6 +402,26 @@ class Puppeteer::DOMWorld
|
|
|
411
402
|
# return new WaitTask(this, pageFunction, 'function', polling, timeout, ...args).promise;
|
|
412
403
|
# }
|
|
413
404
|
|
|
405
|
+
# @param page_function [String]
|
|
406
|
+
# @param args [Array]
|
|
407
|
+
# @param polling [Integer|String]
|
|
408
|
+
# @param timeout [Integer]
|
|
409
|
+
# @return [Puppeteer::JSHandle]
|
|
410
|
+
def wait_for_function(page_function, args: [], polling: nil, timeout: nil)
|
|
411
|
+
option_polling = polling || 'raf'
|
|
412
|
+
option_timeout = timeout || @timeout_settings.timeout
|
|
413
|
+
|
|
414
|
+
Puppeteer::WaitTask.new(
|
|
415
|
+
dom_world: self,
|
|
416
|
+
predicate_body: page_function,
|
|
417
|
+
title: 'function',
|
|
418
|
+
polling: option_polling,
|
|
419
|
+
timeout: option_timeout,
|
|
420
|
+
args: args,
|
|
421
|
+
).await_promise
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
|
|
414
425
|
# @return [String]
|
|
415
426
|
def title
|
|
416
427
|
evaluate('() => document.title')
|
|
@@ -436,7 +447,7 @@ class Puppeteer::DOMWorld
|
|
|
436
447
|
|
|
437
448
|
wait_task = Puppeteer::WaitTask.new(
|
|
438
449
|
dom_world: self,
|
|
439
|
-
predicate_body:
|
|
450
|
+
predicate_body: PREDICATE,
|
|
440
451
|
title: title,
|
|
441
452
|
polling: polling,
|
|
442
453
|
timeout: option_timeout,
|