Module: Calabash::Cucumber::KeyboardHelpers

Includes:
Logging, TestsHelpers
Included in:
Operations
Defined in:
lib/calabash-cucumber/keyboard_helpers.rb

Constant Summary collapse

KEYPLANE_NAMES =
{
    :small_letters => 'small-letters',
    :capital_letters => 'capital-letters',
    :numbers_and_punctuation => 'numbers-and-punctuation',
    :first_alternate => 'first-alternate',
    :numbers_and_punctuation_alternate => 'numbers-and-punctuation-alternate'
}
UIA_SUPPORTED_CHARS =
{
      'Delete' => '\b',
      'Return' => '\n'
      # these are not supported yet and I am pretty sure that they
      # cannot be touched by passing an escaped character and instead
      # the must be found using UIAutomation calls.  -jmoody
      #'Dictation' => nil,
      #'Shift' => nil,
      #'International' => nil,
      #'More' => nil,
}

Constants included from Logging

Logging::CALABASH_NO_DEPRECATION

Instance Method Summary collapse

Methods included from Logging

#_deprecated, #calabash_info, #calabash_warn, #debug_logging?, #full_console_logging?, #no_deprecation_warnings?

Methods included from TestsHelpers

#check_element_does_not_exist, #check_element_exists, #check_view_with_mark_exists, #classes, #each_cell, #each_cell_and_back, #element_does_not_exist, #element_exists, #navigation_path, #query_map, #view_with_mark_exists

Methods included from FailureHelpers

#fail, #screenshot, #screenshot_and_raise, #screenshot_embed

Instance Method Details

#_current_keyplaneObject

returns the current keyplane



334
335
336
337
338
339
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 334

def _current_keyplane
  kp_arr = _do_keyplane(
      lambda { query("view:'UIKBKeyplaneView'", 'keyplane', 'componentName') },
      lambda { query("view:'UIKBKeyplaneView'", 'keyplane', 'name') })
  kp_arr.first.downcase
end

#_do_keyplane(kbtree_proc, keyplane_proc) ⇒ Object

process a keyplane

raises an error if there is not visible keyplane



393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 393

def _do_keyplane(kbtree_proc, keyplane_proc)
  desc = query("view:'UIKBKeyplaneView'", 'keyplane')
  fail('No keyplane (UIKBKeyplaneView keyplane)') if desc.empty?
  fail('Several keyplanes (UIKBKeyplaneView keyplane)') if desc.count > 1
  kp_desc = desc.first
  if /^<UIKBTree/.match(kp_desc)
    #ios5+
    kbtree_proc.call
  elsif /^<UIKBKeyplane/.match(kp_desc)
    #ios4
    keyplane_proc.call
  end
end

#_ensure_can_enter_text(opts = {}) ⇒ Object

ensures that there is a keyboard to enter text

IMPORTANT will always raise an error when the keyboard is split and there is no run_loop i.e. UIAutomation is not available

the default options are

:screenshot +true+ raise with a screenshot
:skip +false+ skip any checking (a nop) - used when iterating over
keyplanes for keys


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 168

def _ensure_can_enter_text(opts={})
  default_opts = {:screenshot => true,
                  :skip => false}
  opts = default_opts.merge(opts)
  return if opts[:skip]

  screenshot = opts[:screenshot]
  unless keyboard_visible?
    msg = 'no visible keyboard'
    if screenshot
      screenshot_and_raise msg
    else
      raise msg
    end
  end

  if split_keyboard_visible? and uia_not_available?
    msg = 'cannot type on a split keyboard without launching with Instruments'
    if screenshot
      screenshot_and_raise msg
    else
      raise msg
    end
  end
end

#_ipad_keyboard_modesObject

returns an array of possible ipad keyboard modes



123
124
125
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 123

def _ipad_keyboard_modes
  [:docked, :undocked, :split]
end

#_point_for_ipad_keyboard_mode_keyObject

returns the activation point of the iPad keyboard mode key.

the mode key is also known as the Hide keyboard key.

raises an error when

  • the device is not an iPad

  • the app was not launched with instruments i.e. there is no run_loop



439
440
441
442
443
444
445
446
447
448
449
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 439

