puppeteer-ruby 0.40.4 → 0.40.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1c608c27cbcee1c2038a3ecb2ba5244ef75906136fdd7aa868c521cd8248053
4
- data.tar.gz: 9535f70cb9b6056324c9828fff4c9e4412e0fbd48c2ac7a7bd8308bc51d1d26c
3
+ metadata.gz: 674e5731f3d469805214a3ddb7e56ae83aaaa6850db3ccddd02002cffe4e1ca4
4
+ data.tar.gz: 47f5ad6e1a7b30c394ce950991c067c9b2dd42c144ec561eaa3dbbc9efb9b77a
5
5
  SHA512:
6
- metadata.gz: 4d9da0c4e2820117bff76f55bf5c9141c1b2ac8af351f6c27951df5bb20c5825a321c33f4ddde13b1e77864fd1c29803d5eb5f014df80d1b596a850a2d7f0ac3
7
- data.tar.gz: f6159e8906c6f35b67057ef47e4e675bfeeb824ee7abaee0d52f5d25ef7bea6f6c7fe699af3a8fee9bbd1020a7894966ee4826d38d01d74e4860f8ead4b759c7
6
+ metadata.gz: b4f53e004dbbba48ebfaa5a1197d5bfdf9d2364a6bd84edf94d378b4b193661f0dc43de51fd61e009d91d5ca1eff7afb62e824fc23ce6bfc6dfa2b36aeda0457
7
+ data.tar.gz: 537e1dc87b4fa9d7644035e1a7a590ec32d64275ee7166940a9e6454b94997b873b1e06c1f2f8ad25c33f39caed4eb05601de46808f09748e13f9db15868c750
data/CHANGELOG.md CHANGED
@@ -1,7 +1,21 @@
1
- ### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.4...main)]
1
+ ### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.7...main)]
2
2
 
3
3
  - xxx
4
4
 
5
+ ### 0.40.7 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.6...0.40.7)]
6
+
7
+ - Port Puppeteer v13.6-v13.7 features.
8
+
9
+ ### 0.40.6 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.5...0.40.6)]
10
+
11
+ - Port Puppeteer v13.1-v13.5 features mainly for request interception.
12
+
13
+ ### 0.40.5 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.4...0.40.5)]
14
+
15
+ Bugfix:
16
+
17
+ - Port Puppeteer v13.1-v13.5 bugfixes mainly for OOPIFs.
18
+
5
19
  ### 0.40.4 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.3...0.40.4)]
6
20
 
7
21
  Bugfix:
data/README.md CHANGED
@@ -229,6 +229,13 @@ end
229
229
 
230
230
  https://yusukeiwaki.github.io/puppeteer-ruby-docs/
231
231
 
232
+ ## Limitations
233
+
234
+ ### Not compatible with Firefox >= v97.0
235
+
236
+ :sos: Help and contribution wanted! :sos:
237
+ https://github.com/YusukeIwaki/puppeteer-ruby/issues/220
238
+
232
239
  ## Contributing
233
240
 
234
241
  Bug reports and pull requests are welcome on GitHub at https://github.com/YusukeIwaki/puppeteer-ruby.
data/docs/api_coverage.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # API coverages
2
- - Puppeteer version: v13.5.1
3
- - puppeteer-ruby version: 0.40.4
2
+ - Puppeteer version: v13.5.2
3
+ - puppeteer-ruby version: 0.40.7
4
4
 
5
5
  ## Puppeteer
6
6
 
@@ -310,8 +310,8 @@
310
310
  * frame
311
311
  * headers
312
312
  * initiator
313
- * ~~interceptResolutionState~~
314
- * ~~isInterceptResolutionHandled~~
313
+ * interceptResolutionState => `#intercept_resolution_state`
314
+ * isInterceptResolutionHandled => `#intercept_resolution_handled?`
315
315
  * isNavigationRequest => `#navigation_request?`
316
316
  * method
317
317
  * postData => `#post_data`
