puppeteer-ruby 0.0.5 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/docs/Puppeteer.html +53 -43
  4. data/docs/Puppeteer/AsyncAwaitBehavior.html +1 -1
  5. data/docs/Puppeteer/Browser.html +255 -147
  6. data/docs/Puppeteer/BrowserContext.html +1 -1
  7. data/docs/Puppeteer/BrowserFetcher.html +1 -1
  8. data/docs/Puppeteer/BrowserRunner.html +1 -1
  9. data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +1 -1
  10. data/docs/Puppeteer/CDPSession.html +86 -57
  11. data/docs/Puppeteer/CDPSession/Error.html +1 -1
  12. data/docs/Puppeteer/ConcurrentRubyUtils.html +1 -1
  13. data/docs/Puppeteer/Connection.html +65 -61
  14. data/docs/Puppeteer/Connection/MessageCallback.html +1 -1
  15. data/docs/Puppeteer/Connection/ProtocolError.html +1 -1
  16. data/docs/Puppeteer/Connection/RequestDebugPrinter.html +5 -5
  17. data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +12 -12
  18. data/docs/Puppeteer/ConsoleMessage.html +1 -1
  19. data/docs/Puppeteer/ConsoleMessage/Location.html +1 -1
  20. data/docs/Puppeteer/DOMWorld.html +708 -69
  21. data/docs/Puppeteer/DOMWorld/DetachedError.html +1 -1
  22. data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +1 -1
  23. data/docs/Puppeteer/DebugPrint.html +2 -2
  24. data/docs/Puppeteer/Device.html +1 -1
  25. data/docs/Puppeteer/Devices.html +1 -1
  26. data/docs/Puppeteer/ElementHandle.html +1120 -181
  27. data/docs/Puppeteer/ElementHandle/BoundingBox.html +507 -0
  28. data/docs/Puppeteer/ElementHandle/BoxModel.html +404 -0
  29. data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +5 -5
  30. data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +5 -5
  31. data/docs/Puppeteer/ElementHandle/Point.html +40 -29
  32. data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +1 -1
  33. data/docs/Puppeteer/EmulationManager.html +1 -1
  34. data/docs/Puppeteer/EventCallbackable.html +1 -1
  35. data/docs/Puppeteer/EventCallbackable/EventListeners.html +1 -1
  36. data/docs/Puppeteer/ExecutionContext.html +227 -1
  37. data/docs/Puppeteer/ExecutionContext/EvaluationError.html +1 -1
  38. data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +1 -1
  39. data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +2 -2
  40. data/docs/Puppeteer/FileChooser.html +455 -0
  41. data/docs/Puppeteer/Frame.html +492 -304
  42. data/docs/Puppeteer/FrameManager.html +22 -26
  43. data/docs/Puppeteer/FrameManager/NavigationError.html +1 -1
  44. data/docs/Puppeteer/IfPresent.html +1 -1
  45. data/docs/Puppeteer/JSHandle.html +1 -1
  46. data/docs/Puppeteer/Keyboard.html +1 -1
  47. data/docs/Puppeteer/Keyboard/KeyDefinition.html +1 -1
  48. data/docs/Puppeteer/Keyboard/KeyDescription.html +1 -1
  49. data/docs/Puppeteer/Launcher.html +1 -1
  50. data/docs/Puppeteer/Launcher/Base.html +1 -1
  51. data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +1 -1
  52. data/docs/Puppeteer/Launcher/BrowserOptions.html +1 -1
  53. data/docs/Puppeteer/Launcher/Chrome.html +64 -23
  54. data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +1 -1
  55. data/docs/Puppeteer/Launcher/ChromeArgOptions.html +1 -1
  56. data/docs/Puppeteer/Launcher/LaunchOptions.html +1 -1
  57. data/docs/Puppeteer/LifecycleWatcher.html +1 -1
  58. data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +1 -1
  59. data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +1 -1
  60. data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +1 -1
  61. data/docs/Puppeteer/Mouse.html +31 -41
  62. data/docs/Puppeteer/Mouse/Button.html +1 -1
  63. data/docs/Puppeteer/NetworkManager.html +1 -1
  64. data/docs/Puppeteer/NetworkManager/Credentials.html +1 -1
  65. data/docs/Puppeteer/Page.html +980 -436
  66. data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
  67. data/docs/Puppeteer/Page/ScreenshotOptions.html +1 -1
  68. data/docs/Puppeteer/Page/ScriptTag.html +24 -24
  69. data/docs/Puppeteer/Page/StyleTag.html +19 -19
  70. data/docs/Puppeteer/Page/TargetCrashedError.html +1 -1
  71. data/docs/Puppeteer/RemoteObject.html +173 -37
  72. data/docs/Puppeteer/Target.html +149 -197
  73. data/docs/Puppeteer/Target/InitializeFailure.html +1 -1
  74. data/docs/Puppeteer/Target/TargetInfo.html +1 -1
  75. data/docs/Puppeteer/TimeoutError.html +2 -2
  76. data/docs/Puppeteer/TimeoutSettings.html +1 -1
  77. data/docs/Puppeteer/TouchScreen.html +1 -1
  78. data/docs/Puppeteer/Viewport.html +81 -1
  79. data/docs/Puppeteer/WaitTask.html +434 -8
  80. data/docs/Puppeteer/WaitTask/TerminatedError.html +1 -1
  81. data/docs/Puppeteer/WaitTask/TimeoutError.html +206 -0
  82. data/docs/Puppeteer/WebSocket.html +26 -26
  83. data/docs/Puppeteer/WebSocket/DriverImpl.html +1 -1
  84. data/docs/Puppeteer/WebSocket/TransportError.html +124 -0
  85. data/docs/Puppeteer/WebSocketTransport.html +2 -2
  86. data/docs/Puppeteer/WebSocktTransportError.html +1 -1
  87. data/docs/_index.html +47 -19
  88. data/docs/class_list.html +1 -1
  89. data/docs/file.README.html +5 -3
  90. data/docs/index.html +5 -3
  91. data/docs/method_list.html +788 -444
  92. data/docs/top-level-namespace.html +1 -1
  93. data/lib/puppeteer.rb +7 -1
  94. data/lib/puppeteer/browser.rb +21 -6
  95. data/lib/puppeteer/browser_runner.rb +1 -1
  96. data/lib/puppeteer/cdp_session.rb +33 -11
  97. data/lib/puppeteer/connection.rb +13 -1
  98. data/lib/puppeteer/dom_world.rb +113 -108
  99. data/lib/puppeteer/element_handle.rb +183 -222
  100. data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
  101. data/lib/puppeteer/element_handle/box_model.rb +19 -0
  102. data/lib/puppeteer/element_handle/point.rb +26 -0
  103. data/lib/puppeteer/errors.rb +1 -3
  104. data/lib/puppeteer/execution_context.rb +36 -17
  105. data/lib/puppeteer/file_chooser.rb +29 -0
  106. data/lib/puppeteer/frame.rb +32 -12
  107. data/lib/puppeteer/frame_manager.rb +0 -2
  108. data/lib/puppeteer/launcher/chrome.rb +48 -2
  109. data/lib/puppeteer/mouse.rb +3 -8
  110. data/lib/puppeteer/page.rb +116 -65
  111. data/lib/puppeteer/remote_object.rb +15 -1
  112. data/lib/puppeteer/target.rb +24 -24
  113. data/lib/puppeteer/version.rb +1 -1
  114. data/lib/puppeteer/viewport.rb +18 -0
  115. data/lib/puppeteer/wait_task.rb +183 -1
  116. data/lib/puppeteer/web_socket.rb +3 -1
  117. data/lib/puppeteer/web_socket_transport.rb +1 -1
  118. metadata +12 -2
