puppeteer-ruby 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/docs/Puppeteer.html +3 -3
  3. data/docs/Puppeteer/AsyncAwaitBehavior.html +1 -1
  4. data/docs/Puppeteer/Browser.html +2 -2
  5. data/docs/Puppeteer/BrowserContext.html +1 -1
  6. data/docs/Puppeteer/BrowserFetcher.html +1 -1
  7. data/docs/Puppeteer/BrowserRunner.html +1 -1
  8. data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +1 -1
  9. data/docs/Puppeteer/CDPSession.html +1 -1
  10. data/docs/Puppeteer/CDPSession/Error.html +1 -1
  11. data/docs/Puppeteer/ConcurrentRubyUtils.html +1 -1
  12. data/docs/Puppeteer/Connection.html +1 -1
  13. data/docs/Puppeteer/Connection/MessageCallback.html +1 -1
  14. data/docs/Puppeteer/Connection/ProtocolError.html +1 -1
  15. data/docs/Puppeteer/Connection/RequestDebugPrinter.html +1 -1
  16. data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +1 -1
  17. data/docs/Puppeteer/ConsoleMessage.html +1 -1
  18. data/docs/Puppeteer/ConsoleMessage/Location.html +1 -1
  19. data/docs/Puppeteer/DOMWorld.html +1 -1
  20. data/docs/Puppeteer/DOMWorld/DetachedError.html +1 -1
  21. data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +1 -1
  22. data/docs/Puppeteer/DebugPrint.html +1 -1
  23. data/docs/Puppeteer/Device.html +1 -1
  24. data/docs/Puppeteer/Devices.html +1 -1
  25. data/docs/Puppeteer/ElementHandle.html +525 -207
  26. data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +5 -5
  27. data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +5 -5
  28. data/docs/Puppeteer/ElementHandle/Point.html +40 -29
  29. data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +1 -1
  30. data/docs/Puppeteer/EmulationManager.html +1 -1
  31. data/docs/Puppeteer/EventCallbackable.html +1 -1
  32. data/docs/Puppeteer/EventCallbackable/EventListeners.html +1 -1
  33. data/docs/Puppeteer/ExecutionContext.html +1 -1
  34. data/docs/Puppeteer/ExecutionContext/EvaluationError.html +1 -1
  35. data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +1 -1
  36. data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +1 -1
  37. data/docs/Puppeteer/FileChooser.html +1 -1
  38. data/docs/Puppeteer/Frame.html +1 -1
  39. data/docs/Puppeteer/FrameManager.html +1 -1
  40. data/docs/Puppeteer/FrameManager/NavigationError.html +1 -1
  41. data/docs/Puppeteer/IfPresent.html +1 -1
  42. data/docs/Puppeteer/JSHandle.html +1 -1
  43. data/docs/Puppeteer/Keyboard.html +1 -1
  44. data/docs/Puppeteer/Keyboard/KeyDefinition.html +1 -1
  45. data/docs/Puppeteer/Keyboard/KeyDescription.html +1 -1
  46. data/docs/Puppeteer/Launcher.html +1 -1
  47. data/docs/Puppeteer/Launcher/Base.html +1 -1
  48. data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +1 -1
  49. data/docs/Puppeteer/Launcher/BrowserOptions.html +1 -1
  50. data/docs/Puppeteer/Launcher/Chrome.html +1 -1
  51. data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +1 -1
  52. data/docs/Puppeteer/Launcher/ChromeArgOptions.html +1 -1
  53. data/docs/Puppeteer/Launcher/LaunchOptions.html +1 -1
  54. data/docs/Puppeteer/LifecycleWatcher.html +1 -1
  55. data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +1 -1
  56. data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +1 -1
  57. data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +1 -1
  58. data/docs/Puppeteer/Mouse.html +1 -1
  59. data/docs/Puppeteer/Mouse/Button.html +1 -1
  60. data/docs/Puppeteer/NetworkManager.html +1 -1
  61. data/docs/Puppeteer/NetworkManager/Credentials.html +1 -1
  62. data/docs/Puppeteer/Page.html +2 -2
  63. data/docs/Puppeteer/Page/FileChooserTimeoutError.html +1 -1
  64. data/docs/Puppeteer/Page/ScreenshotOptions.html +1 -1
  65. data/docs/Puppeteer/Page/ScriptTag.html +1 -1
  66. data/docs/Puppeteer/Page/StyleTag.html +1 -1
  67. data/docs/Puppeteer/Page/TargetCrashedError.html +1 -1
  68. data/docs/Puppeteer/RemoteObject.html +110 -39
  69. data/docs/Puppeteer/Target.html +138 -116
  70. data/docs/Puppeteer/Target/InitializeFailure.html +1 -1
  71. data/docs/Puppeteer/Target/TargetInfo.html +1 -1
  72. data/docs/Puppeteer/TimeoutError.html +2 -2
  73. data/docs/Puppeteer/TimeoutSettings.html +1 -1
  74. data/docs/Puppeteer/TouchScreen.html +1 -1
  75. data/docs/Puppeteer/Viewport.html +81 -1
  76. data/docs/Puppeteer/WaitTask.html +1 -1
  77. data/docs/Puppeteer/WaitTask/TerminatedError.html +1 -1
  78. data/docs/Puppeteer/WaitTask/TimeoutError.html +1 -1
  79. data/docs/Puppeteer/WebSocket.html +26 -26
  80. data/docs/Puppeteer/WebSocket/DriverImpl.html +1 -1
  81. data/docs/Puppeteer/WebSocketTransport.html +2 -2
  82. data/docs/_index.html +26 -12
  83. data/docs/class_list.html +1 -1
  84. data/docs/file.README.html +1 -1
  85. data/docs/index.html +1 -1
  86. data/docs/method_list.html +675 -571
  87. data/docs/top-level-namespace.html +1 -1
  88. data/lib/puppeteer/browser.rb +1 -1
  89. data/lib/puppeteer/element_handle.rb +66 -108
  90. data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
  91. data/lib/puppeteer/element_handle/box_model.rb +19 -0
  92. data/lib/puppeteer/element_handle/point.rb +26 -0
  93. data/lib/puppeteer/errors.rb +1 -3
  94. data/lib/puppeteer/page.rb +1 -1
  95. data/lib/puppeteer/remote_object.rb +9 -0
  96. data/lib/puppeteer/target.rb +9 -12
  97. data/lib/puppeteer/version.rb +1 -1
  98. data/lib/puppeteer/viewport.rb +18 -0
  99. data/lib/puppeteer/web_socket.rb +3 -1
  100. data/lib/puppeteer/web_socket_transport.rb +1 -1
  101. metadata +5 -2
