puppeteer-ruby 0.35.1 → 0.37.2

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +71 -45
  3. data/README.md +69 -0
  4. data/docs/api_coverage.md +55 -45
  5. data/lib/puppeteer/browser.rb +2 -8
  6. data/lib/puppeteer/browser_context.rb +1 -0
  7. data/lib/puppeteer/browser_runner.rb +1 -1
  8. data/lib/puppeteer/concurrent_ruby_utils.rb +2 -2
  9. data/lib/puppeteer/coverage.rb +11 -2
  10. data/lib/puppeteer/define_async_method.rb +1 -1
  11. data/lib/puppeteer/devices.rb +132 -0
  12. data/lib/puppeteer/dom_world.rb +10 -9
  13. data/lib/puppeteer/element_handle/offset.rb +28 -0
  14. data/lib/puppeteer/element_handle/point.rb +11 -0
  15. data/lib/puppeteer/element_handle.rb +68 -7
  16. data/lib/puppeteer/frame.rb +4 -3
  17. data/lib/puppeteer/frame_manager.rb +2 -2
  18. data/lib/puppeteer/{request.rb → http_request.rb} +150 -21
  19. data/lib/puppeteer/{response.rb → http_response.rb} +2 -2
  20. data/lib/puppeteer/js_coverage.rb +28 -7
  21. data/lib/puppeteer/launcher/launch_options.rb +3 -3
  22. data/lib/puppeteer/lifecycle_watcher.rb +2 -2
  23. data/lib/puppeteer/mouse.rb +54 -1
  24. data/lib/puppeteer/network_condition.rb +12 -0
  25. data/lib/puppeteer/network_conditions.rb +24 -0
  26. data/lib/puppeteer/network_manager.rb +64 -18
  27. data/lib/puppeteer/page/metrics.rb +49 -0
  28. data/lib/puppeteer/page/screenshot_options.rb +3 -1
  29. data/lib/puppeteer/page.rb +166 -134
  30. data/lib/puppeteer/puppeteer.rb +5 -0
  31. data/lib/puppeteer/timeout_helper.rb +22 -0
  32. data/lib/puppeteer/tracing.rb +6 -1
  33. data/lib/puppeteer/version.rb +1 -1
  34. data/lib/puppeteer/wait_task.rb +1 -1
  35. data/lib/puppeteer/web_socket.rb +1 -0
  36. data/lib/puppeteer.rb +17 -14
  37. data/puppeteer-ruby.gemspec +1 -1
  38. metadata +11 -6
@@ -2,11 +2,13 @@ require 'base64'
2
2
  require 'json'
3
3
  require "stringio"
4
4
 
5
+ require_relative './page/metrics'
5
6
  require_relative './page/pdf_options'
6
7
  require_relative './page/screenshot_options'
7
8
  require_relative './page/screenshot_task_queue'
8
9
 
9
10
  class Puppeteer::Page
11
+ include Puppeteer::DebugPrint
10
12
  include Puppeteer::EventCallbackable
11
13
  include Puppeteer::IfPresent
12
14
  using Puppeteer::DefineAsyncMethod
@@ -46,6 +48,8 @@ class Puppeteer::Page
46
48
  @screenshot_task_queue = ScreenshotTaskQueue.new
47
49
 
48
50
  @workers = {}
51
+ @user_drag_interception_enabled = false
52
+
49
53
  @client.on_event('Target.attachedToTarget') do |event|
50
54
  if event['targetInfo']['type'] != 'worker'
51
55
  # If we don't detach from service workers, they will never die.
@@ -102,7 +106,9 @@ class Puppeteer::Page
102
106
  @client.on('Runtime.consoleAPICalled') do |event|
103
107
  handle_console_api(event)
104
108
  end
105
- # client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
109
+ @client.on('Runtime.bindingCalled') do |event|
110
+ handle_binding_called(event)
111
+ end
106
112
  @client.on_event('Page.javascriptDialogOpening') do |event|
107
113
  handle_dialog_opening(event)
108
114
  end
@@ -112,7 +118,9 @@ class Puppeteer::Page
112
118
  @client.on_event('Inspector.targetCrashed') do |event|
113
119
  handle_target_crashed
114
120
  end