@@ -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
@@ -122,7 +122,7 @@ class Puppeteer::ExecutionContext
122
122
  remote_object = Puppeteer::RemoteObject.new(result['result'])
123
123
 
124
124
  if exception_details
125
- raise EvaluationError.new("Evaluation failed: #{exceptionDetails}")
125
+ raise EvaluationError.new("Evaluation failed: #{exception_details}")
126
126
  end
127
127
 
128
128
  if @return_by_value
@@ -216,20 +216,39 @@ class Puppeteer::ExecutionContext
216
216
  # return createJSHandle(this, response.objects);
217
217
  # }
218
218
 
219
- # /**
220
- # * @param {Puppeteer.ElementHandle} elementHandle
221
- # * @return {Promise<Puppeteer.ElementHandle>}
222
- # */
223
- # async _adoptElementHandle(elementHandle) {
224
- # assert(elementHandle.executionContext() !== this, 'Cannot adopt handle that already belongs to this execution context');
225
- # assert(this._world, 'Cannot adopt handle without DOMWorld');
226
- # const nodeInfo = await this._client.send('DOM.describeNode', {
227
- # objectId: elementHandle._remoteObject.objectId,
228
- # });
229
- # const {object} = await this._client.send('DOM.resolveNode', {
230
- # backendNodeId: nodeInfo.node.backendNodeId,
231
- # executionContextId: this._contextId,
232
- # });
233
- # return /** @type {Puppeteer.ElementHandle}*/(createJSHandle(this, object));
234
- # }
219
+ # @param backend_node_id [Integer]
220
+ # @return [Puppeteer::ElementHandle]
221
+ def adopt_backend_node_id(backend_node_id)
222
+ response = @client.send_message('DOM.resolveNode',
223
+ backendNodeId: backend_node_id,
224
+ executionContextId: @context_id,
225
+ )
226
+ Puppeteer::JSHandle.create(
227
+ context: self,
228
+ remote_object: Puppeteer::RemoteObject.new(response["object"]),
229
+ )
230
+ end
231
+
232
+ # @param element_handle [Puppeteer::ElementHandle]
233
+ # @return [Puppeteer::ElementHandle]
234
+ def adopt_element_handle(element_handle)
235
+ if element_handle.execution_context == self
236
+ raise ArgumentError.new('Cannot adopt handle that already belongs to this execution context')
237
+ end
238
+
239
+ unless @world
240
+ raise 'Cannot adopt handle without DOMWorld'
241
+ end
242
+
243
+ node_info = element_handle.remote_object.node_info(@client)
244
+ response = @client.send_message('DOM.resolveNode',
245
+ backendNodeId: node_info["node"]["backendNodeId"],
246
+ executionContextId: @context_id,
247
+ )
248
+
249
+ Puppeteer::JSHandle.create(
250
+ context: self,
251
+ remote_object: Puppeteer::RemoteObject.new(response["object"]),
252
+ )
253
+ end
235
254
  end