@@ -116,7 +116,7 @@
116
116
  </div>
117
117
 
118
118
  <div id="footer">
119
- Generated on Tue Jun 9 00:13:39 2020 by
119
+ Generated on Fri Jun 12 12:38:32 2020 by
120
120
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
121
121
  0.9.24 (ruby-2.6.3).
122
122
  </div>
@@ -119,7 +119,7 @@ class Puppeteer::Browser
119
119
  target = @targets[target_id]
120
120
  target.ignore_initialize_callback_promise
121
121
  @targets.delete(target_id)
122
- target.handle_closed
122
+ target.closed_callback
123
123
  if await target.initialized_promise
124
124
  emit_event 'Events.Browser.TargetDestroyed', target
125
125
  target.browser_context.emit_event 'Events.BrowserContext.TargetDestroyed', target
@@ -1,4 +1,6 @@
1
- require 'mime/types'
1
+ require_relative './element_handle/bounding_box'
2
+ require_relative './element_handle/box_model'
3
+ require_relative './element_handle/point'
2
4
 
3
5
  class Puppeteer::ElementHandle < Puppeteer::JSHandle
4
6
  include Puppeteer::IfPresent
@@ -53,29 +55,6 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
53
55
  sleep 0.16
54
56
  end
55
57
 
56
- class Point
57
- def initialize(x:, y:)
58
- @x = x
59
- @y = y
60
- end
61
-
62
- def +(other)
63
- Point.new(
64
- x: @x + other.x,
65
- y: @y + other.y,
66
- )
67
- end
68
-
69
- def /(num)
70
- Point.new(
71
- x: @x / num,
72
- y: @y / num,
73
- )
74
- end
75
-
76
- attr_reader :x, :y
77
- end
78
-
79
58
  class ElementNotVisibleError < StandardError
80
59
  def initialize
81
60
  super("Node is either not visible or not an HTMLElement")
@@ -105,15 +84,6 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
105
84
  quads.first.reduce(:+) / 4
106
85
  end
107
86
 
108
- # /**
109
- # * @return {!Promise<void|Protocol.DOM.getBoxModelReturnValue>}
110
- # */
111
- # _getBoxModel() {
112
- # return this._client.send('DOM.getBoxModel', {
113
- # objectId: this._remoteObject.objectId
114
- # }).catch(error => debugError(error));
115
- # }
116
-
117
87
  # @param quad [Array<number>]