115
- # client.on('Performance.metrics', event => this._emitMetrics(event));
121
+ @client.on_event('Performance.metrics') do |event|
122
+ emit_event(PageEmittedEvents::Metrics, MetricsEvent.new(event))
123
+ end
116
124
  @client.on_event('Log.entryAdded') do |event|
117
125
  handle_log_entry_added(event)
118
126
  end
@@ -134,12 +142,23 @@ class Puppeteer::Page
134
142
  )
135
143
  end
136
144
 
145
+ def drag_interception_enabled?
146
+ @user_drag_interception_enabled
147
+ end
148
+ alias_method :drag_interception_enabled, :drag_interception_enabled?
149
+
137
150
  # @param event_name [Symbol]
138
151
  def on(event_name, &block)
139
152
  unless PageEmittedEvents.values.include?(event_name.to_s)
140
153
  raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
141
154
  end
142
155
 
156
+ if event_name.to_s == 'request'
157
+ super('request') do |req|
158
+ req.enqueue_intercept_action(-> { block.call(req) })
159
+ end
160
+ end
161
+
143
162
  super(event_name.to_s, &block)
144
163
  end
145
164
 
@@ -266,10 +285,20 @@ class Puppeteer::Page
266
285
  @frame_manager.network_manager.request_interception = value
267
286
  end
268
287
 
288
+ def drag_interception_enabled=(enabled)
289
+ @user_drag_interception_enabled = enabled
290
+ @client.send_message('Input.setInterceptDrags', enabled: enabled)
291
+ end
292
+
269
293
  def offline_mode=(enabled)
270
294
  @frame_manager.network_manager.offline_mode = enabled
271
295
  end
272
296
 
297
+ # @param network_condition [Puppeteer::NetworkCondition|nil]
298
+ def emulate_network_conditions(network_condition)
299
+ @frame_manager.network_manager.emulate_network_conditions(network_condition)
300
+ end
301
+
273
302
  # @param {number} timeout
274
303
  def default_navigation_timeout=(timeout)
275
304
  @timeout_settings.default_navigation_timeout = timeout
@@ -381,8 +410,9 @@ class Puppeteer::Page
381
410
  # @param path [String?]
382
411
  # @param content [String?]
383
412
  # @param type [String?]
384
- def add_script_tag(url: nil, path: nil, content: nil, type: nil)
385
- main_frame.add_script_tag(url: url, path: path, content: content, type: type)
413
+ # @param id [String?]
414
+ def add_script_tag(url: nil, path: nil, content: nil, type: nil, id: nil)
415
+ main_frame.add_script_tag(url: url, path: path, content: content, type: type, id: id)
386
416
  end
387
417
 
388
418
  # @param url [String?]
@@ -392,37 +422,51 @@ class Puppeteer::Page
392
422
  main_frame.add_style_tag(url: url, path: path, content: content)
393
423
  end
394
424
 