@@ -0,0 +1,29 @@
1
+ class Puppeteer::FileChooser
2
+ # @param element [Puppeteer::ElementHandle]
3
+ # @param event [Hash]
4
+ def initialize(element, event)
5
+ @element = element
6
+ @multiple = event['mode'] != 'selectSingle'
7
+ @handled = false
8
+ end
9
+
10
+ def multiple?
11
+ @multiple
12
+ end
13
+
14
+ # @param file_paths [Array<String>]
15
+ def accept(file_paths)
16
+ if @handled
17
+ raise 'Cannot accept FileChooser which is already handled!'
18
+ end
19
+ @handled = true
20
+ @element.upload_file(*file_paths)
21
+ end
22
+
23
+ def cancel
24
+ if @handled
25
+ raise 'Cannot cancel FileChooser which is already handled!'
26
+ end
27
+ @handled = true
28
+ end
29
+ end
@@ -1,4 +1,6 @@
1
1
  class Puppeteer::Frame
2
+ using Puppeteer::AsyncAwaitBehavior
3
+
2
4
  # @param {!FrameManager} frameManager
3
5
  # @param {!Puppeteer.CDPSession} client
4
6
  # @param {?Frame} parentFrame
@@ -33,10 +35,17 @@ class Puppeteer::Frame
33
35
 
34
36
  # @param timeout [number|nil]
35
37
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
36
- def wait_for_navigation(timeout: nil, wait_until: nil)
38
+ private def wait_for_navigation(timeout: nil, wait_until: nil)
37
39
  @frame_manager.wait_for_frame_navigation(self, timeout: timeout, wait_until: wait_until)
38
40
  end
39
41
 
42
+ # @param timeout [number|nil]
43
+ # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
44
+ # @return [Future]
45
+ async def async_wait_for_navigation(timeout: nil, wait_until: nil)
46
+ wait_for_navigation(timeout: timeout, wait_until: wait_until)
47
+ end
48
+
40
49
  def execution_context
41
50
  @main_world.execution_context
42
51
  end
@@ -143,6 +152,15 @@ class Puppeteer::Frame
143
152
  @main_world.add_style_tag(style_tag)
144
153
  end
145
154
 
