puppeteer-ruby 0.0.20 → 0.0.26

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.
@@ -12,9 +12,9 @@ module Puppeteer::Launcher
12
12
 
13
13
  firefox_arguments =
14
14
  if !@launch_options.ignore_default_args
15
- default_args.to_a
15
+ default_args(options).to_a
16
16
  elsif @launch_options.ignore_default_args.is_a?(Enumerable)
17
- default_args.reject do |arg|
17
+ default_args(options).reject do |arg|
18
18
  @launch_options.ignore_default_args.include?(arg)
19
19
  end.to_a
20
20
  else
@@ -127,7 +127,7 @@ module Puppeteer::Launcher
127
127
  resolve_executable_path
128
128
  end
129
129
 
130
- private def product
130
+ def product
131
131
  'firefox'
132
132
  end
133
133
 
@@ -173,11 +173,7 @@ module Puppeteer::Launcher
173
173
 
174
174
  # @return [DefaultArgs]
175
175
  def default_args(options = nil)
176
- if options.nil?
177
- @default_args ||= DefaultArgs.new(@chrome_arg_options)
178
- else
179
- DefaultArgs.new(ChromeArgOptions.new(options))
180
- end
176
+ DefaultArgs.new(ChromeArgOptions.new(options || {}))
181
177
  end
182
178
 
183
179
  private def create_profile(extra_prefs = {})
@@ -203,7 +199,7 @@ module Puppeteer::Launcher
203
199
  # https://bugzilla.mozilla.org/show_bug.cgi?id=1543115
204
200
  'browser.dom.window.dump.enabled': true,
205
201
  # Disable topstories
206
- 'browser.newtabpage.activity-stream.feeds.section.topstories': false,
202
+ 'browser.newtabpage.activity-stream.feeds.system.topstories': false,
207
203
  # Always display a blank page
208
204
  'browser.newtabpage.enabled': false,
209
205
  # Background thumbnails in particular cause grief: and disabling
@@ -250,16 +246,15 @@ module Puppeteer::Launcher
250
246
  # Do not warn on quitting Firefox
251
247
  'browser.warnOnQuit': false,
252
248
 
253
- # Do not show datareporting policy notifications which can
254
- # interfere with tests
255
- 'datareporting.healthreport.about.reportUrl': "http://#{server}/dummy/abouthealthreport/",
249
+ # Defensively disable data reporting systems
256
250
  'datareporting.healthreport.documentServerURI': "http://#{server}/dummy/healthreport/",
257
251
  'datareporting.healthreport.logging.consoleEnabled': false,
258
252
  'datareporting.healthreport.service.enabled': false,
259
253
  'datareporting.healthreport.service.firstRun': false,
260
254
  'datareporting.healthreport.uploadEnabled': false,
255
+
256
+ # Do not show datareporting policy notifications which can interfere with tests
261
257
  'datareporting.policy.dataSubmissionEnabled': false,
262
- 'datareporting.policy.dataSubmissionPolicyAccepted': false,
263
258
  'datareporting.policy.dataSubmissionPolicyBypassNotification': true,
264
259
 
265
260
  # DevTools JSONViewer sometimes fails to load dependencies with its require.js.
@@ -372,8 +367,6 @@ module Puppeteer::Launcher
372
367
  # Disable browser animations (tabs, fullscreen, sliding alerts)
373
368
  'toolkit.cosmeticAnimations.enabled': false,
374
369
 
375
- # We want to collect telemetry, but we don't want to send in the results
376
- 'toolkit.telemetry.server': "https://#{server}/dummy/telemetry/",
377
370
  # Prevent starting into safe mode after application crashes
378
371
  'toolkit.startup.max_resumed_crashes': -1,
379
372
  }
@@ -69,17 +69,17 @@ class Puppeteer::LifecycleWatcher
69
69
  @timeout = timeout
70
70
 
71
71
  @listener_ids = {}
72
- @listener_ids['client'] = @frame_manager.client.add_event_listener('Events.CDPSession.Disconnected') do
72
+ @listener_ids['client'] = @frame_manager.client.add_event_listener(CDPSessionEmittedEvents::Disconnected) do
73
73
  terminate(TerminatedError.new('Navigation failed because browser has disconnected!'))
74
74
  end