395
- # /**
396
- # * @param {string} name
397
- # * @param {Function} puppeteerFunction
398
- # */
399
- # async exposeFunction(name, puppeteerFunction) {
400
- # if (this._pageBindings.has(name))
401
- # throw new Error(`Failed to add page binding with name ${name}: window['${name}'] already exists!`);
402
- # this._pageBindings.set(name, puppeteerFunction);
403
-
404
- # const expression = helper.evaluationString(addPageBinding, name);
405
- # await this._client.send('Runtime.addBinding', {name: name});
406
- # await this._client.send('Page.addScriptToEvaluateOnNewDocument', {source: expression});
407
- # await Promise.all(this.frames().map(frame => frame.evaluate(expression).catch(debugError)));
408
-
409
- # function addPageBinding(bindingName) {
410
- # const binding = window[bindingName];
411
- # window[bindingName] = (...args) => {
412
- # const me = window[bindingName];
413
- # let callbacks = me['callbacks'];
414
- # if (!callbacks) {
415
- # callbacks = new Map();
416
- # me['callbacks'] = callbacks;
417
- # }
418
- # const seq = (me['lastSeq'] || 0) + 1;
419
- # me['lastSeq'] = seq;
420
- # const promise = new Promise((resolve, reject) => callbacks.set(seq, {resolve, reject}));
421
- # binding(JSON.stringify({name: bindingName, seq, args}));
422
- # return promise;
423
- # };
424
- # }
425
- # }
425
+ # @param name [String]
426
+ # @param puppeteer_function [Proc]
427
+ def expose_function(name, puppeteer_function)
428
+ if @page_bindings[name]
429
+ raise ArgumentError.new("Failed to add page binding with name `#{name}` already exists!")
430
+ end
431
+ @page_bindings[name] = puppeteer_function
432
+
433
+ add_page_binding = <<~JAVASCRIPT
434
+ function (type, bindingName) {
435
+ /* Cast window to any here as we're about to add properties to it
436
+ * via win[bindingName] which TypeScript doesn't like.
437
+ */
438
+ const win = window;
439
+ const binding = win[bindingName];
440
+
441
+ win[bindingName] = (...args) => {
442
+ const me = window[bindingName];
443
+ let callbacks = me.callbacks;
444
+ if (!callbacks) {
445
+ callbacks = new Map();
446
+ me.callbacks = callbacks;
447
+ }
448
+ const seq = (me.lastSeq || 0) + 1;
449
+ me.lastSeq = seq;
450
+ const promise = new Promise((resolve, reject) =>
451
+ callbacks.set(seq, { resolve, reject })
452
+ );
453
+ binding(JSON.stringify({ type, name: bindingName, seq, args }));
454
+ return promise;
455
+ };
456
+ }
457
+ JAVASCRIPT
458
+
459
+ source = JavaScriptFunction.new(add_page_binding, ['exposedFun', name]).source
460
+ @client.send_message('Runtime.addBinding', name: name)
461
+ @client.send_message('Page.addScriptToEvaluateOnNewDocument', source: source)
462
+
463
+ promises = @frame_manager.frames.map do |frame|
464
+ frame.async_evaluate("() => #{source}")
465
+ end
466
+ await_all(*promises)
467
+
468
+ nil
469
+ end
426
470
 
427
471
  # @param username [String?]
428
472
  # @param password [String?]
@@ -436,40 +480,16 @@ class Puppeteer::Page
436
480
  end
437
481
 
438
482
  # @param user_agent [String]
439
- def user_agent=(user_agent)
440
- @frame_manager.network_manager.user_agent = user_agent
441
- end
442
-
443
- # /**
444
- # * @return {!Promise<!Metrics>}
445
- # */
446
- # async metrics() {
447
- # const response = await this._client.send('Performance.getMetrics');
448
- # return this._buildMetricsObject(response.metrics);
449
- # }
450
-
451
- # /**
452
- # * @param {!Protocol.Performance.metricsPayload} event
453
- # */
454
- # _emitMetrics(event) {
455
- # this.emit(PageEmittedEvents::Metrics, {
456
- # title: event.title,
457
- # metrics: this._buildMetricsObject(event.metrics)
458
- # });
459
- # }
460
-
461
- # /**
462
- # * @param {?Array<!Protocol.Performance.Metric>} metrics
463
- # * @return {!Metrics}
464
- # */
465
- # _buildMetricsObject(metrics) {
466
- # const result = {};
467
- # for (const metric of metrics || []) {
468
- # if (supportedMetrics.has(metric.name))
469
- # result[metric.name] = metric.value;
470
- # }
471
- # return result;
472
- # }
483
+ # @param user_agent_metadata [Hash]
484
+ def set_user_agent(user_agent, user_agent_metadata = nil)
485
+ @frame_manager.network_manager.set_user_agent(user_agent, user_agent_metadata)
486
+ end
487
+ alias_method :user_agent=, :set_user_agent
488
+
489
+ def metrics
490
+ response = @client.send_message('Performance.getMetrics')
491
+ Metrics.new(response['metrics'])
492
+ end
473
493
 
474
494
  class PageError < StandardError ; end
475
495
 
@@ -506,56 +526,51 @@ class Puppeteer::Page
506
526
  add_console_message(event['type'], values, event['stackTrace'])
507
527
  end
508
528
 
