def with_timeout(timeout, timeout_message,
                     exception_class: Wait.default_options[:exception_class],
                     &block)
      if timeout_message.nil? ||
          (timeout_message.is_a?(String) && timeout_message.empty?)
        raise ArgumentError, 'You must provide a timeout message'
      end

      unless block_given?
        raise ArgumentError, 'You must provide a block'
      end

      if timeout.nil?
        raise ArgumentError, 'Timeout cannot be nil'
      end

      # Timeout.timeout will never timeout if the given `timeout` is zero.
      # We will raise an exception if the timeout is zero.
      # Timeout.timeout already raises an exception if `timeout` is negative.
      if timeout == 0
        raise ArgumentError, 'Timeout cannot be 0'
      end

      message = if timeout_message.is_a?(Proc)
                  timeout_message.call({timeout: timeout})
                else
                  timeout_message
                end

      failed = false

      begin
        Timeout.timeout(timeout, PrivateWaitTimeoutError) do
          return block.call
        end
      rescue PrivateWaitTimeoutError => _
        # If we raise Timeout here the stack trace will be cluttered and we
        # wish to show the user a clear message, avoiding
        # "`rescue in with_timeout':" in the stack trace.
        failed = true
      end

      if failed
        raise exception_class, message
      end
    end
def with_timeout(timeout, timeout_message,
                     exception_class: Wait.default_options[:exception_class],
                     &block)
      if timeout_message.nil? ||
          (timeout_message.is_a?(String) && timeout_message.empty?)
        raise ArgumentError, 'You must provide a timeout message'
      end

      unless block_given?
        raise ArgumentError, 'You must provide a block'
      end

      if timeout.nil?
        raise ArgumentError, 'Timeout cannot be nil'
      end

      # Timeout.timeout will never timeout if the given `timeout` is zero.
      # We will raise an exception if the timeout is zero.
      # Timeout.timeout already raises an exception if `timeout` is negative.
      if timeout == 0
        raise ArgumentError, 'Timeout cannot be 0'
      end

      message = if timeout_message.is_a?(Proc)
                  timeout_message.call({timeout: timeout})
                else
                  timeout_message
                end

      failed = false

      begin
        Timeout.timeout(timeout, PrivateWaitTimeoutError) do
          return block.call
        end
      rescue PrivateWaitTimeoutError => _
        # If we raise Timeout here the stack trace will be cluttered and we
        # wish to show the user a clear message, avoiding
        # "`rescue in with_timeout':" in the stack trace.
        failed = true
      end

      if failed
        raise exception_class, message
      end
    end
Evaluates the block given. If the execution time of the block exceeds
 `timeout` it will raise a `exception_class` (default:
 {Calabash::Wait.default_options
 Calabash::Wait.default_options[:exception_class]}).

 If you have an explicit or implicit loop in your block, or
 you want to limit the possible execution time of your block, use
 {Calabash::Wait#with_timeout cal.with_timeout}

 @example
  # If the 'PictureRow' view does not exist, keep panning up.
  cal.with_timeout(15, 'Could not find picture row') do
    cal.pan_screen_up until cal.view_exists?("PictureRow")
  end

 @example
  # Pan up **at least once** and continue pan up until the
  # 'PictureRow' exists.
  cal.wait_for('Could not find picture row') do
    cal.pan_screen_up
    cal.view_exists?("PictureRow")
  end

 @param [Number] timeout The time before failing
 @param [String, Proc] timeout_message The error message if timed out
 @param [Class] exception_class
  (default: {Calabash::Wait.default_options
  Calabash::Wait.default_options[:exception_class]}) The exception type
  raised if timed out
 @return The returned value of the block given
 @raise [ArgumentError] If an invalid timeout is given (<= 0)
 @raise [ArgumentError] If no timeout_message is given
 @raise [ArgumentError] If no block is given