@@ -128,7 +128,7 @@ class Puppeteer::BrowserRunner
128
128
  def close
129
129
  return if @closed
130
130
 
131
- if @using_temp_user_data_dir && !@for_firefox
131
+ if @using_temp_user_data_dir
132
132
  kill
133
133
  elsif @connection
134
134
  begin
@@ -191,6 +191,7 @@ class Puppeteer::Connection
191
191
  'Network.responseReceived',
192
192
  'Network.responseReceivedExtraInfo',
193
193
  'Page.lifecycleEvent',
194
+ 'Target.receivedMessageFromTarget', # only Firefox
194
195
  ]
195
196
 
196
197
  def handle_message(message)
@@ -2,12 +2,13 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
2
2
  class BoxModel
3
3
  QUAD_ATTRIBUTE_NAMES = %i(content padding border margin)
4
4
  # @param result [Hash]
5
- def initialize(result_model)
5
+ # @param offset [Point]
6
+ def initialize(result_model, offset:)
6
7
  QUAD_ATTRIBUTE_NAMES.each do |attr_name|
7
8
  quad = result_model[attr_name.to_s]
8
9
  instance_variable_set(
9
10
  :"@#{attr_name}",
10
- quad.each_slice(2).map { |x, y| Point.new(x: x, y: y) },
11
+ quad.each_slice(2).map { |x, y| Point.new(x: x, y: y) + offset },
11
12
  )
12
13
  end
13
14
  @width = result_model['width']
@@ -11,10 +11,12 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
11
11
  # @param context [Puppeteer::ExecutionContext]
12
12
  # @param client [Puppeteer::CDPSession]
13
13
  # @param remote_object [Puppeteer::RemoteObject]
14
+ # @param frame [Puppeteer::Frame]
14
15
  # @param page [Puppeteer::Page]
15
16
  # @param frame_manager [Puppeteer::FrameManager]
16
- def initialize(context:, client:, remote_object:, page:, frame_manager:)
17
+ def initialize(context:, client:, remote_object:, frame:, page:, frame_manager:)
17
18
  super(context: context, client: client, remote_object: remote_object)
19
+ @frame = frame
18
20
  @page = page
19
21
  @frame_manager = frame_manager
20
22
  @disposed = false
@@ -134,6 +136,37 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
134
136
  end
135
137
  end
136
138
 
139
+ class ElementNotClickableError < StandardError
140
+ def initialize
141
+ super("Node is either not clickable or not an HTMLElement")
142
+ end
143
+ end
144
+
145
+ # @param quad [Array<Array<Point>>]]
146
+ # @param offset [Point]
147
+ private def apply_offsets_to_quad(quad, offset)
148
+ quad.map { |part| part + offset }
149
+ end
150
+
151
+ # @param frame [Puppeteer::Frame]
152
+ # @return [Point]
153
+ private def oopif_offsets(frame)
154
+ offset = Point.new(x: 0, y: 0)
155
+ while frame.parent_frame
156
+ parent = frame.parent_frame
157
+ unless frame.oop_frame?
158
+ frame = parent
159
+ next
160
+ end
161
+ backend_node_id = parent._client.send_message('DOM.getFrameOwner', frameId: frame.id)['backendNodeId']
162
+ result = parent._client.send_message('DOM.getBoxModel', backendNodeId: backend_node_id)
163
+ break unless result
164
+ offset = BoxModel.new(result['model'], offset: offset).content.first
165
+ frame = parent
166
+ end
167
+ offset
168
+ end
169
+
137
170
  def clickable_point(offset = nil)
138
171
  offset_param = Offset.from(offset)
139
172
 
@@ -150,12 +183,22 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
150
183
  end
151
184
 
152
185
  # Filter out quads that have too small area to click into.
