puppeteer-ruby 0.40.4 → 0.40.7

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.
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