ferrum icon indicating copy to clipboard operation
ferrum copied to clipboard

Implement wait_for_selector

Open route opened this issue 5 years ago • 4 comments

https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagewaitforselectorselector-options

route avatar May 20 '20 06:05 route

      sleep(@browser.slowmo) if slowmoable && @browser.slowmo > 0

Is this part of addressing this? Was thinking of just doing a sleep on slowmo define time, we can just do an interval loop to wait on a specific element on the page to show.

Because of this sleep, my current test run seems to take too long to complete.

Daniel-ltw avatar Jun 22 '20 00:06 Daniel-ltw

This is my hacky attempt in my own spec_helper.rb. Rather than just using slowmo.

def wait_for(css_element, visibility: :all)
  @staled_retries ||= 120
  element = first(css_element, visible: visibility, wait: 0.3)
  warn_log "Found #{css_element}"
  yield(element) if block_given?
  element
rescue Capybara::ElementNotFound, Capybara::ExpectationNotMet => e
  warn_log "#{css_element} stale for: #{@staled_retries}"
  if @staled_retries.zero?
    page_path = save_page
    screenshot_path = save_screenshot
    debug_log "Page at #{page_path}"
    debug_log "Screenshot at #{screenshot_path}"
    raise e
  else
    @staled_retries -= 1
    sleep(0.2)
    retry
  end
end

Daniel-ltw avatar Jun 26 '20 01:06 Daniel-ltw

I've been using this... seems like something like this should be in Ferrum.

module Ferrum
  class Frame
    module DOM

      #
      # Finds a node using XPath or a CSS path selector, with waiting.
      #
      # @param [String] selector
      #   The XPath or CSS path selector.
      #
      # @param [Integer] init
      #   How long we should wait before starting to look.
      #
      # @param [Integer] wait
      #   How long we should wait for node to appear.
      #
      # @param [Integer] step
      #   How long to wait between checking.
      #
      # @return [Node, nil]
      #   The matching node.
      #
      # @example
      #   browser.with("a[aria-label='CA']", init:1, wait:5, step:0.2) # => Node
      #
      def with(selector, init:nil, wait:1, step:0.1)
        sleep(init) if init
        meth = selector.start_with?("/") ? :at_xpath : :at_css
        until node = send(meth, selector) rescue nil
          (wait -= step) > 0 ? sleep(step) : break
        end
        node
      end
    end
  end
end

I use it like this:

site.with("#iux-identifier-user-id", init: 2, wait:8, step: 0.5).focus.type(user)

shreeve avatar Mar 21 '24 19:03 shreeve

This is quite a bit simpler than #236, granted this one is just pure Ruby version and doesn't use js timeouts, etc.

shreeve avatar Mar 21 '24 19:03 shreeve