153
- layout_metrics = @client.send_message('Page.getLayoutMetrics')
154
- client_width = layout_metrics["layoutViewport"]["clientWidth"]
155
- client_height = layout_metrics["layoutViewport"]["clientHeight"]
186
+ layout_metrics = @page.client.send_message('Page.getLayoutMetrics')
187
+
188
+ if result.empty? || result["quads"].empty?
189
+ raise ElementNotClickableError.new
190
+ end
191
+
192
+ # Filter out quads that have too small area to click into.
193
+ # Fallback to `layoutViewport` in case of using Firefox.
194
+ layout_viewport = layout_metrics["cssLayoutViewport"] || layout_metrics["layoutViewport"]
195
+ client_width = layout_viewport["clientWidth"]
196
+ client_height = layout_viewport["clientHeight"]
156
197
 
198
+ oopif_offset = oopif_offsets(@frame)
157
199
  quads = result["quads"].
158
200
  map { |quad| from_protocol_quad(quad) }.
201
+ map { |quad| apply_offsets_to_quad(quad, oopif_offset) }.
159
202
  map { |quad| intersect_quad_with_viewport(quad, client_width, client_height) }.
160
203
  select { |quad| compute_quad_area(quad) > 1 }
161
204
  if quads.empty?
@@ -357,13 +400,14 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
357
400
  # @return [BoundingBox|nil]
358
401
  def bounding_box
359
402
  if_present(box_model) do |result_model|
403
+ offset = oopif_offsets(@frame)
360
404
  quads = result_model.border
361
405
 
362
406
  x = quads.map(&:x).min
363
407
  y = quads.map(&:y).min
364
408
  BoundingBox.new(
365
- x: x,
366
- y: y,
409
+ x: x + offset.x,
410
+ y: y + offset.y,
367
411
  width: quads.map(&:x).max - x,
368
412
  height: quads.map(&:y).max - y,
369
413
  )
@@ -373,7 +417,7 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
373
417
  # @return [BoxModel|nil]
374
418
  def box_model
375
419
  if_present(@remote_object.box_model(@client)) do |result|
376
- BoxModel.new(result['model'])
420
+ BoxModel.new(result['model'], offset: oopif_offsets(@frame))
377
421
  end
378
422
  end
379
423
 
@@ -96,6 +96,7 @@ module FrameManagerEmittedEvents ; end
96
96
  FrameAttached: EventsDefinitionUtils.symbol('FrameManager.FrameAttached'),
97
97
  FrameNavigated: EventsDefinitionUtils.symbol('FrameManager.FrameNavigated'),
98
98
  FrameDetached: EventsDefinitionUtils.symbol('FrameManager.FrameDetached'),
99
+ FrameSwapped: EventsDefinitionUtils.symbol('FrameManager.FrameSwapped'),
99
100
  LifecycleEvent: EventsDefinitionUtils.symbol('FrameManager.LifecycleEvent'),
100
101
  FrameNavigatedWithinDocument: EventsDefinitionUtils.symbol('FrameManager.FrameNavigatedWithinDocument'),
101
102
  ExecutionContextCreated: EventsDefinitionUtils.symbol('FrameManager.ExecutionContextCreated'),
@@ -178,7 +178,7 @@ class Puppeteer::FrameManager
178
178
  frame = @frames[event['targetInfo']['targetId']]
179
179
  session = Puppeteer::Connection.from_session(@client).session(event['sessionId'])
180
180
 
181
- frame.send(:update_client, session)
181
+ frame&.send(:update_client, session)
182
182
  setup_listeners(session)
183
183
  async_init(session)
184
184
  end
@@ -353,6 +353,8 @@ class Puppeteer::FrameManager
353
353
  if frame
354
354
  remove_frame_recursively(frame)
355
355
  end
356
+ elsif reason == 'swap'
357
+ emit_event(FrameManagerEmittedEvents::FrameSwapped, frame)
356
358
  end
357
359
  end
358
360
 
@@ -2,6 +2,8 @@ class Puppeteer::HTTPRequest
2
2
  include Puppeteer::DebugPrint
3
3
  include Puppeteer::IfPresent