155
+ # @param selector [String]
156
+ # @param delay [Number]
157
+ # @param button [String] "left"|"right"|"middle"
158
+ # @param click_count [Number]
159
+ # @return [Future]
160
+ async def async_click(selector, delay: nil, button: nil, click_count: nil)
161
+ click(selector, delay: delay, button: button, click_count: click_count)
162
+ end
163
+
146
164
  # @param selector [String]
147
165
  # @param delay [Number]
148
166
  # @param button [String] "left"|"right"|"middle"
@@ -173,11 +191,11 @@ class Puppeteer::Frame
173
191
  @secondary_world.tap(selector)
174
192
  end
175
193
 
176
- # @param {string} selector
177
- # @param {string} text
178
- # @param {{delay: (number|undefined)}=} options
179
- def type(selector, text, delay: nil)
180
- @main_world.type(selector, text, delay: delay)
194
+ # @param selector [String]
195
+ # @param text [String]
196
+ # @param delay [Number]
197
+ def type_text(selector, text, delay: nil)
198
+ @main_world.type_text(selector, text, delay: delay)
181
199
  end
182
200
 
183
201
  # /**
@@ -202,9 +220,10 @@ class Puppeteer::Frame
202
220
  # return Promise.reject(new Error('Unsupported target type: ' + (typeof selectorOrFunctionOrTimeout)));
203
221
  # }
204
222
 
205
- # @param {string} selector
206
- # @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
207
- # @return {!Promise<?Puppeteer.ElementHandle>}
223
+ # @param selector [String]
224
+ # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
225
+ # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
226
+ # @param timeout [Integer]
208
227
  def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
209
228
  handle = @secondary_world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout)
210
229
  if !handle
@@ -216,9 +235,10 @@ class Puppeteer::Frame
216
235
  result
217
236
  end
218
237
 
219
- # @param {string} xpath
220
- # @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
221
- # @return {!Promise<?Puppeteer.ElementHandle>}
238
+ # @param xpath [String]
239
+ # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
240
+ # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
241
+ # @param timeout [Integer]
222
242
  def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil)
223
243
  handle = @secondary_world.wait_for_xpath(xpath, visible: visible, hidden: hidden, timeout: timeout)
224
244
  if !handle
@@ -285,8 +285,6 @@ class Puppeteer::FrameManager
285
285
  frame.navigated_within_document(url)
286
286
  emit_event 'Events.FrameManager.FrameNavigatedWithinDocument', frame
287
287
  emit_event 'Events.FrameManager.FrameNavigated', frame
288
- handle_frame_manager_frame_navigated_within_document(frame)
289
- handle_frame_manager_frame_navigated(frame)
290
288
  end
291
289
 
292
290
  # @param frame_id [String]
@@ -149,8 +149,54 @@ module Puppeteer::Launcher
149
149
 
150
150
  # @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport})} options
151
151
  # @return {!Promise<!Browser>}
152
- def connect(options)
153
- raise NotImplementedError.new('Puppeteer.connect is not implemented yet')
152
+ def connect(options = {})
153
+ @browser_options = BrowserOptions.new(options)
154
+ browser_ws_endpoint = options[:browser_ws_endpoint]
155
+ browser_url = options[:browser_url]
156
+ transport = options[:transport]
157
+
158
+ connection =
159
+ if browser_ws_endpoint && browser_url.nil? && transport.nil?
160
+ connect_with_browser_ws_endpoint(browser_ws_endpoint)
161
+ elsif browser_ws_endpoint.nil? && browser_url && transport.nil?
162
+ connect_with_browser_url(browser_url)
163
+ elsif browser_ws_endpoint.nil? && browser_url.nil? && transport
164
+ connect_with_transport(transport)
165
+ else
166
+ raise ArgumentError.new("Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect")
167
+ end
168
+
169
+ result = connection.send_message('Target.getBrowserContexts')
170
+ browser_context_ids = result['browserContextIds']
171
+
172
+ Puppeteer::Browser.create(
173
+ connection: connection,
174
+ context_ids: browser_context_ids,
175
+ ignore_https_errors: @browser_options.ignore_https_errors?,
176
+ default_viewport: @browser_options.default_viewport,
177
+ process: nil,
178
+ close_callback: -> { connection.send_message('Browser.close') },
179
+ )
180
+ end
181
+
182
+ # @return [Puppeteer::Connection]
183
+ private def connect_with_browser_ws_endpoint(browser_ws_endpoint)
184
+ transport = Puppeteer::WebSocketTransport.create(browser_ws_endpoint)
185
+ Puppeteer::Connection.new(browser_ws_endpoint, transport, @browser_options.slow_mo)
186
+ end
187
+
188
+ # @return [Puppeteer::Connection]
189
+ private def connect_with_browser_url(browser_url)
190
+ raise NotImplementedError.new('Puppeteer#connect with browserUrl is not implemented yet.')
191
+ # const connectionURL = await getWSEndpoint(browserURL);
192
+ # const connectionTransport = await WebSocketTransport.create(
193
+ # connectionURL
194
+ # );
195
+ end
196
+
197
+ # @return [Puppeteer::Connection]
198
+ private def connect_with_transport(transport)
199
+ Puppeteer::Connection.new('', transport, @browser_options.slow_mo)
154
200
  end