509
- # /**
510
- # * @param {!Protocol.Runtime.bindingCalledPayload} event
511
- # */
512
- # async _onBindingCalled(event) {
513
- # const {name, seq, args} = JSON.parse(event.payload);
514
- # let expression = null;
515
- # try {
516
- # const result = await this._pageBindings.get(name)(...args);
517
- # expression = helper.evaluationString(deliverResult, name, seq, result);
518
- # } catch (error) {
519
- # if (error instanceof Error)
520
- # expression = helper.evaluationString(deliverError, name, seq, error.message, error.stack);
521
- # else
522
- # expression = helper.evaluationString(deliverErrorValue, name, seq, error);
523
- # }
524
- # this._client.send('Runtime.evaluate', { expression, contextId: event.executionContextId }).catch(debugError);
525
-
526
- # /**
527
- # * @param {string} name
528
- # * @param {number} seq
529
- # * @param {*} result
530
- # */
531
- # function deliverResult(name, seq, result) {
532
- # window[name]['callbacks'].get(seq).resolve(result);
533
- # window[name]['callbacks'].delete(seq);
534
- # }
535
-
536
- # /**
537
- # * @param {string} name
538
- # * @param {number} seq
539
- # * @param {string} message
540
- # * @param {string} stack
541
- # */
542
- # function deliverError(name, seq, message, stack) {
543
- # const error = new Error(message);
544
- # error.stack = stack;
545
- # window[name]['callbacks'].get(seq).reject(error);
546
- # window[name]['callbacks'].delete(seq);
547
- # }
548
-
549
- # /**
550
- # * @param {string} name
551
- # * @param {number} seq
552
- # * @param {*} value
553
- # */
554
- # function deliverErrorValue(name, seq, value) {
555
- # window[name]['callbacks'].get(seq).reject(value);
556
- # window[name]['callbacks'].delete(seq);
557
- # }
558
- # }
529
+ def handle_binding_called(event)
530
+ execution_context_id = event['executionContextId']
531
+ payload =
532
+ begin
533
+ JSON.parse(event['payload'])
534
+ rescue
535
+ # The binding was either called by something in the page or it was
536
+ # called before our wrapper was initialized.
537
+ return
538
+ end
539
+ name = payload['name']
540
+ seq = payload['seq']
541
+ args = payload['args']
542
+
543
+ if payload['type'] != 'exposedFun' || !@page_bindings[name]
544
+ return
545
+ end
546
+
547
+ expression =
548
+ begin
549
+ result = @page_bindings[name].call(*args)
550
+
551
+ deliver_result = <<~JAVASCRIPT
552
+ function (name, seq, result) {
553
+ window[name].callbacks.get(seq).resolve(result);
554
+ window[name].callbacks.delete(seq);
555
+ }
556
+ JAVASCRIPT
557
+
558
+ JavaScriptFunction.new(deliver_result, [name, seq, result]).source
559
+ rescue => err
560
+ deliver_error = <<~JAVASCRIPT
561
+ function (name, seq, message) {
562
+ const error = new Error(message);
563
+ window[name].callbacks.get(seq).reject(error);
564
+ window[name].callbacks.delete(seq);
565
+ }
566
+ JAVASCRIPT
567
+ JavaScriptFunction.new(deliver_error, [name, seq, err.message]).source
568
+ end
569
+
570
+ @client.async_send_message('Runtime.evaluate', expression: expression, contextId: execution_context_id).rescue do |error|
571
+ debug_puts(error)
572
+ end
573
+ end
559
574
 
560
575
  private def add_console_message(type, args, stack_trace)
561
576
  text_tokens = args.map { |arg| arg.remote_object.value }
@@ -629,12 +644,11 @@ class Puppeteer::Page
629
644
 
630
645
  # @param timeout [number|nil]
631
646
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
632
- # @return [Puppeteer::Response]
647
+ # @return [Puppeteer::HTTPResponse]
633
648
  def reload(timeout: nil, wait_until: nil)
634
- await_all(
635
- async_wait_for_navigation(timeout: timeout, wait_until: wait_until),
636
- @client.async_send_message('Page.reload'),
637
- ).first
649
+ wait_for_navigation(timeout: timeout, wait_until: wait_until) do
650
+ @client.send_message('Page.reload')
651
+ end
638
652
  end
639
653
 
640
654
  def wait_for_navigation(timeout: nil, wait_until: nil)
@@ -660,11 +674,12 @@ class Puppeteer::Page
660
674
  @wait_for_network_manager_event_listener_ids[event_name] =
661
675
  @frame_manager.network_manager.add_event_listener(event_name) do |event_target|
