Override Selenium’s Element#click with SimpleDelegator

Sometimes you click on an element that has just reloaded. Then Selenium returns Element 1 could not be tapped. To overcome that you can use something like:

def compose
  start = Time.now
  begin
    find_element(name: 'Compose').click
  rescue Selenium::WebDriver::Error::UnknownError => e
    fail "Compose button hasn't been tapped in 5 seconds" if Time.now > start + 5
    retry if e.message.include?('could not be tapped')
    raise e
  end
end

However if there are several such ‘unstable’ components, you can decorate #click as follows:

def compose_button
  FlickeringButton.new(find_element(name: 'Compose')).click
end

class FlickeringButton < SimpleDelegator
  def click
    start = Time.now
    begin
      super
    rescue Selenium::WebDriver::Error::UnknownError => e
      fail "Button hasn't been tapped in 5 seconds" if Time.now > start + 5
      retry if e.message.include?('could not be tapped')
      raise e
    end
  end
end

One little quirk I noticed. super inside subclass of SimpleDelegator doesn’t work during Pry session. Use self.__getobj__.name_of_method instead.