def _point_for_ipad_keyboard_mode_key
  raise 'the keyboard mode does not exist on the on the iphone' if device_family_iphone?
  raise 'cannot detect keyboard mode key without launching with instruments' unless uia_available?
  res = send_uia_command({:command => "#{_query_uia_hide_keyboard_button}.rect()"})
  origin = res['value']['origin']
  {:x => origin['x'], :y => origin['y']}

  # this did not work.
  #size = res['value']['size']
  #{:x => (origin['x'] + (size['width']/2)), :y => (origin['y'] + (size['height']/2))}
end

#_qstr_for_keyboardObject

returns a query string for detecting a keyboard



37
38
39
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 37

def _qstr_for_keyboard
  "view:'UIKBKeyplaneView'"
end

#_query_for_keyboard_mode_keyObject

returns a query for touching the iPad keyboard mode key.

the mode key is also know as the Hide keyboard key.

use _point_for_keyboard_mode_key if there is a run_loop available

raises an error when

  • the device is not an iPad

  • the app was launched with Instruments i.e. there is a run_loop



505
506
507
508
509
510
511
512
513
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 505

def _query_for_keyboard_mode_key
  raise 'cannot detect keyboard mode key on iphone' if device_family_iphone?
  if uia_available?
    raise "UIA is available, use '_point_for_keyboard_mode_key' instead"
  end
  qstr = "view:'UIKBKeyView'"
  idx = query(qstr).count - 1
  "#{qstr} index:#{idx}"
end

#_query_for_touch_for_keyboard_mode_option(top_or_bottom, mode) ⇒ Object

returns a query string for touching one of the options that appears when the iPad mode key is touched and held.

the mode key is also know as the Hide keyboard key.

valid arguments are:

top_or_bottom :top | :bottom
mode :docked | :undocked | :skipped

use _point_for_keyboard_mode_key if there is a run_loop available

raises an error when

  • the device is not an iPad

  • the app was launched with Instruments i.e. there is a run_loop

  • it is passed invalid arguments



468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 468

def _query_for_touch_for_keyboard_mode_option(top_or_bottom, mode)
  raise 'the keyboard mode does not exist on the iphone' if device_family_iphone?

  if uia_available?
    raise "UIA is available, use '_point_for_keyboard_mode_key' instead"
  end

  valid = [:top, :bottom]
  unless valid.include? top_or_bottom
    raise "expected '#{top_or_bottom}' to be one of '#{valid}'"
  end

  valid = [:split, :undocked, :docked]
  unless valid.include? mode
    raise "expected '#{mode}' to be one of '#{valid}'"
  end

  hash = {:split => {:top => 'Merge',
                     :bottom => 'Dock and Merge'},
          :undocked => {:top => 'Dock',
                        :bottom => 'Split'},
          :docked => {:top => 'Undock',
                      :bottom => 'Split'}}
  mark = hash[mode][top_or_bottom]
  "label marked:'#{mark}'"
end

#_query_uia_hide_keyboard_buttonObject

returns a query string for finding the iPad ‘Hide keyboard’ button



408
409
410
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 408

def _query_uia_hide_keyboard_button
  "uia.keyboard().buttons()['Hide keyboard']"
end

#_search_keyplanes_and_enter_char(chr, visited = Set.new) ⇒ Object

searches the available keyplanes for chr and if it is found, types it

this is a recursive function

IMPORTANT: use the KEYPLANE_SEARCH_STEP_PAUSE variable to control how quickly the next keyplane is searched. increase this value if you encounter problems with missed keystrokes.

raises an error if the chr cannot be found



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 350