118
88
  # @return [Array<Point>]
119
89
  private def from_protocol_quad(quad)
@@ -265,89 +235,77 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
265
235
  press(key, delay: delay)
266
236
  end
267
237
 
268
- # /**
269
- # * @return {!Promise<?{x: number, y: number, width: number, height: number}>}
270
- # */
271
- # async boundingBox() {
272
- # const result = await this._getBoxModel();
273
-
274
- # if (!result)
275
- # return null;
276
-
277
- # const quad = result.model.border;
278
- # const x = Math.min(quad[0], quad[2], quad[4], quad[6]);
279
- # const y = Math.min(quad[1], quad[3], quad[5], quad[7]);
280
- # const width = Math.max(quad[0], quad[2], quad[4], quad[6]) - x;
281
- # const height = Math.max(quad[1], quad[3], quad[5], quad[7]) - y;
282
-
283
- # return {x, y, width, height};
284
- # }
285
-
286
- # /**
287
- # * @return {!Promise<?BoxModel>}
288
- # */
289
- # async boxModel() {
290
- # const result = await this._getBoxModel();
291
-
292
- # if (!result)
293
- # return null;
294
-
295
- # const {content, padding, border, margin, width, height} = result.model;
296
- # return {
297
- # content: this._fromProtocolQuad(content),
298
- # padding: this._fromProtocolQuad(padding),
299
- # border: this._fromProtocolQuad(border),
300
- # margin: this._fromProtocolQuad(margin),
301
- # width,
302
- # height
303
- # };
304
- # }
305
-
306
- # /**
307
- # *
308
- # * @param {!Object=} options
309
- # * @returns {!Promise<string|!Buffer>}
310
- # */
311
- # async screenshot(options = {}) {
312
- # let needsViewportReset = false;
313
-
314
- # let boundingBox = await this.boundingBox();
315
- # assert(boundingBox, 'Node is either not visible or not an HTMLElement');
316
-
317
- # const viewport = this._page.viewport();
318
-
319
- # if (viewport && (boundingBox.width > viewport.width || boundingBox.height > viewport.height)) {
320
- # const newViewport = {
321
- # width: Math.max(viewport.width, Math.ceil(boundingBox.width)),
322
- # height: Math.max(viewport.height, Math.ceil(boundingBox.height)),
323
- # };
324
- # await this._page.setViewport(Object.assign({}, viewport, newViewport));
238
+ # @return [BoundingBox|nil]
239
+ def bounding_box
240
+ if_present(box_model) do |result_model|
241
+ quads = result_model.border
242
+
243
+ x = quads.map(&:x).min
244
+ y = quads.map(&:y).min
245
+ BoundingBox.new(
246
+ x: x,
247
+ y: y,
248
+ width: quads.map(&:x).max - x,
249
+ height: quads.map(&:y).max - y,
250
+ )
251
+ end
252
+ end
325
253
 
326
- # needsViewportReset = true;
327
- # }
254
+ # @return [BoxModel|nil]
255
+ def box_model
256
+ if_present(@remote_object.box_model(@client)) do |result|
257
+ BoxModel.new(result['model'])
258
+ end
259
+ end
328
260
 
329
- # await this._scrollIntoViewIfNeeded();
261
+ def screenshot(options = {})
262
+ needs_viewport_reset = false
330
263
 
331
- # boundingBox = await this.boundingBox();
332
- # assert(boundingBox, 'Node is either not visible or not an HTMLElement');
333
- # assert(boundingBox.width !== 0, 'Node has 0 width.');
334
- # assert(boundingBox.height !== 0, 'Node has 0 height.');
264
+ box = bounding_box
265
+ unless box
266
+ raise ElementNotVisibleError.new
267
+ end
335
268
 
336
- # const { layoutViewport: { pageX, pageY } } = await this._client.send('Page.getLayoutMetrics');
269
+ viewport = @page.viewport
270
+ if viewport && (box.width > viewport.width || box.height > viewport.height)
271
+ new_viewport = viewport.merge(
272
+ width: [viewport.width, box.width.to_i].min,
273
+ height: [viewport.height, box.height.to_i].min,
274
+ )
275
+ @page.viewport = new_viewport
337
276
 
338
- # const clip = Object.assign({}, boundingBox);
339
- # clip.x += pageX;
340
- # clip.y += pageY;
277
+ needs_viewport_reset = true
278
+ end
279
+ scroll_into_view_if_needed
341
280
 