155
201
 
156
202
  # @return {string}
@@ -61,18 +61,13 @@ class Puppeteer::Mouse
61
61
  # D, [2020-04-15T17:09:47.898422 #88683] DEBUG -- : SEND >> {"sessionId":"0B09EA5E18DEE403E525B3E7FCD7E225","method":"Input.dispatchMouseEvent","params":{"type":"mouseReleased","button":"left","x":0,"y":0,"modifiers":0,"clickCount":1},"id":24}
62
62
  # D, [2020-04-15T17:09:47.899711 #88683] DEBUG -- : SEND >> {"sessionId":"0B09EA5E18DEE403E525B3E7FCD7E225","method":"Input.dispatchMouseEvent","params":{"type":"mousePressed","button":"left","x":0,"y":0,"modifiers":0,"clickCount":1},"id":25}
63
63
  # D, [2020-04-15T17:09:47.900237 #88683] DEBUG -- : SEND >> {"sessionId":"0B09EA5E18DEE403E525B3E7FCD7E225","method":"Input.dispatchMouseEvent","params":{"type":"mouseMoved","button":"left","x":187,"y":283,"modifiers":0},"id":26}
64
- # So we execute move in advance.
64
+ # So we execute them sequential
65
65
  move(x, y)
66
+ down(button: button, click_count: click_count)
66
67
  if delay
67
- down(button: button, click_count: click_count)
68
68
  sleep(delay / 1000.0)
69
- up(button: button, click_count: click_count)
70
- else
71
- await_all(
72
- async_down(button: button, click_count: click_count),
73
- async_up(button: button, click_count: click_count),
74
- )
75
69
  end
70
+ up(button: button, click_count: click_count)
76
71
  end
77
72
 
78
73
  # @param x [number]
@@ -88,8 +88,8 @@ class Puppeteer::Page
88
88
  network_manager.on_event 'Events.NetworkManager.RequestFinished' do |event|
89
89
  emit_event 'Events.Page.RequestFinished', event
90
90
  end
91
- # this._fileChooserInterceptionIsDisabled = false;
92
- # this._fileChooserInterceptors = new Set();
91
+ @file_chooser_interception_is_disabled = false
92
+ @file_chooser_interceptors = Set.new
93
93
 
94
94
  @client.on_event 'Page.domContentEventFired' do |event|
95
95
  emit_event 'Events.Page.DOMContentLoaded'
@@ -106,8 +106,10 @@ class Puppeteer::Page
106
106
  @client.on_event 'Log.entryAdded' do |event|
107
107
  handle_log_entry_added(event)
108
108
  end
109
- # client.on('Page.fileChooserOpened', event => this._onFileChooser(event));
110
- @target.on_close do
109
+ @client.on_event 'Page.fileChooserOpened' do |event|
110
+ handle_file_chooser(event)
111
+ end
112
+ @target.is_closed_promise.then do
111
113
  emit_event 'Events.Page.Close'
112
114
  @closed = true
113
115
  end
@@ -122,41 +124,53 @@ class Puppeteer::Page
122
124
  )
123
125
  end
124
126
 
