puppeteer-ruby 0.35.1 → 0.37.2

Sign up to get free protection for your applications and to get access to all the features.
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