4
4
 
5
+ DEFAULT_INTERCEPT_RESOLUTION_PRIORITY = 0
6
+
5
7
  # defines some methods used only in NetworkManager, Response
6
8
  class InternalAccessor
7
9
  def initialize(request)
@@ -38,6 +40,43 @@ class Puppeteer::HTTPRequest
38
40
  end
39
41
  end
40
42
 
43
+ class InterceptResolutionState
44
+ def self.abort(priority: nil)
45
+ new(action: 'abort', priority: priority)
46
+ end
47
+
48
+ def self.respond(priority: nil)
49
+ new(action: 'respond', priority: priority)
50
+ end
51
+
52
+ def self.continue(priority: nil)
53
+ new(action: 'continue', priority: priority)
54
+ end
55
+
56
+ def self.disabled(priority: nil)
57
+ new(action: 'disabled', priority: priority)
58
+ end
59
+
60
+ def self.none(priority: nil)
61
+ new(action: 'none', priority: priority)
62
+ end
63
+
64
+ def self.already_handled(priority: nil)
65
+ new(action: 'already-handled', priority: priority)
66
+ end
67
+
68
+ private def initialize(action:, priority:)
69
+ @action = action
70
+ @priority = priority
71
+ end
72
+
73
+ def priority_unspecified?
74
+ @priority.nil?
75
+ end
76
+
77
+ attr_reader :action, :priority
78
+ end
79
+
41
80
  # @param client [Puppeteer::CDPSession]
42
81
  # @param frame [Puppeteer::Frame]
43
82
  # @param interception_id [string|nil]
@@ -57,9 +96,8 @@ class Puppeteer::HTTPRequest
57
96
  @frame = frame
58
97
  @redirect_chain = redirect_chain
59
98
  @continue_request_overrides = {}
60
- @current_strategy = 'none'
61
- @current_priority = nil
62
- @intercept_actions = []
99
+ @intercept_resolution_state = InterceptResolutionState.none
100
+ @intercept_handlers = []
63
101
  @initiator = event['initiator']
64
102
 
65
103
  @headers = {}
@@ -115,19 +153,29 @@ class Puppeteer::HTTPRequest
115
153
  @abort_error_reason
116
154
  end
117
155
 
118
- # @returns An array of the current intercept resolution strategy and priority
119
- # `[strategy,priority]`. Strategy is one of: `abort`, `respond`, `continue`,
120
- # `disabled`, `none`, or `already-handled`.
121
- def intercept_resolution
156
+ # @returns An InterceptResolutionState object describing the current resolution
157
+ # action and priority.
158
+ #
159
+ # InterceptResolutionState contains:
160
+ # action: InterceptResolutionAction
161
+ # priority?: number
162
+ #
163
+ # InterceptResolutionAction is one of: `abort`, `respond`, `continue`,
164
+ # `disabled`, `none`, or `alreay-handled`
165
+ def intercept_resolution_state
122
166
  if !@allow_interception
123
- ['disabled']
167
+ InterceptResolutionState.disabled
124
168
  elsif @interception_handled
125
- ['already-handled']
169
+ InterceptResolutionState.already_handled
126
170
  else
127
- [@current_strategy, @current_priority]
171
+ @intercept_resolution_state.dup
128
172
  end
129
173
  end
130
174
 
175
+ def intercept_resolution_handled?
176
+ @interception_handled
177
+ end
178
+
131
179
  # Adds an async request handler to the processing queue.
132
180
  # Deferred handlers are not guaranteed to execute in any particular order,
133
181
  # but they are guarnateed to resolve before the request interception
@@ -135,19 +183,19 @@ class Puppeteer::HTTPRequest
135
183
  #
136
184
  # @param pending_handler [Proc]
137
185
  def enqueue_intercept_action(pending_handler)
138
- @intercept_actions << pending_handler
186
+ @intercept_handlers << pending_handler
139
187
  end
140
188
 