75
75
  @listener_ids['frame_manager'] = [
76
- @frame_manager.add_event_listener('Events.FrameManager.LifecycleEvent') do |_|
76
+ @frame_manager.add_event_listener(FrameManagerEmittedEvents::LifecycleEvent) do |_|
77
77
  check_lifecycle_complete
78
78
  end,
79
- @frame_manager.add_event_listener('Events.FrameManager.FrameNavigatedWithinDocument', &method(:navigated_within_document)),
80
- @frame_manager.add_event_listener('Events.FrameManager.FrameDetached', &method(:handle_frame_detached)),
79
+ @frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameNavigatedWithinDocument, &method(:navigated_within_document)),
80
+ @frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameDetached, &method(:handle_frame_detached)),
81
81
  ]
82
- @listener_ids['network_manager'] = @frame_manager.network_manager.add_event_listener('Events.NetworkManager.Request', &method(:handle_request))
82
+ @listener_ids['network_manager'] = @frame_manager.network_manager.add_event_listener(NetworkManagerEmittedEvents::Request, &method(:handle_request))
83
83
 
84
84
  @same_document_navigation_promise = resolvable_future
85
85
  @lifecycle_promise = resolvable_future
@@ -128,7 +128,7 @@ class Puppeteer::LifecycleWatcher
128
128
  @termination_promise.value!
129
129
  end
130
130
  rescue Timeout::Error
131
- raise Puppeteer::FrameManager::NavigationError.new("Navigation timeout of #{@timeout}ms exceeded")
131
+ raise Puppeteer::TimeoutError.new("Navigation timeout of #{@timeout}ms exceeded")
132
132
  end
133
133
  else
134
134
  @termination_promise
@@ -212,7 +212,7 @@ class Puppeteer::NetworkManager
212
212
  frame = if_present(event['frameId']) { |frame_id| @frame_manager.frame(frame_id) }
213
213
  request = Puppeteer::Request.new(@client, frame, interception_id, @user_request_interception_enabled, event, redirect_chain)
214
214
  @request_id_to_request[event['requestId']] = request
215
- emit_event 'Events.NetworkManager.Request', request
215
+ emit_event(NetworkManagerEmittedEvents::Request, request)
216
216
  end
217
217
 
218
218
  private def handle_request_served_from_cache(event)
@@ -230,8 +230,8 @@ class Puppeteer::NetworkManager
230
230
  response.internal.body_loaded_promise.reject(Puppeteer::Response::Redirected.new)
231
231
  @request_id_to_request.delete(request.internal.request_id)
232
232
  @attempted_authentications.delete(request.internal.interception_id)
233
- emit_event 'Events.NetworkManager.Response', response
234
- emit_event 'Events.NetworkManager.RequestFinished', request
233
+ emit_event(NetworkManagerEmittedEvents::Response, response)
234
+ emit_event(NetworkManagerEmittedEvents::RequestFinished, request)
235
235
  end
236
236
 
237
237
  # @param event [Hash]
@@ -242,7 +242,7 @@ class Puppeteer::NetworkManager
242
242
 
243
243
  response = Puppeteer::Response.new(@client, request, event['response'])
244
244
  request.internal.response = response
245
- emit_event 'Events.NetworkManager.Response', response
245
+ emit_event(NetworkManagerEmittedEvents::Response, response)
246
246
  end
247
247
 
248
248
  private def handle_loading_finished(event)
@@ -260,7 +260,7 @@ class Puppeteer::NetworkManager
260
260
 
261
261
  @request_id_to_request.delete(request.internal.request_id)
262
262
  @attempted_authentications.delete(request.internal.interception_id)
263
- emit_event 'Events.NetworkManager.RequestFinished', request
263
+ emit_event(NetworkManagerEmittedEvents::RequestFinished, request)
264
264
  end
265
265
 
266
266
  private def handle_loading_failed(event)
@@ -275,6 +275,6 @@ class Puppeteer::NetworkManager
275
275
  end
276
276
  @request_id_to_request.delete(request.internal.request_id)
277
277
  @attempted_authentications.delete(request.internal.interception_id)
278
- emit_event 'Events.NetworkManager.RequestFailed', request
278
+ emit_event(NetworkManagerEmittedEvents::RequestFailed, request)
279
279
  end
280
280
  end
@@ -3,6 +3,7 @@ require "stringio"
3
3
 