def _search_keyplanes_and_enter_char(chr, visited=Set.new)
  cur_kp = _current_keyplane
  begin
    keyboard_enter_char(chr, {:should_screenshot => false})
    return true #found
  rescue
    pause = (ENV['KEYPLANE_SEARCH_STEP_PAUSE'] || 0.2).to_f
    sleep (pause) if pause > 0

    visited.add(cur_kp)

    #figure out keyplane alternates
    props = _do_keyplane(
        lambda { query("view:'UIKBKeyplaneView'", 'keyplane', 'properties') },
        lambda { query("view:'UIKBKeyplaneView'", 'keyplane', 'attributes', 'dict') }
    ).first

    known = KEYPLANE_NAMES.values

    found = false
    keyplane_selection_keys = ['shift', 'more']
    keyplane_selection_keys.each do |key|
      sleep (pause) if pause > 0
      plane = props["#{key}-alternate"]
      if known.member?(plane) and (not visited.member?(plane))
        keyboard_enter_char(key.capitalize, {:should_screenshot => false})
        found = _search_keyplanes_and_enter_char(chr, visited)
        return true if found
        #not found => try with other keyplane selection key
        keyplane_selection_keys.delete(key)
        other_key = keyplane_selection_keys.last
        keyboard_enter_char(other_key.capitalize, {:should_screenshot => false})
        found = _search_keyplanes_and_enter_char(chr, visited)
        return true if found
      end
    end
    return false
  end
end

#_touch_bottom_keyboard_mode_rowObject

touches the bottom option on the popup dialog that is presented when the the iPad keyboard mode key is touched and held.

the mode key is also know as the Hide keyboard key.

the mode key allows the user to undock, dock, or split the keyboard.



521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 521

def _touch_bottom_keyboard_mode_row
  mode = ipad_keyboard_mode
  if uia_available?
    start_pt = _point_for_ipad_keyboard_mode_key
    # there are 10 pt btw the key and the popup and the row is 50 pt
    y_offset = 10 + 25
    end_pt = {:x => (start_pt[:x] - 40), :y => (start_pt[:y] - y_offset)}
    uia_pan_offset(start_pt, end_pt, {})
  else
    pan(_query_for_keyboard_mode_key, nil, {:duration => 1.0})
    touch(_query_for_touch_for_keyboard_mode_option(:bottom, mode))
    sleep(0.5)
  end
  2.times { sleep(0.5) }
end

#_touch_top_keyboard_mode_rowObject

touches the top option on the popup dialog that is presented when the the iPad keyboard mode key is touched and held.

the mode key is also know as the Hide keyboard key.

the mode key allows the user to undock, dock, or split the keyboard.



543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 543

def _touch_top_keyboard_mode_row
  mode = ipad_keyboard_mode
  if uia_available?
    start_pt = _point_for_ipad_keyboard_mode_key
    # there are 10 pt btw the key and the popup and each row is 50 pt
    # NB: no amount of offsetting seems to allow touching the top row
    #     when the keyboard is split
    y_offset = 10 + 50 + 25
    end_pt = {:x => (start_pt[:x] - 40), :y => (start_pt[:y] - y_offset)}
    uia_pan_offset(start_pt, end_pt, {:duration => 1.0})
  else
    pan(_query_for_keyboard_mode_key, nil, {})
    touch(_query_for_touch_for_keyboard_mode_option(:top, mode))
    sleep(0.5)
  end
  2.times { sleep(0.5) }
end

#_wait_for_keyboard_in_mode(mode, opts = {}) ⇒ Object



675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 675

def _wait_for_keyboard_in_mode(mode, opts={})
  default_opts = {:post_timeout => 1.0}
  opts = default_opts.merge(opts)
  begin
    wait_for(opts) do
      case mode
        when :split then
          split_keyboard_visible?
        when :undocked
          undocked_keyboard_visible?
        when :docked
          docked_keyboard_visible?
        else
          screenshot_and_raise "expected '#{mode}' to be one of #{_ipad_keyboard_modes}"
      end
    end
  rescue
    actual = ipad_keyboard_mode
    o = status_bar_orientation
    screenshot_and_raise "expected keyboard to be '#{mode}' but found '#{actual}' in orientation '#{o}'"
  end
end

#await_keyboardObject

DEPRECATED: Use wait_for_keyboard instead.



117
118
119
120
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 117

def await_keyboard
  _deprecated('0.9.163', "use 'wait_for_keyboard' instead", :warn)
  wait_for_keyboard
end

#dismiss_ipad_keyboardObject

dismisses a iPad keyboard by touching the ‘Hide keyboard’ button and waits for the keyboard to disappear

raises an error if the device is not an iPad. the dismiss keyboard key does not exist on the iPhone or iPod



417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 417