141
189
  # Awaits pending interception handlers and then decides how to fulfill
142
190
  # the request interception.
143
191
  def finalize_interceptions
144
- @intercept_actions.each(&:call)
145
- case @intercept_resolution
146
- when :abort
192
+ @intercept_handlers.each(&:call)
193
+ case intercept_resolution_state.action
194
+ when 'abort'
147
195
  abort_impl(**@abort_error_reason)
148
- when :respond
196
+ when 'respond'
149
197
  respond_impl(**@response_for_request)
150
- when :continue
198
+ when 'continue'
151
199
  continue_impl(@continue_request_overrides)
152
200
  end
153
201
  end
@@ -169,8 +217,14 @@ class Puppeteer::HTTPRequest
169
217
  private def headers_to_array(headers)
170
218
  return nil unless headers
171
219
 
172
- headers.map do |key, value|
173
- { name: key, value: value.to_s }
220
+ headers.flat_map do |key, value|
221
+ if value.is_a?(Enumerable)
222
+ value.map do |v|
223
+ { name: key, value: v.to_s }
224
+ end
225
+ else
226
+ { name: key, value: value.to_s }
227
+ end
174
228
  end
175
229
  end
176
230
 
@@ -220,17 +274,16 @@ class Puppeteer::HTTPRequest
220
274
  end
221
275
 
222
276
  @continue_request_overrides = overrides
223
- if @current_priority.nil? || priority > @current_priority
224
- @current_strategy = :continue
225
- @current_priority = priority
277
+ if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
278
+ @intercept_resolution_state = InterceptResolutionState.continue(priority: priority)
226
279
  return
227
280
  end
228
281
 
229
- if priority == @current_priority
230
- if @current_strategy == :abort || @current_strategy == :respond
282
+ if priority == @intercept_resolution_state.priority
283
+ if @intercept_resolution_state.action == :abort || @intercept_resolution_state.action == :respond
231
284
  return
232
285
  end
233
- @current_strategy = :continue
286
+ @intercept_resolution_state = InterceptResolutionState.continue(priority: priority)
234
287
  end
235
288
  end
236
289
 
@@ -284,17 +337,16 @@ class Puppeteer::HTTPRequest
284
337
  body: body,
285
338
  }
286
339
 
287
- if @current_priority.nil? || priority > @current_priority
288
- @current_strategy = :respond
289
- @current_priority = priority
340
+ if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
341
+ @intercept_resolution_state = InterceptResolutionState.respond(priority: priority)
290
342
  return
291
343
  end
292
344
 
293
- if priority == @current_priority
294
- if @current_strategy == :abort
345
+ if priority == @intercept_resolution_state.priority
346
+ if @intercept_resolution_state.action == :abort
295
347
  return
296
348
  end
297
- @current_strategy = :respond
349
+ @intercept_resolution_state = InterceptResolutionState.respond(priority: priority)
298
350
  end
299
351
  end
300
352
 
@@ -303,7 +355,12 @@ class Puppeteer::HTTPRequest
303
355
 
304
356
  mock_response_headers = {}
305
357
  headers&.each do |key, value|
306
- mock_response_headers[key.downcase] = value
358
+ mock_response_headers[key.downcase] =
359
+ if value.is_a?(Enumerable)
360
+ value.map(&:to_s)
361
+ else
362
+ value.to_s
363
+ end
307
364
  end
308
365
  if content_type
309
366
  mock_response_headers['content-type'] = content_type
@@ -360,9 +417,8 @@ class Puppeteer::HTTPRequest
360
417
  end
361
418
  @abort_error_reason = error_reason
362
419
 
363
- if @current_priority.nil? || priority > @current_priority
364
- @current_strategy = :abort
365
- @current_priority = priority
420
+ if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
421
+ @intercept_resolution_state = InterceptResolutionState.abort(priority: priority)
366
422
  end
367
423
  end
368
424
 
@@ -12,6 +12,7 @@ class Puppeteer::JSHandle
12
12
  context: context,