662
676
  if predicate.call(event_target)
663
- promise.fulfill(nil)
677
+ promise.fulfill(event_target)
664
678
  end
665
679
  end
666
680
 
667
681
  begin
682
+ # Timeout.timeout(0) means "no limit" for timeout.
668
683
  Timeout.timeout(option_timeout / 1000.0) do
669
684
  await_any(promise, session_close_promise)
670
685
  end
@@ -714,7 +729,7 @@ class Puppeteer::Page
714
729
  # wait_for_request(predicate: -> (req){ req.url.start_with?('https://example.com/search') })
715
730
  #
716
731
  # @param url [String]
717
- # @param predicate [Proc(Puppeteer::Request -> Boolean)]
732
+ # @param predicate [Proc(Puppeteer::HTTPRequest -> Boolean)]
718
733
  define_async_method :async_wait_for_request
719
734
 
720
735
  def wait_for_response(url: nil, predicate: nil, timeout: nil)
@@ -740,7 +755,7 @@ class Puppeteer::Page
740
755
  # @!method async_wait_for_response(url: nil, predicate: nil, timeout: nil)
741
756
  #
742
757
  # @param url [String]
743
- # @param predicate [Proc(Puppeteer::Request -> Boolean)]
758
+ # @param predicate [Proc(Puppeteer::HTTPRequest -> Boolean)]
744
759
  define_async_method :async_wait_for_response
745
760
 
746
761
  # @param timeout [number|nil]
@@ -760,10 +775,9 @@ class Puppeteer::Page
760
775
  entries = history['entries']
761
776
  index = history['currentIndex'] + delta
762
777
  if_present(entries[index]) do |entry|
763
- await_all(
764
- async_wait_for_navigation(timeout: timeout, wait_until: wait_until),
765
- @client.async_send_message('Page.navigateToHistoryEntry', entryId: entry['id']),
766
- )
778
+ wait_for_navigation(timeout: timeout, wait_until: wait_until) do
779
+ @client.send_message('Page.navigateToHistoryEntry', entryId: entry['id'])
780
+ end
767
781
  end
768
782
  end
769
783
 
@@ -799,6 +813,15 @@ class Puppeteer::Page
799
813
  @client.send_message('Emulation.setEmulatedMedia', media: media_type_str)
800
814
  end
801
815
 
816
+ # @param factor [Number|nil] Factor at which the CPU will be throttled (2x, 2.5x. 3x, ...). Passing `nil` disables cpu throttling.
817
+ def emulate_cpu_throttling(factor)
818
+ if factor.nil? || factor >= 1
819
+ @client.send_message('Emulation.setCPUThrottlingRate', rate: factor || 1)
820
+ else
821
+ raise ArgumentError.new('Throttling rate should be greater or equal to 1')
822
+ end
823
+ end
824
+
802
825
  # @param features [Array]
803
826
  def emulate_media_features(features)
804
827
  if features.nil?
@@ -921,7 +944,7 @@ class Puppeteer::Page
921
944
  main_frame.title
922
945
  end
923
946
 
924
- # @param type [String] "png"|"jpeg"
947
+ # @param type [String] "png"|"jpeg"|"webp"
925
948
  # @param path [String]
926
949
  # @param full_page [Boolean]
927
950
  # @param clip [Hash]
@@ -1015,11 +1038,20 @@ class Puppeteer::Page
1015
1038
 
1016
1039
  # @return [Enumerable<String>]
1017
1040
  def create_pdf_stream(options = {})
1041
+ timeout_helper = Puppeteer::TimeoutHelper.new('Page.printToPDF',
1042
+ timeout_ms: options[:timeout],
1043
+ default_timeout_ms: 30000)
1018
1044
  pdf_options = PDFOptions.new(options)
1019
1045
  omit_background = options[:omit_background]
1020
1046
  set_transparent_background_color if omit_background
1021
- result = @client.send_message('Page.printToPDF', pdf_options.page_print_args)
1022
- reset_default_background_color if omit_background
1047
+ result =
1048
+ begin
1049
+ timeout_helper.with_timeout do
1050
+ @client.send_message('Page.printToPDF', pdf_options.page_print_args)
1051
+ end
1052
+ ensure
1053
+ reset_default_background_color if omit_background
1054
+ end
1023
1055
 