4
4
  require_relative './page/pdf_options'
5
5
  require_relative './page/screenshot_options'
6
+ require_relative './page/screenshot_task_queue'
6
7
 
7
8
  class Puppeteer::Page
8
9
  include Puppeteer::EventCallbackable
@@ -13,10 +14,9 @@ class Puppeteer::Page
13
14
  # @param {!Puppeteer.Target} target
14
15
  # @param {boolean} ignoreHTTPSErrors
15
16
  # @param {?Puppeteer.Viewport} defaultViewport
16
- # @param {!Puppeteer.TaskQueue} screenshotTaskQueue
17
17
  # @return {!Promise<!Page>}
18
- def self.create(client, target, ignore_https_errors, default_viewport, screenshot_task_queue)
19
- page = Puppeteer::Page.new(client, target, ignore_https_errors, screenshot_task_queue)
18
+ def self.create(client, target, ignore_https_errors, default_viewport)
19
+ page = Puppeteer::Page.new(client, target, ignore_https_errors)
20
20
  page.init
21
21
  if default_viewport
22
22
  page.viewport = default_viewport
@@ -27,8 +27,7 @@ class Puppeteer::Page
27
27
  # @param {!Puppeteer.CDPSession} client
28
28
  # @param {!Puppeteer.Target} target
29
29
  # @param {boolean} ignoreHTTPSErrors
30
- # @param {!Puppeteer.TaskQueue} screenshotTaskQueue
31
- def initialize(client, target, ignore_https_errors, screenshot_task_queue)
30
+ def initialize(client, target, ignore_https_errors)
32
31
  @closed = false
33
32
  @client = client
34
33
  @target = target
@@ -43,10 +42,10 @@ class Puppeteer::Page
43
42
  @page_bindings = {}
44
43
  # @coverage = Coverage.new(client)
45
44
  @javascript_enabled = true
46
- @screenshot_task_queue = screenshot_task_queue
45
+ @screenshot_task_queue = ScreenshotTaskQueue.new
47
46
 
48
47
  @workers = {}
49
- @client.on_event 'Target.attachedToTarget' do |event|
48
+ @client.on_event('Target.attachedToTarget') do |event|
50
49
  if event['targetInfo']['type'] != 'worker'
51
50
  # If we don't detach from service workers, they will never die.
52
51
  await @client.send_message('Target.detachFromTarget', sessionId: event['sessionId'])
@@ -56,65 +55,69 @@ class Puppeteer::Page
56
55
  session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
57
56
  # const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
58
57
  # this._workers.set(event.sessionId, worker);
59
- # this.emit(Events.Page.WorkerCreated, worker);
58
+ # this.emit(PageEmittedEvents::WorkerCreated, worker);
60
59
  end
61
- @client.on_event 'Target.detachedFromTarget' do |event|
60
+ @client.on_event('Target.detachedFromTarget') do |event|
62
61
  session_id = event['sessionId']
63
62
  worker = @workers[session_id]
64
63
  next unless worker
65
64
 
66
- emit_event('Events.Page.WorkerDestroyed', worker)
65
+ emit_event(PageEmittedEvents::WorkerDestroyed, worker)
67
66
  @workers.delete(session_id)
68
67
  end
69
68
 
70
- @frame_manager.on_event 'Events.FrameManager.FrameAttached' do |event|
71
- emit_event 'Events.Page.FrameAttached', event
69
+ @frame_manager.on_event(FrameManagerEmittedEvents::FrameAttached) do |event|
70
+ emit_event(PageEmittedEvents::FrameAttached, event)
72
71
  end
73
- @frame_manager.on_event 'Events.FrameManager.FrameDetached' do |event|
74
- emit_event 'Events.Page.FrameDetached', event
72
+ @frame_manager.on_event(FrameManagerEmittedEvents::FrameDetached) do |event|
73
+ emit_event(PageEmittedEvents::FrameDetached, event)
75
74
  end
76
- @frame_manager.on_event 'Events.FrameManager.FrameNavigated' do |event|
77
- emit_event 'Events.Page.FrameNavigated', event
75
+ @frame_manager.on_event(FrameManagerEmittedEvents::FrameNavigated) do |event|
76
+ emit_event(PageEmittedEvents::FrameNavigated, event)
78
77
  end
79
78
 