def dismiss_ipad_keyboard
  screenshot_and_raise 'cannot dismiss keyboard on iphone' if device_family_iphone?

  if uia_available?
    send_uia_command({:command =>  "#{_query_uia_hide_keyboard_button}.tap()"})
  else
    touch(_query_for_keyboard_mode_key)
  end

  opts = {:timeout_message => 'keyboard did not disappear'}
  wait_for(opts) do
    not keyboard_visible?
  end
end

#docked_keyboard_visible?Boolean

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.

Returns:

  • (Boolean)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 46

def docked_keyboard_visible?
  res = query(_qstr_for_keyboard).first
  return false if res.nil?

  return true if device_family_iphone?

  # ipad
  rect = res['rect']
  o = status_bar_orientation.to_sym
  case o
    when :left then
      rect['center_x'] == 592 and rect['center_y'] == 512
    when :right then
      rect['center_x'] == 176 and rect['center_y'] == 512
    when :up then
      rect['center_x'] == 384 and rect['center_y'] == 132
    when :down then
      rect['center_x'] == 384 and rect['center_y'] == 892
    else
      false
  end

end

#doneObject

touches the keyboard action key

the action key depends on the keyboard.

some examples include:

  • Return

  • Next

  • Go

  • Join

  • Search

not all keyboards have an action key raises an error if the key cannot be entered



329
330
331
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 329

def done
  tap_keyboard_action_key
end

#ensure_docked_keyboardObject

ensures that the iPad keyboard is docked

docked means the keyboard is pinned to bottom of the view

if the device is not an iPad, this is behaves like a call to wait_for_keyboard

raises an error when

  • there is no visible keyboard or

  • the docked keyboard cannot be achieved



571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 571

def ensure_docked_keyboard
  wait_for_keyboard

  return if device_family_iphone?

  mode = ipad_keyboard_mode
  case mode
    when :split then
      _touch_bottom_keyboard_mode_row
    when :undocked then
      _touch_top_keyboard_mode_row
    when :docked then
      # already docked
    else
    screenshot_and_raise "expected '#{mode}' to be one of #{_ipad_keyboard_modes}"
  end

  begin
    wait_for({:post_timeout => 1.0}) do
      docked_keyboard_visible?
    end
  rescue
    mode = ipad_keyboard_mode
    o = status_bar_orientation
    screenshot_and_raise "expected keyboard to be ':docked' but found '#{mode}' in orientation '#{o}'"
  end
end

#ensure_split_keyboardObject

ensures that the iPad keyboard is split

split means the keyboard is floating in the middle of the view and is split into two sections to enable faster thumb typing.

if the device is not an iPad, this is behaves like a call to wait_for_keyboard

raises an error when

  • there is no visible keyboard or

  • the an undocked keyboard cannot be achieved



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 655

def ensure_split_keyboard
  wait_for_keyboard

  return if device_family_iphone?

  mode = ipad_keyboard_mode
  case mode
    when :split then
      # already split
    when :undocked then
      _touch_bottom_keyboard_mode_row
    when :docked then
      _touch_bottom_keyboard_mode_row
    else
      screenshot_and_raise "expected '#{mode}' to be one of #{_ipad_keyboard_modes}"
  end

  _wait_for_keyboard_in_mode(:split)
end

#ensure_undocked_keyboardObject

ensures that the iPad keyboard is undocked

undocked means the keyboard is floating in the middle of the view

if the device is not an iPad, this is behaves like a call to wait_for_keyboard

raises an error when

  • there is no visible keyboard or

  • the an undocked keyboard cannot be achieved



610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 610

def ensure_undocked_keyboard
  wait_for_keyboard()

  return if device_family_iphone?

  mode = ipad_keyboard_mode
  case mode
    when :split then
      # keep these condition separate because even though they do the same
      # thing, the else condition is a hack
      if ios5?
        # iOS 5 has no 'Merge' feature in split keyboard, so dock first then
        # undock from docked mode
        _touch_bottom_keyboard_mode_row
        _wait_for_keyboard_in_mode(:docked)
      else
        # in iOS > 5, it seems to be impossible consistently touch the
        # the top keyboard mode popup button, so we punt
        _touch_bottom_keyboard_mode_row
        _wait_for_keyboard_in_mode(:docked)
      end
      _touch_top_keyboard_mode_row
    when :undocked then
      # already undocked
    when :docked then
      _touch_top_keyboard_mode_row
    else
      screenshot_and_raise "expected '#{mode}' to be one of #{_ipad_keyboard_modes}"
  end

  _wait_for_keyboard_in_mode(:undocked)
