puppeteer-ruby 0.0.15 → 0.0.20
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 +4 -4
- data/.circleci/config.yml +25 -2
- data/.github/workflows/reviewdog.yml +1 -1
- data/.rubocop.yml +49 -3
- data/Dockerfile +9 -0
- data/README.md +26 -1
- data/docker-compose.yml +34 -0
- data/lib/puppeteer.rb +17 -12
- data/lib/puppeteer/browser.rb +36 -9
- data/lib/puppeteer/browser_context.rb +35 -5
- data/lib/puppeteer/browser_runner.rb +1 -1
- data/lib/puppeteer/cdp_session.rb +10 -0
- data/lib/puppeteer/connection.rb +8 -3
- data/lib/puppeteer/debug_print.rb +2 -2
- data/lib/puppeteer/define_async_method.rb +1 -1
- data/lib/puppeteer/dialog.rb +34 -0
- data/lib/puppeteer/dom_world.rb +37 -14
- data/lib/puppeteer/element_handle.rb +49 -20
- data/lib/puppeteer/env.rb +23 -0
- data/lib/puppeteer/frame.rb +14 -32
- data/lib/puppeteer/js_handle.rb +37 -27
- data/lib/puppeteer/keyboard.rb +3 -2
- data/lib/puppeteer/launcher.rb +11 -1
- data/lib/puppeteer/launcher/base.rb +14 -4
- data/lib/puppeteer/launcher/chrome.rb +1 -1
- data/lib/puppeteer/launcher/firefox.rb +392 -0
- data/lib/puppeteer/mouse.rb +16 -0
- data/lib/puppeteer/network_manager.rb +163 -5
- data/lib/puppeteer/page.rb +158 -85
- data/lib/puppeteer/remote_object.rb +28 -1
- data/lib/puppeteer/request.rb +330 -0
- data/lib/puppeteer/response.rb +113 -0
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +1 -1
- data/lib/puppeteer/web_socket.rb +7 -0
- data/puppeteer-ruby.gemspec +2 -1
- metadata +25 -4
data/lib/puppeteer/mouse.rb
CHANGED
@@ -94,5 +94,21 @@ class Puppeteer::Mouse
|
|
94
94
|
)
|
95
95
|
end
|
96
96
|
|
97
|
+
# Dispatches a `mousewheel` event.
|
98
|
+
#
|
99
|
+
# @param delta_x [Integer]
|
100
|
+
# @param delta_y [Integer]
|
101
|
+
def wheel(delta_x: 0, delta_y: 0)
|
102
|
+
@client.send_message('Input.dispatchMouseEvent',
|
103
|
+
type: 'mouseWheel',
|
104
|
+
x: @x,
|
105
|
+
y: @y,
|
106
|
+
deltaX: delta_x,
|
107
|
+
deltaY: delta_y,
|
108
|
+
modifiers: @keyboard.modifiers,
|
109
|
+
pointerType: 'mouse',
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
97
113
|
define_async_method :async_up
|
98
114
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
class Puppeteer::NetworkManager
|
2
|
+
include Puppeteer::DebugPrint
|
2
3
|
include Puppeteer::EventCallbackable
|
4
|
+
include Puppeteer::IfPresent
|
3
5
|
|
4
6
|
class Credentials
|
5
7
|
# @param username [String|NilClass]
|
@@ -23,19 +25,39 @@ class Puppeteer::NetworkManager
|
|
23
25
|
@request_id_to_request = {}
|
24
26
|
|
25
27
|
# @type {!Map<string, !Protocol.Network.requestWillBeSentPayload>}
|
26
|
-
@request_id_to_request_with_be_sent_event
|
28
|
+
@request_id_to_request_with_be_sent_event = {}
|
27
29
|
|
28
30
|
@extra_http_headers = {}
|
29
31
|
|
30
32
|
@offline = false
|
31
33
|
|
32
|
-
|
33
|
-
# this._attemptedAuthentications = new Set();
|
34
|
+
@attempted_authentications = Set.new
|
34
35
|
@user_request_interception_enabled = false
|
35
36
|
@protocol_request_interception_enabled = false
|
36
37
|
@user_cache_disabled = false
|
37
|
-
|
38
|
-
|
38
|
+
@request_id_to_interception_id = {}
|
39
|
+
|
40
|
+
@client.on_event('Fetch.requestPaused') do |event|
|
41
|
+
handle_request_paused(event)
|
42
|
+
end
|
43
|
+
@client.on_event('Fetch.authRequired') do |event|
|
44
|
+
handle_auth_required(event)
|
45
|
+
end
|
46
|
+
@client.on_event('Network.requestWillBeSent') do |event|
|
47
|
+
handle_request_will_be_sent(event)
|
48
|
+
end
|
49
|
+
@client.on_event('Network.requestServedFromCache') do |event|
|
50
|
+
handle_request_served_from_cache(event)
|
51
|
+
end
|
52
|
+
@client.on_event('Network.responseReceived') do |event|
|
53
|
+
handle_response_received(event)
|
54
|
+
end
|
55
|
+
@client.on_event('Network.loadingFinished') do |event|
|
56
|
+
handle_loading_finished(event)
|
57
|
+
end
|
58
|
+
@client.on_event('Network.loadingFailed') do |event|
|
59
|
+
handle_loading_failed(event)
|
60
|
+
end
|
39
61
|
end
|
40
62
|
|
41
63
|
def init
|
@@ -119,4 +141,140 @@ class Puppeteer::NetworkManager
|
|
119
141
|
cache_disabled = @user_cache_disabled || @protocol_request_interception_enabled
|
120
142
|
@client.send_message('Network.setCacheDisabled', cacheDisabled: cache_disabled)
|
121
143
|
end
|
144
|
+
|
145
|
+
private def handle_request_will_be_sent(event)
|
146
|
+
# Request interception doesn't happen for data URLs with Network Service.
|
147
|
+
if @protocol_request_interception_enabled && !event['request']['url'].start_with?('data:')
|
148
|
+
request_id = event['requestId']
|
149
|
+
interception_id = @request_id_to_interception_id.delete(request_id)
|
150
|
+
if interception_id
|
151
|
+
handle_request(event, interception_id)
|
152
|
+
else
|
153
|
+
@request_id_to_request_with_be_sent_event[request_id] = event
|
154
|
+
end
|
155
|
+
return
|
156
|
+
end
|
157
|
+
handle_request(event, nil)
|
158
|
+
end
|
159
|
+
|
160
|
+
private def handle_auth_required(event)
|
161
|
+
response = 'Default'
|
162
|
+
if @attempted_authentications.include?(event['requestId'])
|
163
|
+
response = 'CancelAuth'
|
164
|
+
elsif @credentials
|
165
|
+
response = 'ProvideCredentials'
|
166
|
+
@attempted_authentications << event['requestId']
|
167
|
+
end
|
168
|
+
|
169
|
+
username = @credentials&.username
|
170
|
+
password = @credentials&.password
|
171
|
+
|
172
|
+
begin
|
173
|
+
@client.send_message('Fetch.continueWithAuth',
|
174
|
+
requestId: event['requestId'],
|
175
|
+
authChallengeResponse: {
|
176
|
+
response: response,
|
177
|
+
username: username,
|
178
|
+
password: password,
|
179
|
+
},
|
180
|
+
)
|
181
|
+
rescue => err
|
182
|
+
debug_puts(err)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
private def handle_request_paused(event)
|
187
|
+
if !@user_request_interception_enabled && @protocol_request_interception_enabled
|
188
|
+
begin
|
189
|
+
@client.send_message('Fetch.continueRequest', requestId: event['requestId'])
|
190
|
+
rescue => err
|
191
|
+
debug_puts(err)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
request_id = event['networkId']
|
196
|
+
interception_id = event['requestId']
|
197
|
+
if request_id && (request_will_be_sent_event = @request_id_to_request_with_be_sent_event.delete(request_id))
|
198
|
+
handle_request(request_will_be_sent_event, interception_id)
|
199
|
+
else
|
200
|
+
@request_id_to_interception_id[request_id] = interception_id
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
private def handle_request(event, interception_id)
|
205
|
+
redirect_chain = []
|
206
|
+
if event['redirectResponse']
|
207
|
+
if_present(@request_id_to_request[event['requestId']]) do |request|
|
208
|
+
handle_request_redirect(request, event['redirectResponse'])
|
209
|
+
redirect_chain = request.internal.redirect_chain
|
210
|
+
end
|
211
|
+
end
|
212
|
+
frame = if_present(event['frameId']) { |frame_id| @frame_manager.frame(frame_id) }
|
213
|
+
request = Puppeteer::Request.new(@client, frame, interception_id, @user_request_interception_enabled, event, redirect_chain)
|
214
|
+
@request_id_to_request[event['requestId']] = request
|
215
|
+
emit_event 'Events.NetworkManager.Request', request
|
216
|
+
end
|
217
|
+
|
218
|
+
private def handle_request_served_from_cache(event)
|
219
|
+
if_present(@request_id_to_request[event['requestId']]) do |request|
|
220
|
+
request.internal.from_memory_cache = true
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# @param request [Puppeteer::Request]
|
225
|
+
# @param response_payload [Hash]
|
226
|
+
private def handle_request_redirect(request, response_payload)
|
227
|
+
response = Puppeteer::Response.new(@client, request, response_payload)
|
228
|
+
request.internal.response = response
|
229
|
+
request.internal.redirect_chain << request
|
230
|
+
response.internal.body_loaded_promise.reject(Puppeteer::Response::Redirected.new)
|
231
|
+
@request_id_to_request.delete(request.internal.request_id)
|
232
|
+
@attempted_authentications.delete(request.internal.interception_id)
|
233
|
+
emit_event 'Events.NetworkManager.Response', response
|
234
|
+
emit_event 'Events.NetworkManager.RequestFinished', request
|
235
|
+
end
|
236
|
+
|
237
|
+
# @param event [Hash]
|
238
|
+
private def handle_response_received(event)
|
239
|
+
request = @request_id_to_request[event['requestId']]
|
240
|
+
# FileUpload sends a response without a matching request.
|
241
|
+
return unless request
|
242
|
+
|
243
|
+
response = Puppeteer::Response.new(@client, request, event['response'])
|
244
|
+
request.internal.response = response
|
245
|
+
emit_event 'Events.NetworkManager.Response', response
|
246
|
+
end
|
247
|
+
|
248
|
+
private def handle_loading_finished(event)
|
249
|
+
request = @request_id_to_request[event['requestId']]
|
250
|
+
# For certain requestIds we never receive requestWillBeSent event.
|
251
|
+
# @see https://crbug.com/750469
|
252
|
+
return unless request
|
253
|
+
|
254
|
+
|
255
|
+
# Under certain conditions we never get the Network.responseReceived
|
256
|
+
# event from protocol. @see https://crbug.com/883475
|
257
|
+
if_present(request.response) do |response|
|
258
|
+
response.internal.body_loaded_promise.fulfill(nil)
|
259
|
+
end
|
260
|
+
|
261
|
+
@request_id_to_request.delete(request.internal.request_id)
|
262
|
+
@attempted_authentications.delete(request.internal.interception_id)
|
263
|
+
emit_event 'Events.NetworkManager.RequestFinished', request
|
264
|
+
end
|
265
|
+
|
266
|
+
private def handle_loading_failed(event)
|
267
|
+
request = @request_id_to_request[event['requestId']]
|
268
|
+
# For certain requestIds we never receive requestWillBeSent event.
|
269
|
+
# @see https://crbug.com/750469
|
270
|
+
return unless request
|
271
|
+
|
272
|
+
request.internal.failure_text = event['errorText']
|
273
|
+
if_present(request.response) do |response|
|
274
|
+
response.internal.body_loaded_promise.fulfill(nil)
|
275
|
+
end
|
276
|
+
@request_id_to_request.delete(request.internal.request_id)
|
277
|
+
@attempted_authentications.delete(request.internal.interception_id)
|
278
|
+
emit_event 'Events.NetworkManager.RequestFailed', request
|
279
|
+
end
|
122
280
|
end
|
data/lib/puppeteer/page.rb
CHANGED
@@ -101,7 +101,9 @@ class Puppeteer::Page
|
|
101
101
|
end
|
102
102
|
# client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
|
103
103
|
# client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
|
104
|
-
|
104
|
+
@client.on_event 'Page.javascriptDialogOpening' do |event|
|
105
|
+
handle_dialog_opening(event)
|
106
|
+
end
|
105
107
|
# client.on('Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails));
|
106
108
|
# client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
|
107
109
|
# client.on('Performance.metrics', event => this._emitMetrics(event));
|
@@ -129,7 +131,7 @@ class Puppeteer::Page
|
|
129
131
|
EVENT_MAPPINGS = {
|
130
132
|
close: 'Events.Page.Close',
|
131
133
|
# console: 'Events.Page.Console',
|
132
|
-
|
134
|
+
dialog: 'Events.Page.Dialog',
|
133
135
|
domcontentloaded: 'Events.Page.DOMContentLoaded',
|
134
136
|
# error:
|
135
137
|
frameattached: 'Events.Page.FrameAttached',
|
@@ -266,7 +268,13 @@ class Puppeteer::Page
|
|
266
268
|
@frame_manager.main_frame
|
267
269
|
end
|
268
270
|
|
269
|
-
attr_reader :
|
271
|
+
attr_reader :touch_screen, :coverage, :accessibility
|
272
|
+
|
273
|
+
def keyboard(&block)
|
274
|
+
@keyboard.instance_eval(&block) unless block.nil?
|
275
|
+
|
276
|
+
@keyboard
|
277
|
+
end
|
270
278
|
|
271
279
|
def frames
|
272
280
|
@frame_manager.frames
|
@@ -626,20 +634,17 @@ class Puppeteer::Page
|
|
626
634
|
# this.emit(Events.Page.Console, message);
|
627
635
|
# }
|
628
636
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
# const dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt);
|
641
|
-
# this.emit(Events.Page.Dialog, dialog);
|
642
|
-
# }
|
637
|
+
private def handle_dialog_opening(event)
|
638
|
+
dialog_type = event['type']
|
639
|
+
unless %w(alert confirm prompt beforeunload).include?(dialog_type)
|
640
|
+
raise ArgumentError.new("Unknown javascript dialog type: #{dialog_type}")
|
641
|
+
end
|
642
|
+
dialog = Puppeteer::Dialog.new(@client,
|
643
|
+
type: dialog_type,
|
644
|
+
message: event['message'],
|
645
|
+
default_value: event['defaultPrompt'])
|
646
|
+
emit_event('Events.Page.Dialog', dialog)
|
647
|
+
end
|
643
648
|
|
644
649
|
# @return [String]
|
645
650
|
def url
|
@@ -681,49 +686,111 @@ class Puppeteer::Page
|
|
681
686
|
).first
|
682
687
|
end
|
683
688
|
|
684
|
-
# @param timeout [number|nil]
|
685
|
-
# @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
|
686
689
|
private def wait_for_navigation(timeout: nil, wait_until: nil)
|
687
690
|
main_frame.send(:wait_for_navigation, timeout: timeout, wait_until: wait_until)
|
688
691
|
end
|
689
692
|
|
693
|
+
# @!method async_wait_for_navigation(timeout: nil, wait_until: nil)
|
694
|
+
#
|
695
|
+
# @param timeout [number|nil]
|
696
|
+
# @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
|
690
697
|
define_async_method :async_wait_for_navigation
|
691
698
|
|
692
|
-
|
693
|
-
|
694
|
-
# * @param {!{timeout?: number}=} options
|
695
|
-
# * @return {!Promise<!Puppeteer.Request>}
|
696
|
-
# */
|
697
|
-
# async waitForRequest(urlOrPredicate, options = {}) {
|
698
|
-
# const {
|
699
|
-
# timeout = this._timeoutSettings.timeout(),
|
700
|
-
# } = options;
|
701
|
-
# return helper.waitForEvent(this._frameManager.networkManager(), Events.NetworkManager.Request, request => {
|
702
|
-
# if (helper.isString(urlOrPredicate))
|
703
|
-
# return (urlOrPredicate === request.url());
|
704
|
-
# if (typeof urlOrPredicate === 'function')
|
705
|
-
# return !!(urlOrPredicate(request));
|
706
|
-
# return false;
|
707
|
-
# }, timeout, this._sessionClosePromise());
|
708
|
-
# }
|
699
|
+
private def wait_for_network_manager_event(event_name, predicate:, timeout:)
|
700
|
+
option_timeout = timeout || @timeout_settings.timeout
|
709
701
|
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
702
|
+
@wait_for_network_manager_event_listener_ids ||= {}
|
703
|
+
if_present(@wait_for_network_manager_event_listener_ids[event_name]) do |listener_id|
|
704
|
+
@frame_manager.network_manager.remove_event_listener(listener_id)
|
705
|
+
end
|
706
|
+
|
707
|
+
promise = resolvable_future
|
708
|
+
|
709
|
+
@wait_for_network_manager_event_listener_ids[event_name] =
|
710
|
+
@frame_manager.network_manager.add_event_listener(event_name) do |event_target|
|
711
|
+
if predicate.call(event_target)
|
712
|
+
promise.fulfill(nil)
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
begin
|
717
|
+
Timeout.timeout(option_timeout / 1000.0) do
|
718
|
+
await_any(promise, session_close_promise)
|
719
|
+
end
|
720
|
+
rescue Timeout::Error
|
721
|
+
raise Puppeteer::TimeoutError.new("waiting for #{event_name} failed: timeout #{timeout}ms exceeded")
|
722
|
+
ensure
|
723
|
+
@frame_manager.network_manager.remove_event_listener(@wait_for_network_manager_event_listener_ids[event_name])
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
private def session_close_promise
|
728
|
+
@disconnect_promise ||= resolvable_future do |future|
|
729
|
+
@client.observe_first('Events.CDPSession.Disconnected') do
|
730
|
+
future.reject(Puppeteer::CDPSession::Error.new('Target Closed'))
|
731
|
+
end
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
private def wait_for_request(url: nil, predicate: nil, timeout: nil)
|
736
|
+
if !url && !predicate
|
737
|
+
raise ArgumentError.new('url or predicate must be specified')
|
738
|
+
end
|
739
|
+
if predicate && !predicate.is_a?(Proc)
|
740
|
+
raise ArgumentError.new('predicate must be a proc.')
|
741
|
+
end
|
742
|
+
request_predicate =
|
743
|
+
if url
|
744
|
+
-> (request) { request.url == url }
|
745
|
+
else
|
746
|
+
-> (request) { predicate.call(request) }
|
747
|
+
end
|
748
|
+
|
749
|
+
wait_for_network_manager_event('Events.NetworkManager.Request',
|
750
|
+
predicate: request_predicate,
|
751
|
+
timeout: timeout,
|
752
|
+
)
|
753
|
+
end
|
754
|
+
|
755
|
+
# @!method async_wait_for_request(url: nil, predicate: nil, timeout: nil)
|
756
|
+
#
|
757
|
+
# Waits until request URL matches or request matches the given predicate.
|
758
|
+
#
|
759
|
+
# Waits until request URL matches
|
760
|
+
# wait_for_request(url: 'https://example.com/awesome')
|
761
|
+
#
|
762
|
+
# Waits until request matches the given predicate
|
763
|
+
# wait_for_request(predicate: -> (req){ req.url.start_with?('https://example.com/search') })
|
764
|
+
#
|
765
|
+
# @param url [String]
|
766
|
+
# @param predicate [Proc(Puppeteer::Request -> Boolean)]
|
767
|
+
define_async_method :async_wait_for_request
|
768
|
+
|
769
|
+
private def wait_for_response(url: nil, predicate: nil, timeout: nil)
|
770
|
+
if !url && !predicate
|
771
|
+
raise ArgumentError.new('url or predicate must be specified')
|
772
|
+
end
|
773
|
+
if predicate && !predicate.is_a?(Proc)
|
774
|
+
raise ArgumentError.new('predicate must be a proc.')
|
775
|
+
end
|
776
|
+
response_predicate =
|
777
|
+
if url
|
778
|
+
-> (response) { response.url == url }
|
779
|
+
else
|
780
|
+
-> (response) { predicate.call(response) }
|
781
|
+
end
|
782
|
+
|
783
|
+
wait_for_network_manager_event('Events.NetworkManager.Response',
|
784
|
+
predicate: response_predicate,
|
785
|
+
timeout: timeout,
|
786
|
+
)
|
787
|
+
end
|
788
|
+
|
789
|
+
# @!method async_wait_for_response(url: nil, predicate: nil, timeout: nil)
|
790
|
+
#
|
791
|
+
# @param url [String]
|
792
|
+
# @param predicate [Proc(Puppeteer::Request -> Boolean)]
|
793
|
+
define_async_method :async_wait_for_response
|
727
794
|
|
728
795
|
# @param timeout [number|nil]
|
729
796
|
# @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
|
@@ -762,20 +829,19 @@ class Puppeteer::Page
|
|
762
829
|
@client.send_message('Emulation.setScriptExecutionDisabled', value: !enabled)
|
763
830
|
end
|
764
831
|
|
765
|
-
#
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
# await this._client.send('Page.setBypassCSP', { enabled });
|
770
|
-
# }
|
832
|
+
# @param enabled [Boolean]
|
833
|
+
def bypass_csp=(enabled)
|
834
|
+
@client.send_message('Page.setBypassCSP', enabled: enabled)
|
835
|
+
end
|
771
836
|
|
772
|
-
#
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
837
|
+
# @param media_type [String|Symbol|nil] either of (media, print, nil)
|
838
|
+
def emulate_media_type(media_type)
|
839
|
+
media_type_str = media_type.to_s
|
840
|
+
unless ['screen', 'print', ''].include?(media_type_str)
|
841
|
+
raise ArgumentError.new("Unsupported media type: #{media_type}")
|
842
|
+
end
|
843
|
+
@client.send_message('Emulation.setEmulatedMedia', media: media_type_str)
|
844
|
+
end
|
779
845
|
|
780
846
|
# /**
|
781
847
|
# * @param {?Array<MediaFeature>} features
|
@@ -795,7 +861,7 @@ class Puppeteer::Page
|
|
795
861
|
|
796
862
|
# @param timezone_id [String?]
|
797
863
|
def emulate_timezone(timezone_id)
|
798
|
-
@client.send_message('Emulation.setTimezoneOverride', timezoneId:
|
864
|
+
@client.send_message('Emulation.setTimezoneOverride', timezoneId: timezone_id || '')
|
799
865
|
rescue => err
|
800
866
|
if err.message.include?('Invalid timezone')
|
801
867
|
raise ArgumentError.new("Invalid timezone ID: #{timezone_id}")
|
@@ -1019,8 +1085,19 @@ class Puppeteer::Page
|
|
1019
1085
|
define_async_method :async_select
|
1020
1086
|
|
1021
1087
|
# @param selector [String]
|
1022
|
-
def tap(selector)
|
1023
|
-
|
1088
|
+
def tap(selector: nil, &block)
|
1089
|
+
# resolves double meaning of tap.
|
1090
|
+
if selector.nil? && block
|
1091
|
+
# Original usage of Object#tap.
|
1092
|
+
#
|
1093
|
+
# browser.new_page.tap do |page|
|
1094
|
+
# ...
|
1095
|
+
# end
|
1096
|
+
super(&block)
|
1097
|
+
else
|
1098
|
+
# Puppeteer's Page#tap.
|
1099
|
+
main_frame.tap(selector)
|
1100
|
+
end
|
1024
1101
|
end
|
1025
1102
|
|
1026
1103
|
define_async_method :async_tap
|
@@ -1034,16 +1111,6 @@ class Puppeteer::Page
|
|
1034
1111
|
|
1035
1112
|
define_async_method :async_type_text
|
1036
1113
|
|
1037
|
-
# /**
|
1038
|
-
# * @param {(string|number|Function)} selectorOrFunctionOrTimeout
|
1039
|
-
# * @param {!{visible?: boolean, hidden?: boolean, timeout?: number, polling?: string|number}=} options
|
1040
|
-
# * @param {!Array<*>} args
|
1041
|
-
# * @return {!Promise<!Puppeteer.JSHandle>}
|
1042
|
-
# */
|
1043
|
-
# waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) {
|
1044
|
-
# return this.mainFrame().waitFor(selectorOrFunctionOrTimeout, options, ...args);
|
1045
|
-
# }
|
1046
|
-
|
1047
1114
|
# @param selector [String]
|
1048
1115
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
1049
1116
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
@@ -1054,6 +1121,11 @@ class Puppeteer::Page
|
|
1054
1121
|
|
1055
1122
|
define_async_method :async_wait_for_selector
|
1056
1123
|
|
1124
|
+
# @param milliseconds [Integer] the number of milliseconds to wait.
|
1125
|
+
def wait_for_timeout(milliseconds)
|
1126
|
+
main_frame.wait_for_timeout(milliseconds)
|
1127
|
+
end
|
1128
|
+
|
1057
1129
|
# @param xpath [String]
|
1058
1130
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
1059
1131
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
@@ -1064,12 +1136,13 @@ class Puppeteer::Page
|
|
1064
1136
|
|
1065
1137
|
define_async_method :async_wait_for_xpath
|
1066
1138
|
|
1067
|
-
# @param
|
1068
|
-
# @param
|
1069
|
-
# @param
|
1070
|
-
# @
|
1071
|
-
|
1072
|
-
|
1139
|
+
# @param page_function [String]
|
1140
|
+
# @param args [Integer|Array]
|
1141
|
+
# @param polling [String]
|
1142
|
+
# @param timeout [Integer]
|
1143
|
+
# @return [Puppeteer::JSHandle]
|
1144
|
+
def wait_for_function(page_function, args: [], polling: nil, timeout: nil)
|
1145
|
+
main_frame.wait_for_function(page_function, args: args, polling: polling, timeout: timeout)
|
1073
1146
|
end
|
1074
1147
|
|
1075
1148
|
define_async_method :async_wait_for_function
|