80
79
  network_manager = @frame_manager.network_manager
81
- network_manager.on_event 'Events.NetworkManager.Request' do |event|
82
- emit_event 'Events.Page.Request', event
80
+ network_manager.on_event(NetworkManagerEmittedEvents::Request) do |event|
81
+ emit_event(PageEmittedEvents::Request, event)
83
82
  end
84
- network_manager.on_event 'Events.NetworkManager.Response' do |event|
85
- emit_event 'Events.Page.Response', event
83
+ network_manager.on_event(NetworkManagerEmittedEvents::Response) do |event|
84
+ emit_event(PageEmittedEvents::Response, event)
86
85
  end
87
- network_manager.on_event 'Events.NetworkManager.RequestFailed' do |event|
88
- emit_event 'Events.Page.RequestFailed', event
86
+ network_manager.on_event(NetworkManagerEmittedEvents::RequestFailed) do |event|
87
+ emit_event(PageEmittedEvents::RequestFailed, event)
89
88
  end
90
- network_manager.on_event 'Events.NetworkManager.RequestFinished' do |event|
91
- emit_event 'Events.Page.RequestFinished', event
89
+ network_manager.on_event(NetworkManagerEmittedEvents::RequestFinished) do |event|
90
+ emit_event(PageEmittedEvents::RequestFinished, event)
92
91
  end
93
92
  @file_chooser_interception_is_disabled = false
94
93
  @file_chooser_interceptors = Set.new
95
94
 
96
- @client.on_event 'Page.domContentEventFired' do |event|
97
- emit_event 'Events.Page.DOMContentLoaded'
95
+ @client.on_event('Page.domContentEventFired') do |event|
96
+ emit_event(PageEmittedEvents::DOMContentLoaded)
98
97
  end
99
- @client.on_event 'Page.loadEventFired' do |event|
100
- emit_event 'Events.Page.Load'
98
+ @client.on_event('Page.loadEventFired') do |event|
99
+ emit_event(PageEmittedEvents::Load)
101
100
  end
102
101
  # client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
103
102
  # client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
104
- @client.on_event 'Page.javascriptDialogOpening' do |event|
103
+ @client.on_event('Page.javascriptDialogOpening') do |event|
105
104
  handle_dialog_opening(event)
106
105
  end
107
- # client.on('Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails));
108
- # client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
106
+ @client.on_event('Runtime.exceptionThrown') do |exception|
107
+ handle_exception(exception['exceptionDetails'])
108
+ end
109
+ @client.on_event('Inspector.targetCrashed') do |event|
110
+ handle_target_crashed
111
+ end
109
112
  # client.on('Performance.metrics', event => this._emitMetrics(event));
110
- @client.on_event 'Log.entryAdded' do |event|
113
+ @client.on_event('Log.entryAdded') do |event|
111
114
  handle_log_entry_added(event)
112
115
  end
113
- @client.on_event 'Page.fileChooserOpened' do |event|
116
+ @client.on_event('Page.fileChooserOpened') do |event|
114
117
  handle_file_chooser(event)
115
118
  end
116
119
  @target.is_closed_promise.then do
117
- emit_event 'Events.Page.Close'
120
+ emit_event(PageEmittedEvents::Close)
118
121
  @closed = true
119
122
  end
120
123
  end
@@ -128,43 +131,22 @@ class Puppeteer::Page
128
131
  )
129
132
  end
130
133
 
131
- EVENT_MAPPINGS = {
132
- close: 'Events.Page.Close',
133
- # console: 'Events.Page.Console',
134
- dialog: 'Events.Page.Dialog',
135
- domcontentloaded: 'Events.Page.DOMContentLoaded',
136
- # error:
137
- frameattached: 'Events.Page.FrameAttached',
138
- framedetached: 'Events.Page.FrameDetached',
139
- framenavigated: 'Events.Page.FrameNavigated',
140
- load: 'Events.Page.Load',
141
- # metrics: 'Events.Page.Metrics',
142
- # pageerror: 'Events.Page.PageError',
143
- popup: 'Events.Page.Popup',
144
- request: 'Events.Page.Request',
145
- requestfailed: 'Events.Page.RequestFailed',
146
- requestfinished: 'Events.Page.RequestFinished',
147
- response: 'Events.Page.Response',
148
- # workercreated: 'Events.Page.WorkerCreated',
149
- # workerdestroyed: 'Events.Page.WorkerDestroyed',
150
- }
151
-
152
134
  # @param event_name [Symbol]
