puppeteer-ruby 0.37.2 → 0.39.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +31 -1
- data/README.md +1 -1
- data/docs/api_coverage.md +6 -6
- data/lib/puppeteer/aria_query_handler.rb +3 -3
- data/lib/puppeteer/browser_runner.rb +21 -10
- data/lib/puppeteer/cdp_session.rb +5 -0
- data/lib/puppeteer/dom_world.rb +9 -5
- data/lib/puppeteer/element_handle.rb +10 -8
- data/lib/puppeteer/executable_path_finder.rb +28 -0
- data/lib/puppeteer/frame.rb +30 -8
- data/lib/puppeteer/frame_manager.rb +136 -59
- data/lib/puppeteer/http_request.rb +9 -1
- data/lib/puppeteer/launcher/chrome.rb +66 -30
- data/lib/puppeteer/launcher/chrome_arg_options.rb +2 -1
- data/lib/puppeteer/launcher/firefox.rb +268 -228
- data/lib/puppeteer/launcher/launch_options.rb +2 -1
- data/lib/puppeteer/page/screenshot_options.rb +1 -1
- data/lib/puppeteer/page.rb +75 -19
- data/lib/puppeteer/puppeteer.rb +2 -0
- data/lib/puppeteer/target.rb +5 -0
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer.rb +1 -0
- metadata +3 -2
data/lib/puppeteer/page.rb
CHANGED
@@ -50,19 +50,26 @@ class Puppeteer::Page
|
|
50
50
|
@workers = {}
|
51
51
|
@user_drag_interception_enabled = false
|
52
52
|
|
53
|
-
@client.
|
54
|
-
if event['targetInfo']['type'] != 'worker'
|
53
|
+
@client.add_event_listener('Target.attachedToTarget') do |event|
|
54
|
+
if event['targetInfo']['type'] != 'worker' && event['targetInfo']['type'] != 'iframe'
|
55
55
|
# If we don't detach from service workers, they will never die.
|
56
|
+
# We still want to attach to workers for emitting events.
|
57
|
+
# We still want to attach to iframes so sessions may interact with them.
|
58
|
+
# We detach from all other types out of an abundance of caution.
|
59
|
+
# See https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypePage%5B%5D%22
|
60
|
+
# for the complete list of available types.
|
56
61
|
@client.async_send_message('Target.detachFromTarget', sessionId: event['sessionId'])
|
57
62
|
next
|
58
63
|
end
|
59
64
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
65
|
+
if event['targetInfo']['type'] == 'worker'
|
66
|
+
session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
|
67
|
+
# const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
|
68
|
+
# this._workers.set(event.sessionId, worker);
|
69
|
+
# this.emit(PageEmittedEvents::WorkerCreated, worker);
|
70
|
+
end
|
64
71
|
end
|
65
|
-
@client.
|
72
|
+
@client.add_event_listener('Target.detachedFromTarget') do |event|
|
66
73
|
session_id = event['sessionId']
|
67
74
|
worker = @workers[session_id]
|
68
75
|
next unless worker
|
@@ -103,10 +110,10 @@ class Puppeteer::Page
|
|
103
110
|
@client.on_event('Page.loadEventFired') do |event|
|
104
111
|
emit_event(PageEmittedEvents::Load)
|
105
112
|
end
|
106
|
-
@client.
|
113
|
+
@client.add_event_listener('Runtime.consoleAPICalled') do |event|
|
107
114
|
handle_console_api(event)
|
108
115
|
end
|
109
|
-
@client.
|
116
|
+
@client.add_event_listener('Runtime.bindingCalled') do |event|
|
110
117
|
handle_binding_called(event)
|
111
118
|
end
|
112
119
|
@client.on_event('Page.javascriptDialogOpening') do |event|
|
@@ -518,7 +525,7 @@ class Puppeteer::Page
|
|
518
525
|
return
|
519
526
|
end
|
520
527
|
|
521
|
-
context = @frame_manager.execution_context_by_id(event['executionContextId'])
|
528
|
+
context = @frame_manager.execution_context_by_id(event['executionContextId'], @client)
|
522
529
|
values = event['args'].map do |arg|
|
523
530
|
remote_object = Puppeteer::RemoteObject.new(arg)
|
524
531
|
Puppeteer::JSHandle.create(context: context, remote_object: remote_object)
|
@@ -664,19 +671,38 @@ class Puppeteer::Page
|
|
664
671
|
private def wait_for_network_manager_event(event_name, predicate:, timeout:)
|
665
672
|
option_timeout = timeout || @timeout_settings.timeout
|
666
673
|
|
667
|
-
|
668
|
-
|
674
|
+
promise = resolvable_future
|
675
|
+
|
676
|
+
listener_id = @frame_manager.network_manager.add_event_listener(event_name) do |event_target|
|
677
|
+
if predicate.call(event_target)
|
678
|
+
promise.fulfill(event_target)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
begin
|
683
|
+
# Timeout.timeout(0) means "no limit" for timeout.
|
684
|
+
Timeout.timeout(option_timeout / 1000.0) do
|
685
|
+
await_any(promise, session_close_promise)
|
686
|
+
end
|
687
|
+
rescue Timeout::Error
|
688
|
+
raise Puppeteer::TimeoutError.new("waiting for #{event_name} failed: timeout #{option_timeout}ms exceeded")
|
689
|
+
ensure
|
669
690
|
@frame_manager.network_manager.remove_event_listener(listener_id)
|
670
691
|
end
|
692
|
+
end
|
693
|
+
|
694
|
+
private def wait_for_frame_manager_event(*event_names, predicate:, timeout:)
|
695
|
+
option_timeout = timeout || @timeout_settings.timeout
|
671
696
|
|
672
697
|
promise = resolvable_future
|
673
698
|
|
674
|
-
|
675
|
-
@frame_manager.
|
699
|
+
listener_ids = event_names.map do |event_name|
|
700
|
+
@frame_manager.add_event_listener(event_name) do |event_target|
|
676
701
|
if predicate.call(event_target)
|
677
|
-
promise.fulfill(event_target)
|
702
|
+
promise.fulfill(event_target) unless promise.resolved?
|
678
703
|
end
|
679
704
|
end
|
705
|
+
end
|
680
706
|
|
681
707
|
begin
|
682
708
|
# Timeout.timeout(0) means "no limit" for timeout.
|
@@ -684,9 +710,11 @@ class Puppeteer::Page
|
|
684
710
|
await_any(promise, session_close_promise)
|
685
711
|
end
|
686
712
|
rescue Timeout::Error
|
687
|
-
raise Puppeteer::TimeoutError.new("waiting for #{
|
713
|
+
raise Puppeteer::TimeoutError.new("waiting for #{event_names.join(" or ")} failed: timeout #{option_timeout}ms exceeded")
|
688
714
|
ensure
|
689
|
-
|
715
|
+
listener_ids.each do |listener_id|
|
716
|
+
@frame_manager.remove_event_listener(listener_id)
|
717
|
+
end
|
690
718
|
end
|
691
719
|
end
|
692
720
|
|
@@ -709,7 +737,7 @@ class Puppeteer::Page
|
|
709
737
|
if url
|
710
738
|
-> (request) { request.url == url }
|
711
739
|
else
|
712
|
-
|
740
|
+
predicate
|
713
741
|
end
|
714
742
|
|
715
743
|
wait_for_network_manager_event(NetworkManagerEmittedEvents::Request,
|
@@ -743,7 +771,7 @@ class Puppeteer::Page
|
|
743
771
|
if url
|
744
772
|
-> (response) { response.url == url }
|
745
773
|
else
|
746
|
-
|
774
|
+
predicate
|
747
775
|
end
|
748
776
|
|
749
777
|
wait_for_network_manager_event(NetworkManagerEmittedEvents::Response,
|
@@ -758,6 +786,34 @@ class Puppeteer::Page
|
|
758
786
|
# @param predicate [Proc(Puppeteer::HTTPRequest -> Boolean)]
|
759
787
|
define_async_method :async_wait_for_response
|
760
788
|
|
789
|
+
def wait_for_frame(url: nil, predicate: nil, timeout: nil)
|
790
|
+
if !url && !predicate
|
791
|
+
raise ArgumentError.new('url or predicate must be specified')
|
792
|
+
end
|
793
|
+
if predicate && !predicate.is_a?(Proc)
|
794
|
+
raise ArgumentError.new('predicate must be a proc.')
|
795
|
+
end
|
796
|
+
frame_predicate =
|
797
|
+
if url
|
798
|
+
-> (frame) { frame.url == url }
|
799
|
+
else
|
800
|
+
predicate
|
801
|
+
end
|
802
|
+
|
803
|
+
wait_for_frame_manager_event(
|
804
|
+
FrameManagerEmittedEvents::FrameAttached,
|
805
|
+
FrameManagerEmittedEvents::FrameNavigated,
|
806
|
+
predicate: frame_predicate,
|
807
|
+
timeout: timeout,
|
808
|
+
)
|
809
|
+
end
|
810
|
+
|
811
|
+
# @!method async_wait_for_frame(url: nil, predicate: nil, timeout: nil)
|
812
|
+
#
|
813
|
+
# @param url [String]
|
814
|
+
# @param predicate [Proc(Puppeteer::Frame -> Boolean)]
|
815
|
+
define_async_method :async_wait_for_frame
|
816
|
+
|
761
817
|
# @param timeout [number|nil]
|
762
818
|
# @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
|
763
819
|
def go_back(timeout: nil, wait_until: nil)
|
data/lib/puppeteer/puppeteer.rb
CHANGED
@@ -44,6 +44,7 @@ class Puppeteer::Puppeteer
|
|
44
44
|
args: nil,
|
45
45
|
user_data_dir: nil,
|
46
46
|
devtools: nil,
|
47
|
+
debugging_port: nil,
|
47
48
|
headless: nil,
|
48
49
|
ignore_https_errors: nil,
|
49
50
|
default_viewport: NoViewport.new,
|
@@ -63,6 +64,7 @@ class Puppeteer::Puppeteer
|
|
63
64
|
args: args,
|
64
65
|
user_data_dir: user_data_dir,
|
65
66
|
devtools: devtools,
|
67
|
+
debugging_port: debugging_port,
|
66
68
|
headless: headless,
|
67
69
|
ignore_https_errors: ignore_https_errors,
|
68
70
|
default_viewport: default_viewport,
|
data/lib/puppeteer/target.rb
CHANGED
data/lib/puppeteer/version.rb
CHANGED
data/lib/puppeteer.rb
CHANGED
@@ -33,6 +33,7 @@ require 'puppeteer/dialog'
|
|
33
33
|
require 'puppeteer/dom_world'
|
34
34
|
require 'puppeteer/emulation_manager'
|
35
35
|
require 'puppeteer/exception_details'
|
36
|
+
require 'puppeteer/executable_path_finder'
|
36
37
|
require 'puppeteer/execution_context'
|
37
38
|
require 'puppeteer/file_chooser'
|
38
39
|
require 'puppeteer/frame'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppeteer-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.39.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -282,6 +282,7 @@ files:
|
|
282
282
|
- lib/puppeteer/event_callbackable.rb
|
283
283
|
- lib/puppeteer/events.rb
|
284
284
|
- lib/puppeteer/exception_details.rb
|
285
|
+
- lib/puppeteer/executable_path_finder.rb
|
285
286
|
- lib/puppeteer/execution_context.rb
|
286
287
|
- lib/puppeteer/file_chooser.rb
|
287
288
|
- lib/puppeteer/frame.rb
|