13
13
  client: context.client,
14
14
  remote_object: remote_object,
15
+ frame: frame,
15
16
  page: frame_manager.page,
16
17
  frame_manager: frame_manager,
17
18
  )
@@ -122,7 +122,7 @@ module Puppeteer::Launcher
122
122
  '--disable-default-apps',
123
123
  '--disable-dev-shm-usage',
124
124
  '--disable-extensions',
125
- '--disable-features=Translate',
125
+ '--disable-features=Translate,BackForwardCache',
126
126
  '--disable-hang-monitor',
127
127
  '--disable-ipc-flooding-protection',
128
128
  '--disable-popup-blocking',
@@ -77,6 +77,7 @@ class Puppeteer::LifecycleWatcher
77
77
  check_lifecycle_complete
78
78
  end,
79
79
  @frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameNavigatedWithinDocument, &method(:navigated_within_document)),
80
+ @frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameSwapped, &method(:handle_frame_swapped)),
80
81
  @frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameDetached, &method(:handle_frame_detached)),
81
82
  ]
82
83
  @listener_ids['network_manager'] = @frame_manager.network_manager.add_event_listener(NetworkManagerEmittedEvents::Request, &method(:handle_request))
@@ -142,11 +143,21 @@ class Puppeteer::LifecycleWatcher
142
143
  check_lifecycle_complete
143
144
  end
144
145
 
146
+ private def handle_frame_swapped(frame)
147
+ return if frame != @frame
148
+ @swapped = true
149
+ check_lifecycle_complete
150
+ end
151
+
145
152
  private def check_lifecycle_complete
146
153
  # We expect navigation to commit.
147
154
  return unless @expected_lifecycle.completed?(@frame)
148
155
  @lifecycle_promise.fulfill(true) if @lifecycle_promise.pending?
149
156
  if @frame.loader_id == @initial_loader_id && !@has_same_document_navigation
157
+ if @swapped
158
+ @swapped = false
159
+ @new_document_navigation_promise.fulfill(true)
160
+ end
150
161
  return
151
162
  end
152
163
  if @has_same_document_navigation && @same_document_navigation_promise.pending?
@@ -119,4 +119,8 @@ class Puppeteer::NetworkEventManager
119
119
  def get_queued_event_group(network_request_id)
120
120
  @queued_event_group_map[network_request_id]
121
121
  end
122
+
123
+ def forget_queued_event_group(network_request_id)
124
+ @queued_event_group_map.delete(network_request_id)
125
+ end
122
126
  end
@@ -217,6 +217,7 @@ class Puppeteer::NetworkManager
217
217
  # CDP may have sent a Fetch.requestPaused event already. Check for it.
218
218
  if_present(@network_event_manager.get_request_paused(network_request_id)) do |request_paused_event|
219
219
  fetch_request_id = request_paused_event['requestId']
220
+ patch_request_event_headers(event, request_paused_event)
220
221
  handle_request(event, fetch_request_id)
221
222
  @network_event_manager.forget_request_paused(network_request_id)
222
223
  end
@@ -277,12 +278,19 @@ class Puppeteer::NetworkManager
277
278
  end
278
279
 
279
280
  if request_will_be_sent_event
281
+ patch_request_event_headers(request_will_be_sent_event, event)
280
282
  handle_request(request_will_be_sent_event, fetch_request_id)
281
283
  else
282
284
  @network_event_manager.store_request_paused(network_request_id, event)
283
285
  end
284
286
  end
285
287
 
288
+ private def patch_request_event_headers(request_will_be_sent_event, request_paused_event)
289
+ request_will_be_sent_event['request']['headers'].merge!(
290
+ # includes extra headers, like: Accept, Origin
291
+ request_paused_event['request']['headers'])
292
+ end
293
+
286
294
  private def handle_request(event, fetch_request_id)
287
295
  redirect_chain = []
288
296
  if event['redirectResponse']
