puppeteer-ruby 0.37.1 → 0.38.0

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.
@@ -50,19 +50,26 @@ class Puppeteer::Page
50
50
  @workers = {}
51
51
  @user_drag_interception_enabled = false
52
52
 
53
- @client.on_event('Target.attachedToTarget') do |event|
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
- session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
61
- # const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
62
- # this._workers.set(event.sessionId, worker);
63
- # this.emit(PageEmittedEvents::WorkerCreated, worker);
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.on_event('Target.detachedFromTarget') do |event|
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.on('Runtime.consoleAPICalled') do |event|
113
+ @client.add_event_listener('Runtime.consoleAPICalled') do |event|
107
114
  handle_console_api(event)
108
115
  end
109
- @client.on('Runtime.bindingCalled') do |event|
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|
@@ -153,6 +160,12 @@ class Puppeteer::Page
153
160
  raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
154
161
  end
155
162
 
163
+ if event_name.to_s == 'request'
164
+ super('request') do |req|
165
+ req.enqueue_intercept_action(-> { block.call(req) })
166
+ end
167
+ end
168
+
156
169
  super(event_name.to_s, &block)
157
170
  end
158
171
 
@@ -512,7 +525,7 @@ class Puppeteer::Page
512
525
  return
513
526
  end
514
527
 
515
- context = @frame_manager.execution_context_by_id(event['executionContextId'])
528
+ context = @frame_manager.execution_context_by_id(event['executionContextId'], @client)
516
529
  values = event['args'].map do |arg|
517
530
  remote_object = Puppeteer::RemoteObject.new(arg)
518
531
  Puppeteer::JSHandle.create(context: context, remote_object: remote_object)
@@ -638,7 +651,7 @@ class Puppeteer::Page
638
651
 
639
652
  # @param timeout [number|nil]
640
653
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
641
- # @return [Puppeteer::Response]
654
+ # @return [Puppeteer::HTTPResponse]
642
655
  def reload(timeout: nil, wait_until: nil)
643
656
  wait_for_navigation(timeout: timeout, wait_until: wait_until) do
644
657
  @client.send_message('Page.reload')
@@ -658,28 +671,50 @@ class Puppeteer::Page
658
671
  private def wait_for_network_manager_event(event_name, predicate:, timeout:)
659
672
  option_timeout = timeout || @timeout_settings.timeout
660
673
 
661
- @wait_for_network_manager_event_listener_ids ||= {}
662
- if_present(@wait_for_network_manager_event_listener_ids[event_name]) do |listener_id|
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
663
690
  @frame_manager.network_manager.remove_event_listener(listener_id)
664
691
  end
692
+ end
693
+
694
+ private def wait_for_frame_manager_event(*event_names, predicate:, timeout:)
695
+ option_timeout = timeout || @timeout_settings.timeout
665
696
 
666
697
  promise = resolvable_future
667
698
 
668
- @wait_for_network_manager_event_listener_ids[event_name] =
669
- @frame_manager.network_manager.add_event_listener(event_name) do |event_target|
699
+ listener_ids = event_names.map do |event_name|
700
+ @frame_manager.add_event_listener(event_name) do |event_target|
670
701
  if predicate.call(event_target)
671
- promise.fulfill(nil)
702
+ promise.fulfill(event_target) unless promise.resolved?
672
703
  end
673
704
  end
705
+ end
674
706
 
675
707
  begin
708
+ # Timeout.timeout(0) means "no limit" for timeout.
676
709
  Timeout.timeout(option_timeout / 1000.0) do
677
710
  await_any(promise, session_close_promise)
678
711
  end
679
712
  rescue Timeout::Error
680
- raise Puppeteer::TimeoutError.new("waiting for #{event_name} failed: timeout #{timeout}ms exceeded")
713
+ raise Puppeteer::TimeoutError.new("waiting for #{event_names.join(" or ")} failed: timeout #{option_timeout}ms exceeded")
681
714
  ensure
682
- @frame_manager.network_manager.remove_event_listener(@wait_for_network_manager_event_listener_ids[event_name])
715
+ listener_ids.each do |listener_id|
716
+ @frame_manager.remove_event_listener(listener_id)
717
+ end
683
718
  end
684
719
  end
685
720
 
@@ -702,7 +737,7 @@ class Puppeteer::Page
702
737
  if url
703
738
  -> (request) { request.url == url }
704
739
  else
705
- -> (request) { predicate.call(request) }
740
+ predicate
706
741
  end
707
742
 