125
- # /**
126
- # * @param {!Protocol.Page.fileChooserOpenedPayload} event
127
- # */
128
- # async _onFileChooser(event) {
129
- # if (!this._fileChooserInterceptors.size)
130
- # return;
131
- # const frame = this._frameManager.frame(event.frameId);
132
- # const context = await frame.executionContext();
133
- # const element = await context._adoptBackendNodeId(event.backendNodeId);
134
- # const interceptors = Array.from(this._fileChooserInterceptors);
135
- # this._fileChooserInterceptors.clear();
136
- # const fileChooser = new FileChooser(this._client, element, event);
137
- # for (const interceptor of interceptors)
138
- # interceptor.call(null, fileChooser);
139
- # }
127
+ def handle_file_chooser(event)
128
+ return if @file_chooser_interceptors.empty?
129
+
130
+ frame = @frame_manager.frame(event['frameId'])
131
+ context = frame.execution_context
132
+ element = context.adopt_backend_node_id(event['backendNodeId'])
133
+ interceptors = @file_chooser_interceptors.to_a
134
+ @file_chooser_interceptors.clear
135
+ file_chooser = Puppeteer::FileChooser.new(element, event)
136
+ interceptors.each do |promise|
137
+ promise.fulfill(file_chooser)
138
+ end
139
+ end
140
140
 
141
- # /**
142
- # * @param {!{timeout?: number}=} options
143
- # * @return !Promise<!FileChooser>}
144
- # */
145
- # async waitForFileChooser(options = {}) {
146
- # if (!this._fileChooserInterceptors.size)
147
- # await this._client.send('Page.setInterceptFileChooserDialog', {enabled: true});
141
+ class FileChooserTimeoutError < StandardError
142
+ def initialize(timeout:)
143
+ super("waiting for filechooser failed: timeout #{timeout}ms exceeded")
144
+ end
145
+ end
148
146
 
149
- # const {
150
- # timeout = this._timeoutSettings.timeout(),
151
- # } = options;
152
- # let callback;
153
- # const promise = new Promise(x => callback = x);
154
- # this._fileChooserInterceptors.add(callback);
155
- # return helper.waitWithTimeout(promise, 'waiting for file chooser', timeout).catch(e => {
156
- # this._fileChooserInterceptors.delete(callback);
157
- # throw e;
158
- # });
159
- # }
147
+ # @param timeout [Integer]
148
+ # @return [Puppeteer::FileChooser]
149
+ def wait_for_file_chooser(timeout: nil)
150
+ if @file_chooser_interceptors.empty?
151
+ @client.send_message('Page.setInterceptFileChooserDialog', enabled: true)
152
+ end
153
+
154
+ option_timeout = timeout || @timeout_settings.timeout
155
+ promise = resolvable_future
156
+ @file_chooser_interceptors << promise
157
+
158
+ begin
159
+ Timeout.timeout(option_timeout / 1000.0) do
160
+ promise.value!
161
+ end
162
+ rescue Timeout::Error
163
+ raise FileChooserTimeoutError.new(timeout: option_timeout)
164
+ ensure
165
+ @file_chooser_interceptors.delete(promise)
166
+ end
167
+ end
168
+
169
+ # @param timeout [Integer]
170
+ # @return [Future<Puppeteer::FileChooser>]
171
+ async def async_wait_for_file_chooser(timeout: nil)
172
+ wait_for_file_chooser(timeout: timeout)
173
+ end
160
174
 
161
175
 
162
176
  # /**
@@ -275,23 +289,37 @@ class Puppeteer::Page
275
289
  end
276
290
 
277
291
  # `$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
278
- # @param {string} selector
279
- # @param {Function|string} pageFunction
280
- # @param {!Array<*>} args
281
- # @return {!Promise<(!Object|undefined)>}
292
+ # @param selector [String]
293
+ # @param page_function [String]
294
+ # @return [Object]
282
295
  def Seval(selector, page_function, *args)
283
296
  main_frame.Seval(selector, page_function, *args)
284
297
  end
285
298
 
299
+ # `$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
300
+ # @param selector [String]
301
+ # @param page_function [String]
302
+ # @return [Future]
303
+ async def async_Seval(selector, page_function, *args)
304
+ Seval(selector, page_function, *args)
305
+ end
306
+
286
307
  # `$$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
287
- # @param {string} selector
288
- # @param {Function|string} pageFunction
289
- # @param {!Array<*>} args
290
- # @return {!Promise<(!Object|undefined)>}
308
+ # @param selector [String]
309
+ # @param page_function [String]
310
+ # @return [Object]
291
311
  def SSeval(selector, page_function, *args)
292
312
  main_frame.SSeval(selector, page_function, *args)
293
313
  end
294
314
 