153
135
  def on(event_name, &block)
154
- unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
155
- raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
136
+ unless PageEmittedEvents.values.include?(event_name.to_s)
137
+ raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
156
138
  end
157
139
 
158
- add_event_listener(EVENT_MAPPINGS[event_name.to_sym], &block)
140
+ super(event_name.to_s, &block)
159
141
  end
160
142
 
161
143
  # @param event_name [Symbol]
162
144
  def once(event_name, &block)
163
- unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
164
- raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
145
+ unless PageEmittedEvents.values.include?(event_name.to_s)
146
+ raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
165
147
  end
166
148
 
167
- observe_first(EVENT_MAPPINGS[event_name.to_sym], &block)
149
+ super(event_name.to_s, &block)
168
150
  end
169
151
 
170
152
  def handle_file_chooser(event)
@@ -211,19 +193,10 @@ class Puppeteer::Page
211
193
 
212
194
  define_async_method :async_wait_for_file_chooser
213
195
 
214
- # /**
215
- # * @param {!{longitude: number, latitude: number, accuracy: (number|undefined)}} options
216
- # */
217
- # async setGeolocation(options) {
218
- # const { longitude, latitude, accuracy = 0} = options;
219
- # if (longitude < -180 || longitude > 180)
220
- # throw new Error(`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`);
221
- # if (latitude < -90 || latitude > 90)
222
- # throw new Error(`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`);
223
- # if (accuracy < 0)
224
- # throw new Error(`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`);
225
- # await this._client.send('Emulation.setGeolocationOverride', {longitude, latitude, accuracy});
226
- # }
196
+ # @param [Puppeteer::Geolocation]
197
+ def geolocation=(geolocation)
198
+ @client.send_message('Emulation.setGeolocationOverride', geolocation.to_h)
199
+ end
227
200
 
228
201
  attr_reader :javascript_enabled, :target
229
202
 
@@ -238,7 +211,7 @@ class Puppeteer::Page
238
211
  class TargetCrashedError < StandardError; end
239
212
 
240
213
  private def handle_target_crashed
241
- emit_event 'error', TargetCrashedError.new('Page crashed!')
214
+ emit_event(PageEmittedEvents::Error, TargetCrashedError.new('Page crashed!'))
242
215
  end
243
216
 
244
217
  private def handle_log_entry_added(event)
@@ -259,7 +232,7 @@ class Puppeteer::Page
259
232
  url: url,
260
233
  line_number: line_number,
261
234
  )
