lib/puppeteer/page.rb in puppeteer-ruby-0.0.15 vs lib/puppeteer/page.rb in puppeteer-ruby-0.0.16

- old
+ new

@@ -687,46 +687,99 @@ main_frame.send(:wait_for_navigation, timeout: timeout, wait_until: wait_until) end define_async_method :async_wait_for_navigation - # /** - # * @param {(string|Function)} urlOrPredicate - # * @param {!{timeout?: number}=} options - # * @return {!Promise<!Puppeteer.Request>} - # */ - # async waitForRequest(urlOrPredicate, options = {}) { - # const { - # timeout = this._timeoutSettings.timeout(), - # } = options; - # return helper.waitForEvent(this._frameManager.networkManager(), Events.NetworkManager.Request, request => { - # if (helper.isString(urlOrPredicate)) - # return (urlOrPredicate === request.url()); - # if (typeof urlOrPredicate === 'function') - # return !!(urlOrPredicate(request)); - # return false; - # }, timeout, this._sessionClosePromise()); - # } + private def wait_for_network_manager_event(event_name, predicate:, timeout:) + option_timeout = timeout || @timeout_settings.timeout - # /** - # * @param {(string|Function)} urlOrPredicate - # * @param {!{timeout?: number}=} options - # * @return {!Promise<!Puppeteer.Response>} - # */ - # async waitForResponse(urlOrPredicate, options = {}) { - # const { - # timeout = this._timeoutSettings.timeout(), - # } = options; - # return helper.waitForEvent(this._frameManager.networkManager(), Events.NetworkManager.Response, response => { - # if (helper.isString(urlOrPredicate)) - # return (urlOrPredicate === response.url()); - # if (typeof urlOrPredicate === 'function') - # return !!(urlOrPredicate(response)); - # return false; - # }, timeout, this._sessionClosePromise()); - # } + @wait_for_network_manager_event_listener_ids ||= {} + if_present(@wait_for_network_manager_event_listener_ids[event_name]) do |listener_id| + @frame_manager.network_manager.remove_event_listener(listener_id) + end + promise = resolvable_future + + @wait_for_network_manager_event_listener_ids[event_name] = + @frame_manager.network_manager.add_event_listener(event_name) do |event_target| + if predicate.call(event_target) + promise.fulfill(nil) + end + end + + begin + Timeout.timeout(option_timeout / 1000.0) do + await_any(promise, session_close_promise) + end + rescue Timeout::Error + raise Puppeteer::TimeoutError.new("waiting for #{event_name} failed: timeout #{timeout}ms exceeded") + ensure + @frame_manager.network_manager.remove_event_listener(@wait_for_network_manager_event_listener_ids[event_name]) + end + end + + private def session_close_promise + @disconnect_promise ||= resolvable_future do |future| + @client.observe_first('Events.CDPSession.Disconnected') do + future.reject(Puppeteer::CDPSession::Error.new('Target Closed')) + end + end + end + + # - Waits until request URL matches + # `wait_for_request(url: 'https://example.com/awesome')` + # - Waits until request matches the given predicate + # `wait_for_request(predicate: -> (req){ req.url.start_with?('https://example.com/search') })` + # + # @param url [String] + # @param predicate [Proc(Puppeteer::Request -> Boolean)] + private def wait_for_request(url: nil, predicate: nil, timeout: nil) + if !url && !predicate + raise ArgumentError.new('url or predicate must be specified') + end + if predicate && !predicate.is_a?(Proc) + raise ArgumentError.new('predicate must be a proc.') + end + request_predicate = + if url + -> (request) { request.url == url } + else + -> (request) { predicate.call(request) } + end + + wait_for_network_manager_event('Events.NetworkManager.Request', + predicate: request_predicate, + timeout: timeout, + ) + end + + define_async_method :async_wait_for_request + + # @param url [String] + # @param predicate [Proc(Puppeteer::Request -> Boolean)] + private def wait_for_response(url: nil, predicate: nil, timeout: nil) + if !url && !predicate + raise ArgumentError.new('url or predicate must be specified') + end + if predicate && !predicate.is_a?(Proc) + raise ArgumentError.new('predicate must be a proc.') + end + response_predicate = + if url + -> (response) { response.url == url } + else + -> (response) { predicate.call(response) } + end + + wait_for_network_manager_event('Events.NetworkManager.Response', + predicate: response_predicate, + timeout: timeout, + ) + end + + define_async_method :async_wait_for_response + # @param timeout [number|nil] # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2' def go_back(timeout: nil, wait_until: nil) go(-1, timeout: timeout, wait_until: wait_until) end @@ -760,24 +813,23 @@ return if @javascript_enabled == enabled @javascript_enabled = enabled @client.send_message('Emulation.setScriptExecutionDisabled', value: !enabled) end - # /** - # * @param {boolean} enabled - # */ - # async setBypassCSP(enabled) { - # await this._client.send('Page.setBypassCSP', { enabled }); - # } + # @param enabled [Boolean] + def bypass_csp=(enabled) + @client.send_message('Page.setBypassCSP', enabled: enabled) + end - # /** - # * @param {?string} type - # */ - # async emulateMediaType(type) { - # assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type); - # await this._client.send('Emulation.setEmulatedMedia', {media: type || ''}); - # } + # @param media_type [String|Symbol|nil] either of (media, print, nil) + def emulate_media_type(media_type) + media_type_str = media_type.to_s + unless ['screen', 'print', ''].include?(media_type_str) + raise ArgumentError.new("Unsupported media type: #{media_type}") + end + @client.send_message('Emulation.setEmulatedMedia', media: media_type_str) + end # /** # * @param {?Array<MediaFeature>} features # */ # async emulateMediaFeatures(features) { @@ -793,11 +845,11 @@ # } # } # @param timezone_id [String?] def emulate_timezone(timezone_id) - @client.send_message('Emulation.setTimezoneOverride', timezoneId: timezoneId || '') + @client.send_message('Emulation.setTimezoneOverride', timezoneId: timezone_id || '') rescue => err if err.message.include?('Invalid timezone') raise ArgumentError.new("Invalid timezone ID: #{timezone_id}") else raise err @@ -1031,19 +1083,9 @@ def type_text(selector, text, delay: nil) main_frame.type_text(selector, text, delay: delay) end define_async_method :async_type_text - - # /** - # * @param {(string|number|Function)} selectorOrFunctionOrTimeout - # * @param {!{visible?: boolean, hidden?: boolean, timeout?: number, polling?: string|number}=} options - # * @param {!Array<*>} args - # * @return {!Promise<!Puppeteer.JSHandle>} - # */ - # waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) { - # return this.mainFrame().waitFor(selectorOrFunctionOrTimeout, options, ...args); - # } # @param selector [String] # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false. # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false. # @param timeout [Integer]