end

#ipad_keyboard_mode(opts = {}) ⇒ Object

returns the keyboard mode

                keyboard is pinned to bottom of the view #=> :docked
          keyboard is floating in the middle of the view #=> :undocked
                          keyboard is floating and split #=> :split
no keyboard and :raise_on_no_visible_keyboard == +false+ #=> :unknown

raises an error if the device is not an iPad

raises an error if the :raise_on_no_visible_keyboard is true (default) and no keyboard is visible

set :raise_on_no_visible_keyboard to false to use in wait functions



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 141

def ipad_keyboard_mode(opts = {})
  raise 'the keyboard mode does not exist on the iphone or ipod' if device_family_iphone?

  default_opts = {:raise_on_no_visible_keyboard => true}
  opts = default_opts.merge(opts)
  if opts[:raise_on_no_visible_keyboard]
    screenshot_and_raise 'there is no visible keyboard' unless keyboard_visible?
    return :docked if docked_keyboard_visible?
    return :undocked if undocked_keyboard_visible?
    :split
  else
    return :docked if docked_keyboard_visible?
    return :undocked if undocked_keyboard_visible?
    return :split if split_keyboard_visible?
    :unknown
  end
end

#keyboard_enter_char(chr, opts = {}) ⇒ Object

use keyboard to enter chr

IMPORTANT: use the POST_ENTER_KEYBOARD environmental variable to slow down the typing; adds a wait after each character is touched. this can fix problems where the typing is too fast and characters are skipped.

there are several special ‘characters’, some of which do not appear on all keyboards:

  • ‘Delete’

  • ‘Return’

raises error if there is no visible keyboard or the keyboard is not supported

use the should_screenshot to control whether or not to raise an error if chr is not found



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 211

def keyboard_enter_char(chr, opts={})
  unless opts.is_a?(Hash)
   msg = "you should no longer pass a boolean as the second arg; pass {:should_screenshot => '#{opts}'}  hash instead"
   _deprecated('0.9.163', msg, :warn)
   opts = {:should_screenshot => opts}
  end

  default_opts = {:should_screenshot => true,
                  # introduce a small wait to avoid skipping characters
                  # keep this as short as possible
                  :wait_after_char => (ENV['POST_ENTER_KEYBOARD'] || 0.05).to_f}

  opts = default_opts.merge(opts)

  should_screenshot = opts[:should_screenshot]
  _ensure_can_enter_text({:screenshot => should_screenshot,
                          :skip => (not should_screenshot)})

  if uia_available?
    if chr.length == 1
      uia_type_string chr
    else
      code = UIA_SUPPORTED_CHARS[chr]

      unless code
        raise "typing character '#{chr}' is not yet supported when running with Instruments"
      end

      # on iOS 6, the Delete char code is _not_ \b
      # on iOS 7, the Delete char code is \b on non-numeric keyboards
      #           on numeric keyboards, it is actually a button on the
      #           keyboard and not a key
      if code.eql?(UIA_SUPPORTED_CHARS['Delete'])
        uia("uia.keyboard().elements().firstWithName('Delete').tap()")
      elsif code.eql?(UIA_SUPPORTED_CHARS['Return'])
        tap_keyboard_action_key
      else
        uia_type_string(code, '')
      end
    end
    res = {'results' => []}
  else
    res = http({:method => :post, :path => 'keyboard'},
               {:key => chr, :events => load_playback_data('touch_done')})
    res = JSON.parse(res)
    if res['outcome'] != 'SUCCESS'
      msg = "Keyboard enter failed failed because: #{res['reason']}\n#{res['details']}"
      if should_screenshot
        screenshot_and_raise msg
      else
        raise msg
      end
    end
  end

  if ENV['POST_ENTER_KEYBOARD']
    w = ENV['POST_ENTER_KEYBOARD'].to_f
    if w > 0
      sleep(w)
    end
  end
  pause = opts[:wait_after_char]
  sleep(pause) if pause > 0
  res['results']