708
743
  wait_for_network_manager_event(NetworkManagerEmittedEvents::Request,
@@ -722,7 +757,7 @@ class Puppeteer::Page
722
757
  # wait_for_request(predicate: -> (req){ req.url.start_with?('https://example.com/search') })
723
758
  #
724
759
  # @param url [String]
725
- # @param predicate [Proc(Puppeteer::Request -> Boolean)]
760
+ # @param predicate [Proc(Puppeteer::HTTPRequest -> Boolean)]
726
761
  define_async_method :async_wait_for_request
727
762
 
728
763
  def wait_for_response(url: nil, predicate: nil, timeout: nil)
@@ -736,7 +771,7 @@ class Puppeteer::Page
736
771
  if url
737
772
  -> (response) { response.url == url }
738
773
  else
739
- -> (response) { predicate.call(response) }
774
+ predicate
740
775
  end
741
776
 
742
777
  wait_for_network_manager_event(NetworkManagerEmittedEvents::Response,
@@ -748,9 +783,37 @@ class Puppeteer::Page
748
783
  # @!method async_wait_for_response(url: nil, predicate: nil, timeout: nil)
749
784
  #
750
785
  # @param url [String]
751
- # @param predicate [Proc(Puppeteer::Request -> Boolean)]
786
+ # @param predicate [Proc(Puppeteer::HTTPRequest -> Boolean)]
752
787
  define_async_method :async_wait_for_response
753
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
+
754
817
  # @param timeout [number|nil]
755
818
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
756
819
  def go_back(timeout: nil, wait_until: nil)
@@ -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,
@@ -119,6 +119,11 @@ class Puppeteer::Target
119
119
  end
120
120
  end
121
121
 
122
+ # @internal
123
+ def raw_type
124
+ @target_info.type
125
+ end
126
+
122
127
  # @return {!Puppeteer.Browser}
123
128
  def browser
124
129
  @browser_context.browser
@@ -1,3 +1,3 @@
1
1
  module Puppeteer
2
- VERSION = '0.37.1'
2
+ VERSION = '0.38.0'
3
3
  end
@@ -37,7 +37,7 @@ class Puppeteer::WaitTask
37
37
 
38
38
  # Since page navigation requires us to re-install the pageScript, we should track
39
39
  # timeout on our end.
40
- if timeout
40
+ if timeout && timeout > 0
41
41
  timeout_error = TimeoutError.new(title: title, timeout: timeout)
42
42
  Concurrent::Promises.schedule(timeout / 1000.0) { terminate(timeout_error) unless @timeout_cleared }
43
43
  end
data/lib/puppeteer.rb CHANGED
@@ -33,10 +33,13 @@ 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'
39
40
  require 'puppeteer/frame_manager'
41
+ require 'puppeteer/http_request'
42
+ require 'puppeteer/http_response'
40
43
  require 'puppeteer/js_coverage'
41
44
  require 'puppeteer/js_handle'
42
45
  require 'puppeteer/keyboard'
@@ -50,8 +53,6 @@ require 'puppeteer/protocol_stream_reader'
50
53
  require 'puppeteer/puppeteer'
51
54
  require 'puppeteer/query_handler_manager'
52
55
  require 'puppeteer/remote_object'
53
- require 'puppeteer/request'
54
- require 'puppeteer/response'
55
56
  require 'puppeteer/target'
56
57
  require 'puppeteer/tracing'
57
58
  require 'puppeteer/timeout_helper'
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rollbar'
33
33
  spec.add_development_dependency 'rspec', '~> 3.10.0 '
34
34
  spec.add_development_dependency 'rspec_junit_formatter' # for CircleCI.
35
- spec.add_development_dependency 'rubocop', '~> 1.22.0'
35
+ spec.add_development_dependency 'rubocop', '~> 1.23.0'
36
36
  spec.add_development_dependency 'rubocop-rspec'
37
37
  spec.add_development_dependency 'sinatra'
38
38
  spec.add_development_dependency 'webrick'
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.37.1
4
+ version: 0.38.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-10-26 00:00:00.000000000 Z
11
+ date: 2021-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 1.22.0
173
+ version: 1.23.0
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 1.22.0
180
+ version: 1.23.0
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rubocop-rspec
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -282,11 +282,14 @@ 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
288
289
  - lib/puppeteer/frame_manager.rb
289
290
  - lib/puppeteer/geolocation.rb
291
+ - lib/puppeteer/http_request.rb
292
+ - lib/puppeteer/http_response.rb
290
293
  - lib/puppeteer/if_present.rb
291
294
  - lib/puppeteer/js_coverage.rb
292
295
  - lib/puppeteer/js_handle.rb
@@ -313,8 +316,6 @@ files:
313
316
  - lib/puppeteer/puppeteer.rb
314
317
  - lib/puppeteer/query_handler_manager.rb
315
318
  - lib/puppeteer/remote_object.rb
316
- - lib/puppeteer/request.rb
317
- - lib/puppeteer/response.rb
318
319
  - lib/puppeteer/target.rb
319
320
  - lib/puppeteer/timeout_helper.rb
320
321
  - lib/puppeteer/timeout_settings.rb