262
- emit_event('Events.Page.Console',
235
+ emit_event(PageEmittedEvents::Console,
263
236
  Puppeteer::ConsoleMessage.new(level, text, [], console_message_location))
264
237
  end
265
238
  end
@@ -367,47 +340,34 @@ class Puppeteer::Page
367
340
 
368
341
  define_async_method :async_Sx
369
342
 
370
- # /**
371
- # * @param {!Array<string>} urls
372
- # * @return {!Promise<!Array<Network.Cookie>>}
373
- # */
374
- # async cookies(...urls) {
375
- # return (await this._client.send('Network.getCookies', {
376
- # urls: urls.length ? urls : [this.url()]
377
- # })).cookies;
378
- # }
343
+ # @return [Array<Hash>]
344
+ def cookies(*urls)
345
+ @client.send_message('Network.getCookies', urls: (urls.empty? ? [url] : urls))['cookies']
346
+ end
379
347
 
380
- # /**
381
- # * @param {Array<Protocol.Network.deleteCookiesParameters>} cookies
382
- # */
383
- # async deleteCookie(...cookies) {
384
- # const pageURL = this.url();
385
- # for (const cookie of cookies) {
386
- # const item = Object.assign({}, cookie);
387
- # if (!cookie.url && pageURL.startsWith('http'))
388
- # item.url = pageURL;
389
- # await this._client.send('Network.deleteCookies', item);
390
- # }
391
- # }
348
+ def delete_cookie(*cookies)
349
+ page_url = url
350
+ starts_with_http = page_url.start_with?("http")
351
+ cookies.each do |cookie|
352
+ item = (starts_with_http ? { url: page_url } : {}).merge(cookie)
353
+ @client.send_message("Network.deleteCookies", item)
354
+ end
355
+ end
392
356
 
393
- # /**
394
- # * @param {Array<Network.CookieParam>} cookies
395
- # */
396
- # async setCookie(...cookies) {
397
- # const pageURL = this.url();
398
- # const startsWithHTTP = pageURL.startsWith('http');
399
- # const items = cookies.map(cookie => {
400
- # const item = Object.assign({}, cookie);
401
- # if (!item.url && startsWithHTTP)
402
- # item.url = pageURL;
403
- # assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
404
- # assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
405
- # return item;
406
- # });
407
- # await this.deleteCookie(...items);
408
- # if (items.length)
409
- # await this._client.send('Network.setCookies', { cookies: items });
410
- # }
357
+ def set_cookie(*cookies)
358
+ page_url = url
359
+ starts_with_http = page_url.start_with?("http")
360
+ items = cookies.map do |cookie|
361
+ (starts_with_http ? { url: page_url } : {}).merge(cookie).tap do |item|
362
+ raise ArgumentError.new("Blank page can not have cookie \"#{item[:name]}\"") if item[:url] == "about:blank"
363
+ raise ArgumetnError.new("Data URL page can not have cookie \"#{item[:name]}\"") if item[:url]&.start_with?("data:")
364
+ end
365
+ end
366
+ delete_cookie(*items)
367
+ unless items.empty?
368
+ @client.send_message("Network.setCookies", cookies: items)
369
+ end
370
+ end
411
371
 
412
372
  class ScriptTag
413
373
  # @param {!{content?: string, path?: string, type?: string, url?: string}} options
@@ -502,7 +462,7 @@ class Puppeteer::Page
502
462
  # * @param {!Protocol.Performance.metricsPayload} event
503
463
  # */
504
464
  # _emitMetrics(event) {
505
- # this.emit(Events.Page.Metrics, {
465
+ # this.emit(PageEmittedEvents::Metrics, {
506
466
  # title: event.title,
507
467
  # metrics: this._buildMetricsObject(event.metrics)
508
468
  # });
@@ -521,15 +481,14 @@ class Puppeteer::Page
521
481
  # return result;
522
482
  # }
523
483
 
524
- # /**
525
- # * @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
526
- # */
527
- # _handleException(exceptionDetails) {
528
- # const message = helper.getExceptionMessage(exceptionDetails);
529
- # const err = new Error(message);
530
- # err.stack = ''; // Don't report clientside error with a node stack attached
531
- # this.emit(Events.Page.PageError, err);
532
- # }
484
+ class PageError < StandardError ; end
485
+
486
+ private def handle_exception(exception_details)
487
+ message = Puppeteer::ExceptionDetails.new(exception_details).message
488
+ err = PageError.new(message)
489
+ # err.stack = ''; // Don't report clientside error with a node stack attached
490
+ emit_event(PageEmittedEvents::PageError, err)
491
+ end
533
492
 
534
493
  # /**
535
494
  # * @param {!Protocol.Runtime.consoleAPICalledPayload} event
@@ -613,7 +572,7 @@ class Puppeteer::Page
613
572
  # * @param {Protocol.Runtime.StackTrace=} stackTrace
614
573
  # */
615
574
  # _addConsoleMessage(type, args, stackTrace) {
616
- # if (!this.listenerCount(Events.Page.Console)) {
575
+ # if (!this.listenerCount(PageEmittedEvents::Console)) {
617
576
  # args.forEach(arg => arg.dispose());
618
577
  # return;
619
578
  # }
@@ -631,7 +590,7 @@ class Puppeteer::Page
631
590
  # columnNumber: stackTrace.callFrames[0].columnNumber,
632
591
  # } : {};
633
592
  # const message = new ConsoleMessage(type, textTokens.join(' '), args, location);
634
- # this.emit(Events.Page.Console, message);
593
+ # this.emit(PageEmittedEvents::Console, message);
635
594
  # }
636
595
 
637
596
  private def handle_dialog_opening(event)
@@ -643,7 +602,7 @@ class Puppeteer::Page
643
602
  type: dialog_type,
644
603
  message: event['message'],
645
604
  default_value: event['defaultPrompt'])