end

#keyboard_enter_text(text) ⇒ Object

uses the keyboard to enter text

raises an error if the text cannot be entered



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 280

def keyboard_enter_text(text)
  _ensure_can_enter_text
  if uia_available?
    text_before = _text_from_first_responder()
    text_before = text_before.gsub("\n","\\n") if text_before
    uia_type_string(text, text_before)
  else
    text.each_char do |ch|
      begin
        keyboard_enter_char(ch, {:should_screenshot => false})
      rescue
        _search_keyplanes_and_enter_char(ch)
      end
    end
  end
end

#keyboard_visible?Boolean

returns true if there is a visible keyboard

Returns:

  • (Boolean)


99
100
101
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 99

def keyboard_visible?
  docked_keyboard_visible? or undocked_keyboard_visible? or split_keyboard_visible?
end

#split_keyboard_visible?Boolean

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

returns false if the device is not an iPad; all keyboards on the iPhone and iPod are docked

Returns:

  • (Boolean)


92
93
94
95
96
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 92

def split_keyboard_visible?
  return false if device_family_iphone?
  query("view:'UIKBKeyView'").count > 0 and
        element_does_not_exist(_qstr_for_keyboard)
end

#tap_keyboard_action_keyObject

touches the keyboard action key

the action key depends on the keyboard. some examples include:

  • Return

  • Next

  • Go

  • Join

  • Search

not all keyboards have an action key raises an error if the key cannot be entered



308
309
310
311
312
313
314
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 308

def tap_keyboard_action_key
  if uia_available?
    uia_type_string '\n', '', false
  else
    keyboard_enter_char 'Return'
  end
end

#uia_keyboard_visible?Boolean

used for detecting keyboards that are not normally visible to calabash e.g. the keyboard on ‘z’

IMPORTANT this should only be used when the app does not respond to keyboard_visible?

raises an error if the there is no run_loop

Returns:

  • (Boolean)


705
706
707
708
709
710
711
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 705

def uia_keyboard_visible?
  unless uia_available?
    screenshot_and_raise 'only available if there is a run_loop i.e. the app was launched with Instruments'
  end
  res = uia_query_windows(:keyboard)
  not res.eql?(':nil')
end

#uia_wait_for_keyboard(opts = {}) ⇒ Object

waits for a keyboard that is not normally visible to calabash e.g. the keyboard on MFMailComposeViewController

IMPORTANT this should only be used when the app does not respond to keyboard_visible?

raises an error if the there is no run_loop



720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 720

def uia_wait_for_keyboard(opts={})
  unless uia_available?
    screenshot_and_raise 'only available if there is a run_loop i.e. the app was launched with Instruments'
  end
  default_opts = {:timeout => 10,
                  :retry_frequency => 0.1,
                  :post_timeout => 0.5}
  opts = default_opts.merge(opts)
  unless opts[:timeout_message]
    msg = "waited for '#{opts[:timeout]}' for keyboard"
    opts[:timeout_message] = msg
  end

  wait_for(opts) do
    uia_keyboard_visible?
  end
end

#undocked_keyboard_visible?Boolean

returns true if an undocked keyboard is visible.

a undocked keyboard is floats in the middle of the view

returns false if the device is not an iPad; all keyboards on the iPhone and iPod are docked

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 76

def undocked_keyboard_visible?
  return false if device_family_iphone?

  res = query(_qstr_for_keyboard).first
  return false if res.nil?

  not docked_keyboard_visible?
end

#wait_for_keyboard(opts = {}) ⇒ Object

waits for a keyboard to appear and once it does appear waits for 0.3 seconds

raises an error if no keyboard appears



107
108
109
110
111
112
113
114
# File 'lib/calabash-cucumber/keyboard_helpers.rb', line 107

def wait_for_keyboard(opts={})
  default_opts = {:timeout_message => 'keyboard did not appear',
                  :post_timeout => 0.3}
  opts = default_opts.merge(opts)
  wait_for(opts) do
    keyboard_visible?
  end
end