315
+ # `$$eval()` in JavaScript. $ is not allowed to use as a method name in Ruby.
316
+ # @param selector [String]
317
+ # @param page_function [String]
318
+ # @return [Future]
319
+ async def async_SSeval(selector, page_function, *args)
320
+ SSeval(selector, page_function, *args)
321
+ end
322
+
295
323
  # `$x()` in JavaScript. $ is not allowed to use as a method name in Ruby.
296
324
  # @param {string} expression
297
325
  # @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
@@ -610,20 +638,20 @@ class Puppeteer::Page
610
638
  main_frame.goto(url, referer: referer, timeout: timeout, wait_until: wait_until)
611
639
  end
612
640
 
613
- # @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
614
- # @return {!Promise<?Puppeteer.Response>}
641
+ # @param timeout [number|nil]
642
+ # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
643
+ # @return [Puppeteer::Response]
615
644
  def reload(timeout: nil, wait_until: nil)
616
- # const [response] = await Promise.all([
617
- # this.waitForNavigation(options),
618
- # this._client.send('Page.reload')
619
- # ]);
620
- # return response;
645
+ await_all(
646
+ async_wait_for_navigation(timeout: timeout, wait_until: wait_until),
647
+ @client.async_send_message('Page.reload'),
648
+ ).first
621
649
  end
622
650
 
623
651
  # @param timeout [number|nil]
624
652
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
625
653
  private def wait_for_navigation(timeout: nil, wait_until: nil)
626
- main_frame.wait_for_navigation(timeout: timeout, wait_until: wait_until)
654
+ main_frame.send(:wait_for_navigation, timeout: timeout, wait_until: wait_until)
627
655
  end
628
656
 
629
657
  # @param timeout [number|nil]
@@ -968,16 +996,21 @@ class Puppeteer::Page
968
996
  main_frame.select(selector, *values)
969
997
  end
970
998
 
971
- # @param {string} selector
999
+ # @param selector [String]
972
1000
  def tap(selector)
973
1001
  main_frame.tap(selector)
974
1002
  end
975
1003
 
976
- # @param {string} selector
977
- # @param {string} text
978
- # @param {{delay: (number|undefined)}=} options
979
- def type(selector, text, delay: nil)
980
- main_frame.type(selector, text, delay: delay)
1004
+ # @param selector [String]
1005
+ async def async_tap(selector)
1006
+ tap(selector)
1007
+ end
1008
+
1009
+ # @param selector [String]
1010
+ # @param text [String]
1011
+ # @param delay [Number]
1012
+ def type_text(selector, text, delay: nil)
1013
+ main_frame.type_text(selector, text, delay: delay)
981
1014
  end
982
1015
 
983
1016
  # /**
@@ -990,20 +1023,38 @@ class Puppeteer::Page
990
1023
  # return this.mainFrame().waitFor(selectorOrFunctionOrTimeout, options, ...args);
991
1024
  # }
992
1025
 
993
- # @param {string} selector
994
- # @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
995
- # @return {!Promise<?Puppeteer.ElementHandle>}
1026
+ # @param selector [String]
1027
+ # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
1028
+ # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
1029
+ # @param timeout [Integer]
996
1030
  def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
997
1031
  main_frame.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout)
998
1032
  end
999
1033
 
1000
- # @param {string} xpath
1001
- # @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
1002
- # @return {!Promise<?Puppeteer.ElementHandle>}
1034
+ # @param selector [String]
1035
+ # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
1036
+ # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
1037
+ # @param timeout [Integer]
1038
+ async def async_wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
1039
+ wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout)
1040
+ end
1041
+
1042
+ # @param xpath [String]
1043
+ # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
1044
+ # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
1045
+ # @param timeout [Integer]
1003
1046
  def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil)
1004
1047
  main_frame.wait_for_xpath(xpath, visible: visible, hidden: hidden, timeout: timeout)
1005
1048
  end
1006
1049
 
1050
+ # @param xpath [String]
1051
+ # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
1052
+ # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
1053
+ # @param timeout [Integer]
1054
+ async def async_wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil)
1055
+ wait_for_xpath(xpath, visible: visible, hidden: hidden, timeout: timeout)
1056
+ end
1057
+
1007
1058
  # @param {Function|string} pageFunction
1008
1059
  # @param {!{polling?: string|number, timeout?: number}=} options
1009
1060
  # @param {!Array<*>} args