646
- emit_event('Events.Page.Dialog', dialog)
605
+ emit_event(PageEmittedEvents::Dialog, dialog)
647
606
  end
648
607
 
649
608
  # @return [String]
@@ -726,7 +685,7 @@ class Puppeteer::Page
726
685
 
727
686
  private def session_close_promise
728
687
  @disconnect_promise ||= resolvable_future do |future|
729
- @client.observe_first('Events.CDPSession.Disconnected') do
688
+ @client.observe_first(CDPSessionEmittedEvents::Disconnected) do
730
689
  future.reject(Puppeteer::CDPSession::Error.new('Target Closed'))
731
690
  end
732
691
  end
@@ -746,7 +705,7 @@ class Puppeteer::Page
746
705
  -> (request) { predicate.call(request) }
747
706
  end
748
707
 
749
- wait_for_network_manager_event('Events.NetworkManager.Request',
708
+ wait_for_network_manager_event(NetworkManagerEmittedEvents::Request,
750
709
  predicate: request_predicate,
751
710
  timeout: timeout,
752
711
  )
@@ -780,7 +739,7 @@ class Puppeteer::Page
780
739
  -> (response) { predicate.call(response) }
781
740
  end
782
741
 
783
- wait_for_network_manager_event('Events.NetworkManager.Response',
742
+ wait_for_network_manager_event(NetworkManagerEmittedEvents::Response,
784
743
  predicate: response_predicate,
785
744
  timeout: timeout,
786
745
  )
@@ -907,15 +866,28 @@ class Puppeteer::Page
907
866
  main_frame.title
908
867
  end
909
868
 
910
- # /**
911
- # * @param {!ScreenshotOptions=} options
912
- # * @return {!Promise<!Buffer|!String>}
913
- # */
914
- def screenshot(options = {})
869
+ # @param type [String] "png"|"jpeg"
870
+ # @param path [String]
871
+ # @param full_page [Boolean]
872
+ # @param clip [Hash]
873
+ # @param quality [Integer]
874
+ # @param omit_background [Boolean]
875
+ # @param encoding [String]
876
+ def screenshot(type: nil, path: nil, full_page: nil, clip: nil, quality: nil, omit_background: nil, encoding: nil)
877
+ options = {
878
+ type: type,
879
+ path: path,
880
+ full_page: full_page,
881
+ clip: clip,
882
+ quality: quality,
883
+ omit_background: omit_background,
884
+ encoding: encoding,
885
+ }.compact
915
886
  screenshot_options = ScreenshotOptions.new(options)
916
887
 
917
- # @screenshot_task_queue.post_task(-> { screenshot_task(screenshot_options.type, screenshot_options) })
918
- screenshot_task(screenshot_options.type, screenshot_options)
888
+ @screenshot_task_queue.post_task do
889
+ screenshot_task(screenshot_options.type, screenshot_options)
890
+ end
919
891
  end
920
892
 
921
893
  # @param {"png"|"jpeg"} format
@@ -939,16 +911,16 @@ class Puppeteer::Page
939
911
  clip = { x: 0, y: 0, width: width, height: height, scale: 1 }
940
912
 
941
913
  screen_orientation =
942
- if @viewport.landscape?
914
+ if @viewport&.landscape?
943
915
  { angle: 90, type: 'landscapePrimary' }
944
916
  else
945
917
  { angle: 0, type: 'portraitPrimary' }
946
918
  end
947
919
  @client.send_message('Emulation.setDeviceMetricsOverride',
948
- mobile: @viewport.mobile?,
920
+ mobile: @viewport&.mobile? || false,
949
921
  width: width,
950
922
  height: height,
951
- deviceScaleFactor: @viewport.device_scale_factor,
923
+ deviceScaleFactor: @viewport&.device_scale_factor || 1,
952
924
  screenOrientation: screen_orientation)
953
925
  end
954
926
 
@@ -1043,6 +1015,12 @@ class Puppeteer::Page
1043
1015
  else
1044
1016
  @client.connection.send_message('Target.closeTarget', targetId: @target.target_id)
1045
1017
  await @target.is_closed_promise
1018
+
1019
+ # @closed sometimes remains false, so wait for @closed = true with 100ms timeout.
1020
+ 25.times do
1021
+ break if @closed
1022
+ sleep 0.004
1023
+ end
1046
1024
  end
1047
1025
  end
1048
1026