342
- # const imageData = await this._page.screenshot(Object.assign({}, {
343
- # clip
344
- # }, options));
281
+ box = bounding_box
282
+ unless box
283
+ raise ElementNotVisibleError.new
284
+ end
285
+ if box.width == 0
286
+ raise 'Node has 0 width.'
287
+ end
288
+ if box.height == 0
289
+ raise 'Node has 0 height.'
290
+ end
345
291
 
346
- # if (needsViewportReset)
347
- # await this._page.setViewport(viewport);
292
+ layout_metrics = @client.send_message('Page.getLayoutMetrics')
293
+ page_x = layout_metrics["layoutViewport"]["pageX"]
294
+ page_y = layout_metrics["layoutViewport"]["pageY"]
295
+
296
+ clip = {
297
+ x: page_x + box.x,
298
+ y: page_y + box.y,
299
+ width: box.width,
300
+ height: box.height,
301
+ }
348
302
 
349
- # return imageData;
350
- # }
303
+ @page.screenshot({ clip: clip }.merge(options))
304
+ ensure
305
+ if needs_viewport_reset
306
+ @page.viewport = viewport
307
+ end
308
+ end
351
309
 
352
310
  # `$()` in JavaScript. $ is not allowed to use as a method name in Ruby.
353
311
  # @param selector [String]
@@ -0,0 +1,12 @@
1
+ class Puppeteer::ElementHandle < Puppeteer::JSHandle
2
+ class BoundingBox
3
+ def initialize(x:, y:, width:, height:)
4
+ @x = x
5
+ @y = y
6
+ @width = width
7
+ @height = height
8
+ end
9
+
10
+ attr_reader :x, :y, :width, :height
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ class Puppeteer::ElementHandle < Puppeteer::JSHandle
2
+ class BoxModel
3
+ QUAD_ATTRIBUTE_NAMES = %i(content padding border margin)
4
+ # @param result [Hash]
5
+ def initialize(result_model)
6
+ QUAD_ATTRIBUTE_NAMES.each do |attr_name|
7
+ quad = result_model[attr_name.to_s]
8
+ instance_variable_set(
9
+ :"@#{attr_name}",
10
+ quad.each_slice(2).map { |x, y| Point.new(x: x, y: y) },
11
+ )
12
+ end
13
+ @width = result_model['width']
14
+ @height = result_model['height']
15
+ end
16
+ attr_reader(*QUAD_ATTRIBUTE_NAMES)
17
+ attr_reader :width, :height
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ class Puppeteer::ElementHandle < Puppeteer::JSHandle
2
+ # A class to represent (x, y)-coordinates
3
+ # supporting + and / operators.
4
+ class Point
5
+ def initialize(x:, y:)
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def +(other)
11
+ Point.new(
12
+ x: @x + other.x,
13
+ y: @y + other.y,
14
+ )
15
+ end
16
+
17
+ def /(num)
18
+ Point.new(
19
+ x: @x / num,
20
+ y: @y / num,
21
+ )
22
+ end
23
+
24
+ attr_reader :x, :y
25
+ end
26
+ end
@@ -1,4 +1,2 @@
1
- # ref: https://github.com/puppeteer/puppeteer/blob/master/lib/Errors.js
1
+ # ref: https://github.com/puppeteer/puppeteer/blob/master/src/Errors.ts
2
2
  class Puppeteer::TimeoutError < StandardError; end
3
-
4
- class Puppeteer::WebSocktTransportError < StandardError; end
@@ -109,7 +109,7 @@ class Puppeteer::Page
109
109
  @client.on_event 'Page.fileChooserOpened' do |event|
110
110
  handle_file_chooser(event)
111
111
  end
112
- @target.on_close do
112
+ @target.is_closed_promise.then do
113
113
  emit_event 'Events.Page.Close'
114
114
  @closed = true
115
115
  end
@@ -62,6 +62,15 @@ class Puppeteer::RemoteObject
62
62
  client.send_message('DOM.getContentQuads', objectId: @object_id)
63
63
  end
64
64
 
65
+ # used in ElementHandle#_box_model
66
+ def box_model(client)
67
+ client.send_message('DOM.getBoxModel', objectId: @object_id)
68
+ rescue => err
69
+ debug_puts(err)
70
+ nil
71
+ end
72
+
73
+
65
74
  # helper#valueFromRemoteObject
66
75
  def value
