module Calabash::Cucumber::KeyboardHelpers

Collection of methods for interacting with the keyboard.

We’ve gone to great lengths to provide the fastest keyboard entry possible.

Constants

KEYBOARD_QUERY

@!visibility private

KEYBOARD_TYPES

@!visibility private

SPLIT_KEYBOARD_QUERY

@!visibility private

Public Instance Methods

_text_from_first_responder()

@visibility private TODO Remove in 0.21.0

docked_keyboard_visible?() click to toggle source

Returns true if a docked keyboard is visible.

A docked keyboard is pinned to the bottom of the view.

Keyboards on the iPhone and iPod are docked.

@return [Boolean] if a keyboard is visible and docked.

# File lib/calabash-cucumber/keyboard_helpers.rb, line 27
def docked_keyboard_visible?
  keyboard = _query_for_keyboard

  return false if keyboard.nil?

  return true if device_family_iphone?

  keyboard_height = keyboard['rect']['height']
  keyboard_y = keyboard['rect']['y']
  dimensions = screen_dimensions
  scale = dimensions[:scale]

  if landscape?
    screen_height = dimensions[:width]/scale
  else
    screen_height = dimensions[:height]/scale
  end

  screen_height - keyboard_height == keyboard_y
end
expect_keyboard_visible!() click to toggle source

@!visibility private Raises an error ir the keyboard is not visible.

# File lib/calabash-cucumber/keyboard_helpers.rb, line 87
def expect_keyboard_visible!
  if !keyboard_visible?
    screenshot_and_raise "Keyboard is not visible"
  end
  true
end
keyboard_type(query = "* isFirstResponder:1") click to toggle source

@!visibility private Returns the keyboard type as a symbol from the specified query

UIKeyboardTypeDefault => :default UIKeyboardTypeASCIICapable => :ascii_capable UIKeyboardTypeNumbersAndPunctuation => :numbers_and_punctuation UIKeyboardTypeURL => :url UIKeyboardTypeNumberPad => :number_pad UIKeyboardTypePhonePad => :phone_pad UIKeyboardTypeNamePhonePad => :name_phone_pad UIKeyboardTypeEmailAddress => :email UIKeyboardTypeDecimalPad => :decimal UIKeyboardTypeTwitter => :twitter UIKeyboardTypeWebSearch => :web_search

@raise [RuntimeError] if there is no visible keyboard