1024
1056
  Puppeteer::ProtocolStreamReader.new(
1025
1057
  client: @client,
@@ -149,6 +149,11 @@ class Puppeteer::Puppeteer
149
149
  # # ???
150
150
  # end
151
151
 
152
+ # @return [Puppeteer::NetworkConditions]
153
+ def network_conditions
154
+ Puppeteer::NetworkConditions
155
+ end
156
+
152
157
  # @param args [Array<String>]
153
158
  # @param user_data_dir [String]
154
159
  # @param devtools [Boolean]
@@ -0,0 +1,22 @@
1
+ require 'timeout'
2
+
3
+ class Puppeteer::TimeoutHelper
4
+ # @param timeout_ms [String|Integer|nil]
5
+ # @param default_timeout_ms [Integer]
6
+ def initialize(task_name, timeout_ms:, default_timeout_ms:)
7
+ @task_name = task_name
8
+ @timeout_ms = (timeout_ms || default_timeout_ms).to_i
9
+ end
10
+
11
+ def with_timeout(&block)
12
+ if @timeout_ms > 0
13
+ begin
14
+ Timeout.timeout(@timeout_ms / 1000.0, &block)
15
+ rescue Timeout::Error
16
+ raise Puppeteer::TimeoutError.new("waiting for #{@task_name} failed: timeout #{@timeout_ms}ms exceeded")
17
+ end
18
+ else
19
+ block.call
20
+ end
21
+ end
22
+ end
@@ -27,11 +27,16 @@ class Puppeteer::Tracing
27
27
  option_categories << 'disabled-by-default-devtools.screenshot'
28
28
  end
29
29
 
30
+ ex_cat = option_categories.select { |cat| cat.start_with?('-') }.map { |cat| cat[1..-1] }
31
+ in_cat = option_categories.reject { |cat| cat.start_with?('-') }
30
32
  @path = path
31
33
  @recording = true
32
34
  @client.send_message('Tracing.start',
33
35
  transferMode: 'ReturnAsStream',
34
- categories: option_categories.join(','),
36
+ traceConfig: {
37
+ excludedCategories: ex_cat,
38
+ includedCategories: in_cat,
39
+ },
35
40
  )
36
41
  end
37
42
 
@@ -1,3 +1,3 @@
1
1
  module Puppeteer
2
- VERSION = '0.35.1'
2
+ VERSION = '0.37.2'
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
@@ -55,6 +55,7 @@ class Puppeteer::WebSocket
55
55
  def initialize(url:, max_payload_size:)
56
56
  @impl = DriverImpl.new(url)
57
57
  @driver = ::WebSocket::Driver.client(@impl, max_length: max_payload_size)
58
+ @driver.set_header('User-Agent', "Puppeteer #{Puppeteer::VERSION}")
58
59
 
59
60
  setup
60
61
  @driver.start
data/lib/puppeteer.rb CHANGED
@@ -5,7 +5,6 @@ module Puppeteer; end
5
5
  require 'puppeteer/env'
6
6
 
7
7
  # Custom data types.
8
- require 'puppeteer/device'
9
8
  require 'puppeteer/events'
10
9
  require 'puppeteer/errors'
11
10
  require 'puppeteer/geolocation'
@@ -38,22 +37,24 @@ require 'puppeteer/execution_context'
38
37
  require 'puppeteer/file_chooser'
39
38
  require 'puppeteer/frame'
40
39
  require 'puppeteer/frame_manager'
40
+ require 'puppeteer/http_request'
41
+ require 'puppeteer/http_response'
41
42
  require 'puppeteer/js_coverage'
42
43
  require 'puppeteer/js_handle'
43
44
  require 'puppeteer/keyboard'
44
45
  require 'puppeteer/launcher'
45
46
  require 'puppeteer/lifecycle_watcher'
46
47
  require 'puppeteer/mouse'
48
+ require 'puppeteer/network_conditions'
47
49
  require 'puppeteer/network_manager'
48
50
  require 'puppeteer/page'
49
51
  require 'puppeteer/protocol_stream_reader'
50
52
  require 'puppeteer/puppeteer'
51
53
  require 'puppeteer/query_handler_manager'
52
54
  require 'puppeteer/remote_object'
53
- require 'puppeteer/request'
54
- require 'puppeteer/response'
55
55
  require 'puppeteer/target'
56
56
  require 'puppeteer/tracing'
57
+ require 'puppeteer/timeout_helper'
57
58
  require 'puppeteer/timeout_settings'
58
59
  require 'puppeteer/touch_screen'
59
60
  require 'puppeteer/version'
@@ -66,17 +67,19 @@ require 'puppeteer/element_handle'
66
67
 
67
68
  # ref: https://github.com/puppeteer/puppeteer/blob/master/lib/Puppeteer.js
68
69
  module Puppeteer
69
- module_function def method_missing(method, *args, **kwargs, &block)
70
- @puppeteer ||= ::Puppeteer::Puppeteer.new(
71
- project_root: __dir__,
72
- preferred_revision: '706915',
73
- is_puppeteer_core: true,
74
- )
75
-
76
- if kwargs.empty? # for Ruby < 2.7
77
- @puppeteer.public_send(method, *args, &block)
78
- else
79
- @puppeteer.public_send(method, *args, **kwargs, &block)
70
+ @puppeteer ||= ::Puppeteer::Puppeteer.new(
71
+ project_root: __dir__,
72
+ preferred_revision: '706915',
73
+ is_puppeteer_core: true,
74
+ ).tap do |instance|
75
+ instance.public_methods(false).each do |method_name|
76
+ define_singleton_method(method_name) do |*args, **kwargs, &block|
77
+ if kwargs.empty? # for Ruby < 2.7
78
+ @puppeteer.public_send(method_name, *args, &block)
79
+ else
80
+ @puppeteer.public_send(method_name, *args, **kwargs, &block)
81
+ end
82
+ end
80
83
  end
81
84
  end
82
85
  end
@@ -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.18.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.35.1
4
+ version: 0.37.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-23 00:00:00.000000000 Z
11
+ date: 2021-11-21 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.18.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.18.0
180
+ version: 1.23.0
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rubocop-rspec
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -274,6 +274,7 @@ files:
274
274
  - lib/puppeteer/element_handle.rb
275
275
  - lib/puppeteer/element_handle/bounding_box.rb
276
276
  - lib/puppeteer/element_handle/box_model.rb
277
+ - lib/puppeteer/element_handle/offset.rb
277
278
  - lib/puppeteer/element_handle/point.rb
278
279
  - lib/puppeteer/emulation_manager.rb
279
280
  - lib/puppeteer/env.rb
@@ -286,6 +287,8 @@ files:
286
287
  - lib/puppeteer/frame.rb
287
288
  - lib/puppeteer/frame_manager.rb
288
289
  - lib/puppeteer/geolocation.rb
290
+ - lib/puppeteer/http_request.rb
291
+ - lib/puppeteer/http_response.rb
289
292
  - lib/puppeteer/if_present.rb
290
293
  - lib/puppeteer/js_coverage.rb
291
294
  - lib/puppeteer/js_handle.rb
@@ -300,8 +303,11 @@ files:
300
303
  - lib/puppeteer/launcher/launch_options.rb
301
304
  - lib/puppeteer/lifecycle_watcher.rb
302
305
  - lib/puppeteer/mouse.rb
306
+ - lib/puppeteer/network_condition.rb
307
+ - lib/puppeteer/network_conditions.rb
303
308
  - lib/puppeteer/network_manager.rb
304
309
  - lib/puppeteer/page.rb
310
+ - lib/puppeteer/page/metrics.rb
305
311
  - lib/puppeteer/page/pdf_options.rb
306
312
  - lib/puppeteer/page/screenshot_options.rb
307
313
  - lib/puppeteer/page/screenshot_task_queue.rb
@@ -309,9 +315,8 @@ files:
309
315
  - lib/puppeteer/puppeteer.rb
310
316
  - lib/puppeteer/query_handler_manager.rb
311
317
  - lib/puppeteer/remote_object.rb
312
- - lib/puppeteer/request.rb
313
- - lib/puppeteer/response.rb
314
318
  - lib/puppeteer/target.rb
319
+ - lib/puppeteer/timeout_helper.rb
315
320
  - lib/puppeteer/timeout_settings.rb
316
321
  - lib/puppeteer/touch_screen.rb
317
322
  - lib/puppeteer/tracing.rb