67
76
  if @unserializable_value
@@ -37,7 +37,7 @@ class Puppeteer::Target
37
37
  @initialized_promise = @initialize_callback_promise.then do |success|
38
38
  handle_initialized(success)
39
39
  end
40
- # this._isClosedPromise = new Promise(fulfill => this._closedCallback = fulfill);
40
+ @is_closed_promise = resolvable_future
41
41
 
42
42
  @is_initialized = @target_info.type != 'page' || !@target_info.url.empty?
43
43
 
@@ -46,12 +46,18 @@ class Puppeteer::Target
46
46
  end
47
47
  end
48
48
 
49
- attr_reader :target_id, :initialized_promise
49
+ attr_reader :target_id, :initialized_promise, :is_closed_promise
50
+
51
+ def closed_callback
52
+ @is_closed_promise.fulfill(true)
53
+ end
50
54
 
51
55
  class InitializeFailure < StandardError; end
52
56
 
53
57
  def ignore_initialize_callback_promise
54
- @initialize_callback_promise.fulfill(false)
58
+ unless @initialize_callback_promise.fulfilled?
59
+ @initialize_callback_promise.fulfill(false)
60
+ end
55
61
  end
56
62
 
57
63
  private def handle_initialized(success)
@@ -70,15 +76,6 @@ class Puppeteer::Target
70
76
  true
71
77
  end
72
78
 
73
- def handle_closed
74
- @closed = true
75
- @on_close&.call
76
- end
77
-
78
- def on_close(&block)
79
- @on_close = block
80
- end
81
-
82
79
  def initialized?
83
80
  @is_initialized
84
81
  end
@@ -1,3 +1,3 @@
1
1
  class Puppeteer
2
- VERSION = '0.0.9'
2
+ VERSION = '0.0.10'
3
3
  end
@@ -33,4 +33,22 @@ class Puppeteer::Viewport
33
33
  def landscape?
34
34
  @is_landscape
35
35
  end
36
+
37
+ def merge(
38
+ width: nil,
39
+ height: nil,
40
+ device_scale_factor: nil,
41
+ is_mobile: nil,
42
+ has_touch: nil,
43
+ is_landscape: nil)
44
+
45
+ Puppeteer::Viewport.new(
46
+ width: width || @width,
47
+ height: height || @height,
48
+ device_scale_factor: device_scale_factor || @device_scale_factor,
49
+ is_mobile: is_mobile.nil? ? @is_mobile : is_mobile,
50
+ has_touch: has_touch.nil? ? @has_touch : has_touch,
51
+ is_landscape: is_landscape.nil? ? @is_landscape : is_landscape,
52
+ )
53
+ end
36
54
  end
@@ -43,6 +43,8 @@ class Puppeteer::WebSocket
43
43
  end
44
44
  end
45
45
 
46
+ class TransportError < StandardError; end
47
+
46
48
  private def setup
47
49
  @ready_state = STATE_CONNECTING
48
50
  @driver.on(:open) do
@@ -55,7 +57,7 @@ class Puppeteer::WebSocket
55
57
  end
56
58
  @driver.on(:error) do |event|
57
59
  if !handle_on_error(error_message: event.message)
58
- raise Puppeteer::WebSocktTransportError.new(event.message)
60
+ raise TransportError.new(event.message)
59
61
  end
60
62
  end
61
63
  @driver.on(:message) do |event|
@@ -11,7 +11,7 @@ class Puppeteer::WebSocketTransport
11
11
  promise.fulfill(Puppeteer::WebSocketTransport.new(ws))
12
12
  end
13
13
  ws.on_error do |error_message|
14
- promise.reject(Puppeteer::WebSocktTransportError.new(error_message))
14
+ promise.reject(Puppeteer::WebSocket::TransportError.new(error_message))
15
15
  end
16
16
  promise.value!
17
17
  end
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.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-08 00:00:00.000000000 Z
11
+ date: 2020-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -294,6 +294,9 @@ files:
294
294
  - lib/puppeteer/devices.rb
295
295
  - lib/puppeteer/dom_world.rb
296
296
  - lib/puppeteer/element_handle.rb
297
+ - lib/puppeteer/element_handle/bounding_box.rb
298
+ - lib/puppeteer/element_handle/box_model.rb
299
+ - lib/puppeteer/element_handle/point.rb
297
300
  - lib/puppeteer/emulation_manager.rb
298
301
  - lib/puppeteer/errors.rb
299
302
  - lib/puppeteer/event_callbackable.rb