@@ -387,6 +395,7 @@ class Puppeteer::NetworkManager
387
395
  # We may have skipped response and loading events because we didn't have
388
396
  # this ExtraInfo event yet. If so, emit those events now.
389
397
  if_present(@network_event_manager.get_queued_event_group(event['requestId'])) do |queued_events|
398
+ @network_event_manager.forget_queued_event_group(event['requestId'])
390
399
  emit_response_event(queued_events.response_received_event, event)
391
400
  if_present(queued_events.loading_finished_event) do |loading_finished_event|
392
401
  emit_loading_finished(loading_finished_event)
@@ -227,7 +227,7 @@ class Puppeteer::Page
227
227
  @client.send_message('Emulation.setGeolocationOverride', geolocation.to_h)
228
228
  end
229
229
 
230
- attr_reader :javascript_enabled, :target
230
+ attr_reader :javascript_enabled, :target, :client
231
231
  alias_method :javascript_enabled?, :javascript_enabled
232
232
 
233
233
  def browser
@@ -389,7 +389,18 @@ class Puppeteer::Page
389
389
  @client.send_message('Network.getCookies', urls: (urls.empty? ? [url] : urls))['cookies']
390
390
  end
391
391
 
392
+ # check if each cookie element has required fields ('name' and 'value')
393
+ private def assert_cookie_params(cookies, requires:)
394
+ return if cookies.all? do |cookie|
395
+ requires.all? { |field_name| cookie[field_name] || cookie[field_name.to_s] }
396
+ end
397
+
398
+ raise ArgumentError.new("Each coookie must have #{requires.join(" and ")} attribute.")
399
+ end
400
+
392
401
  def delete_cookie(*cookies)
402
+ assert_cookie_params(cookies, requires: %i(name))
403
+
393
404
  page_url = url
394
405
  starts_with_http = page_url.start_with?("http")
395
406
  cookies.each do |cookie|
@@ -399,12 +410,14 @@ class Puppeteer::Page
399
410
  end
400
411
 
401
412
  def set_cookie(*cookies)
413
+ assert_cookie_params(cookies, requires: %i(name value))
414
+
402
415
  page_url = url
403
416
  starts_with_http = page_url.start_with?("http")
404
417
  items = cookies.map do |cookie|
405
418
  (starts_with_http ? { url: page_url } : {}).merge(cookie).tap do |item|
406
419
  raise ArgumentError.new("Blank page can not have cookie \"#{item[:name]}\"") if item[:url] == "about:blank"
407
- raise ArgumetnError.new("Data URL page can not have cookie \"#{item[:name]}\"") if item[:url]&.start_with?("data:")
420
+ raise ArgumentError.new("Data URL page can not have cookie \"#{item[:name]}\"") if item[:url]&.start_with?("data:")
408
421
  end
409
422
  end
410
423
  delete_cookie(*items)
@@ -508,7 +521,6 @@ class Puppeteer::Page
508
521
  end
509
522
 
510
523
  private def handle_console_api(event)
511
- puts "~~~~~~~~~~~~~~#{event}"
512
524
  if event['executionContextId'] == 0
513
525
  # DevTools protocol stores the last 1000 console messages. These
514
526
  # messages are always reported even for removed execution contexts. In
@@ -1,3 +1,3 @@
1
1
  module Puppeteer
2
- VERSION = '0.40.4'
2
+ VERSION = '0.40.7'
3
3
  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.11.0'
34
34
  spec.add_development_dependency 'rspec_junit_formatter' # for CircleCI.
35
- spec.add_development_dependency 'rubocop', '~> 1.26.0'
35
+ spec.add_development_dependency 'rubocop', '~> 1.29.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.40.4
4
+ version: 0.40.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-10 00:00:00.000000000 Z
11
+ date: 2022-05-10 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.26.0
173
+ version: 1.29.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.26.0
180
+ version: 1.29.0
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rubocop-rspec
183
183
  requirement: !ruby/object:Gem::Requirement