# File lib/calabash-cucumber/keyboard_helpers.rb, line 207
def keyboard_type(query = "* isFirstResponder:1")
  if !keyboard_visible?
    screenshot_and_raise "There must be a visible keyboard"
  end

  query_result = _query_wrapper(query, :keyboardType).first
  keyboard_type = KEYBOARD_TYPES[query_result]

  if !keyboard_type
    RunLoop.log_debug("Found query_result:#{query_result}, but expected
                      to match key in #{KEYBOARD_TYPES}")
    keyboard_type = :unknown
  end

  keyboard_type
end
keyboard_visible?() click to toggle source

Returns true if there is a visible keyboard.

@return [Boolean] Returns true if there is a visible keyboard.

# File lib/calabash-cucumber/keyboard_helpers.rb, line 78
def keyboard_visible?
  # Order matters!
  docked_keyboard_visible? ||
    undocked_keyboard_visible? ||
    split_keyboard_visible?
end
lookup_key_name(key_code) click to toggle source

Waits for a keyboard to appear and returns the localized name of the ‘key_code` signifier

@param [String] key_code Maps to a specific name in some localization

# File lib/calabash-cucumber/keyboard_helpers.rb, line 147
def lookup_key_name(key_code)
  wait_for_keyboard
  begin
    response_json = JSON.parse(http(:path => 'keyboard-language'))
  rescue JSON::ParserError
    raise RuntimeError, "Could not parse output of keyboard-language route. Did the app crash?"
  end
  if response_json['outcome'] != 'SUCCESS'
    screenshot_and_raise "failed to retrieve the keyboard localization"
  end
  localized_lang = response_json['results']['input_mode']
  RunLoop::L10N.new.lookup_localization_name(key_code, localized_lang)
end
split_keyboard_visible?() click to toggle source

Returns true if a split keyboard is visible.

A split keyboard is floats in the middle of the view and is split to allow faster thumb typing

@return [Boolean] Returns false if the device is not an iPad; all keyboards on the Phone and iPod are docked and not split.

# File lib/calabash-cucumber/keyboard_helpers.rb, line 70
def split_keyboard_visible?
  return false if device_family_iphone?
  _query_for_split_keyboard && !_query_for_keyboard
end
text_from_first_responder() click to toggle source

@!visibility private Returns the the text in the first responder.

The first responder will be the UITextField or UITextView instance that is associated with the visible keyboard.

Returns empty string if no textField or textView elements are found to be the first responder.

@raise [RuntimeError] if there is no visible keyboard

# File lib/calabash-cucumber/keyboard_helpers.rb, line 171
def text_from_first_responder
  if !keyboard_visible?
    screenshot_and_raise "There must be a visible keyboard"
  end

  query = "* isFirstResponder:1"
  elements = _query_wrapper(query, :text)

  return "" if elements.count == 0

  text = elements[0]

  # first responder did not respond to :text selector
  return "" if text == "*****"

  return "" if text.nil?

  text
end
Also aliased as: _text_from_first_responder
undocked_keyboard_visible?() click to toggle source

Returns true if an undocked keyboard is visible.

A undocked keyboard is floats in the middle of the view.

@return [Boolean] Returns false if the device is not an iPad; all keyboards on the iPhone and iPod are docked.

# File lib/calabash-cucumber/keyboard_helpers.rb, line 54
def undocked_keyboard_visible?
  return false if device_family_iphone?

  keyboard = _query_for_keyboard
  return false if keyboard.nil?

  !docked_keyboard_visible?
end
wait_for_keyboard(options={}) click to toggle source

Waits for a keyboard to appear and once it does appear waits for ‘:post_timeout` seconds.

@see Calabash::Cucumber::WaitHelpers#wait_for for other options this

method can handle.

@param [Hash] options controls the ‘wait_for` behavior @option opts [String] :timeout_message (’keyboard did not appear’)

Controls the message that appears in the error.

@option opts [Number] :post_timeout (0.3) Controls how long to wait

_after_ the keyboard has appeared.

@raise [Calabash::Cucumber::WaitHelpers::WaitError] if no keyboard appears

# File lib/calabash-cucumber/keyboard_helpers.rb, line 107
def wait_for_keyboard(options={})
  default_opts = {
    :timeout_message => "Keyboard did not appear",
    :post_timeout => 0.3
  }

  merged_opts = default_opts.merge(options)
  wait_for(merged_opts) do
    keyboard_visible?
  end
  true
end
wait_for_no_keyboard(options={}) click to toggle source

Waits for a keyboard to disappear.

@see Calabash::Cucumber::WaitHelpers#wait_for for other options this

method can handle.

@param [Hash] options controls the ‘wait_for` behavior @option opts [String] :timeout_message (’keyboard did not appear’)

Controls the message that appears in the error.

@raise [Calabash::Cucumber::WaitHelpers::WaitError] If keyboard does

not disappear.
# File lib/calabash-cucumber/keyboard_helpers.rb, line 131
def wait_for_no_keyboard(options={})
  default_opts = {
    :timeout_message => "Keyboard is visible",
  }

  merged_opts = default_opts.merge(options)
  wait_for(merged_opts) do
    !keyboard_visible?
  end
  true
end

Private Instance Methods

_query_for_keyboard() click to toggle source

@!visibility private

# File lib/calabash-cucumber/keyboard_helpers.rb, line 258
def _query_for_keyboard
  _query_wrapper(KEYBOARD_QUERY).first
end
_query_for_split_keyboard() click to toggle source

@!visibility private

# File lib/calabash-cucumber/keyboard_helpers.rb, line 263
def _query_for_split_keyboard
  _query_wrapper(SPLIT_KEYBOARD_QUERY).first
end
_query_wrapper(query, *args) click to toggle source

@!visibility private

# File lib/calabash-cucumber/keyboard_helpers.rb, line 253
def _query_wrapper(query, *args)
  Calabash::Cucumber::Map.map(query, :query, *args)
end