Module: Calabash::Cucumber::Core

Constant Summary

Constants included from PlaybackHelpers

PlaybackHelpers::DATA_PATH

Instance Method Summary collapse

Methods included from PlaybackHelpers

#find_compatible_recording, #interpolate, #load_playback_data, #load_recording, #playback, #playback_file_directories, #record_begin, #record_end, #recording_name_for

Methods included from RotationHelpers

#rotate, #rotate_home_button_to, #rotation_candidates

Methods included from StatusBarHelpers

#device_orientation, #landscape?, #portrait?, #status_bar_orientation

Methods included from UIA

#escape_uia_string, #send_uia_command, #uia, #uia_call, #uia_call_method, #uia_call_windows, #uia_double_tap, #uia_double_tap_mark, #uia_double_tap_offset, #uia_element_does_not_exist?, #uia_element_exists?, #uia_enter, #uia_flick_offset, #uia_handle_command, #uia_names, #uia_pan, #uia_pan_offset, #uia_pinch, #uia_pinch_offset, #uia_query, #uia_query_el, #uia_query_windows, #uia_screenshot, #uia_scroll_to, #uia_send_app_to_background, #uia_serialize_argument, #uia_serialize_arguments, #uia_serialize_command, #uia_set_location, #uia_swipe, #uia_swipe_offset, #uia_tap, #uia_tap_mark, #uia_tap_offset, #uia_touch_hold, #uia_touch_hold_offset, #uia_two_finger_tap, #uia_two_finger_tap_offset, #uia_type_string

Methods included from Map

#assert_map_results, #map, #raw_map

Methods included from FailureHelpers

#fail, #screenshot, #screenshot_and_raise, #screenshot_embed

Methods included from QueryHelpers

#escape_quotes, #point_from

Methods included from ConnectionHelpers

#connection, #http

Methods included from EnvironmentHelpers

#_deprecated, #debug_logging?, #default_device, #device_family_iphone?, #full_console_logging?, #ios5?, #ios6?, #ios7?, #ipad?, #iphone?, #iphone_4in?, #iphone_5?, #iphone_app_emulated_on_ipad?, #ipod?, #no_deprecation_warnings?, #simulator?, #uia_available?, #uia_not_available?, #xamarin_test_cloud?

Instance Method Details

#_debug_level_response(json) ⇒ Object



452
453
454
455
456
457
458
# File 'lib/calabash-cucumber/core.rb', line 452

def _debug_level_response(json)
  res = JSON.parse(json)
  if res['outcome'] != 'SUCCESS'
    screenshot_and_raise "debug_level #{json} failed because: #{res['reason']}\n#{res['details']}"
  end
  res['results'].first
end

#backdoor(sel, arg) ⇒ Object



420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/calabash-cucumber/core.rb', line 420

def backdoor(sel, arg)
  json = {
        :selector => sel,
        :arg => arg
  }
  res = http({:method => :post, :path => 'backdoor'}, json)
  res = JSON.parse(res)
  if res['outcome'] != 'SUCCESS'
    screenshot_and_raise "backdoor #{json} failed because: #{res['reason']}\n#{res['details']}"
  end
  res['result']
end

#calabash_exitObject



433
434
435
436
437
438
439
440
441
442
# File 'lib/calabash-cucumber/core.rb', line 433

def calabash_exit
  # Exiting the app shuts down the HTTP connection and generates ECONNREFUSED,
  # or HTTPClient::KeepAliveDisconnected
  # which needs to be suppressed.
  begin
    http({:method => :post, :path => 'exit', :retryable_errors => Calabash::Cucumber::HTTPHelpers::RETRYABLE_ERRORS - [Errno::ECONNREFUSED, HTTPClient::KeepAliveDisconnected]})
  rescue Errno::ECONNREFUSED, HTTPClient::KeepAliveDisconnected
    []
  end
end

#cell_swipe(options = {}) ⇒ Object



114
115
116
117
118
119
# File 'lib/calabash-cucumber/core.rb', line 114

def cell_swipe(options={})
  if uia_available?
    raise 'cell_swipe not supported with instruments, simply use swipe with a query that matches the cell'
  end
  playback('cell_swipe', options)
end

#client_versionObject



61
62
63
# File 'lib/calabash-cucumber/core.rb', line 61

def client_version
  Calabash::Cucumber::VERSION
end

#console_attachObject



478
479
480
481
# File 'lib/calabash-cucumber/core.rb', line 478

def console_attach
  # setting the @calabash_launcher here for backward compatibility
  @calabash_launcher = launcher.attach
end

#double_tap(uiquery, options = {}) ⇒ Object



77
78
79
# File 'lib/calabash-cucumber/core.rb', line 77

def double_tap(uiquery, options={})
  query_action_with_options(:double_tap, uiquery, options)
end

#extract_query_and_options(uiquery, options) ⇒ Object



498
499
500
501
# File 'lib/calabash-cucumber/core.rb', line 498

def extract_query_and_options(uiquery, options)
  options = prepare_query_options(uiquery, options)
  return options[:query], options
end

#flash(uiquery, *args) ⇒ Object

causes all views matched by the query to briefly change colors making them visually identifiable.

returns [] if no views are matched

if there are matching views, returns an array of that contains the result of calling the objc selector description on each matching view.

NB: the args argument is ignored and should be deprecated



51
52
53
54
55
# File 'lib/calabash-cucumber/core.rb', line 51

def flash(uiquery, *args)
  # todo deprecate the *args argument in the flash method
  # todo :flash operation should return views as JSON objects
  map(uiquery, :flash, *args).compact
end

#flick(uiquery, delta, options = {}) ⇒ Object



85
86
87
88
89
90
91
92
93
# File 'lib/calabash-cucumber/core.rb', line 85

def flick(uiquery, delta, options={})
  uiquery, options = extract_query_and_options(uiquery, options)
  options[:delta] = delta
  views_touched = launcher.actions.flick(options)
  unless uiquery.nil?
    screenshot_and_raise "flick could not find view: '#{uiquery}', args: #{options}" if views_touched.empty?
  end
  views_touched
end

#launcherObject



483
484
485
486
# File 'lib/calabash-cucumber/core.rb', line 483

def launcher
  # setting the @calabash_launcher here for backward compatibility
  @calabash_launcher = Calabash::Cucumber::Launcher.launcher
end

#location_for_place(place) ⇒ Object



359
360
361
362
363
# File 'lib/calabash-cucumber/core.rb', line 359

def location_for_place(place)
  search_results = locations_for_place(place)
  raise "Got no results for #{place}" if search_results.empty?
  search_results.first
end

#locations_for_place(place) ⇒ Object



365
366
367
# File 'lib/calabash-cucumber/core.rb', line 365

def locations_for_place(place)
  Geocoder.search(place)
end

#macro(txt) ⇒ Object



30
31
32
33
34
35
36
# File 'lib/calabash-cucumber/core.rb', line 30

def macro(txt)
  if self.respond_to? :step
    step(txt)
  else
    Then txt
  end
end

#move_wheel(opts = {}) ⇒ Object



369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/calabash-cucumber/core.rb', line 369

def move_wheel(opts={})
  q = opts[:query] || 'pickerView'
  wheel = opts[:wheel] || 0
  dir = opts[:dir] || :down

  raise 'Wheel index must be non negative' if wheel < 0
  raise "Only up and down supported :dir (#{dir})" unless [:up, :down].include?(dir)

  if ENV['OS'] == 'ios4'
    playback "wheel_#{dir}", :query => "#{q} pickerTable index:#{wheel}"
  elsif ios7?
    raise NotImplementedError
  else
    playback "wheel_#{dir}", :query => "#{q} pickerTableView index:#{wheel}"
  end

end

#pan(from, to, options = {}) ⇒ Object



106
107
108
# File 'lib/calabash-cucumber/core.rb', line 106

def pan(from, to, options={})
  launcher.actions.pan(from, to, options)
end

#picker(opts = {:query => 'pickerView', :action => :texts}) ⇒ Object



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/calabash-cucumber/core.rb', line 387

def picker(opts={:query => 'pickerView', :action => :texts})
  raise 'Not implemented' unless opts[:action] == :texts

  q = opts[:query]

  check_element_exists(q)

  comps = query(q, :numberOfComponents).first
  row_counts = []
  texts = []
  comps.times do |i|
    row_counts[i] = query(q, :numberOfRowsInComponent => i).first
    texts[i] = []
  end

  row_counts.each_with_index do |row_count, comp|
    row_count.times do |i|
      #view = query(q,[{:viewForRow => 0}, {:forComponent => 0}],:accessibilityLabel).first
      spec = [{:viewForRow => i}, {:forComponent => comp}]
      view = query(q, spec).first
      if view
        txt = query(q, spec, :accessibilityLabel).first
      else
        txt = query(q, :delegate, [{:pickerView => :view},
                                   {:titleForRow => i},
                                   {:forComponent => comp}]).first
      end
      texts[comp] << txt
    end
  end
  texts
end

#pinch(in_out, options = {}) ⇒ Object



110
111
112
# File 'lib/calabash-cucumber/core.rb', line 110

def pinch(in_out, options={})
  launcher.actions.pinch(in_out.to_sym,options)
end

#prepare_query_options(uiquery, options) ⇒ Object



503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'lib/calabash-cucumber/core.rb', line 503

def prepare_query_options(uiquery, options)
  opts = options.dup
  if uiquery.is_a?(Array)
    raise 'No elements in array' if uiquery.empty?
    uiquery = uiquery.first
  end #this is deliberately not elsif (uiquery.first could be a hash)

  if uiquery.is_a?(Hash)
    opts[:offset] = point_from(uiquery, options)
    uiquery = nil
  end
  opts[:query] = uiquery
  opts
end

#query(uiquery, *args) ⇒ Object



38
39
40
# File 'lib/calabash-cucumber/core.rb', line 38

def query(uiquery, *args)
  map(uiquery, :query, *args)
end

#query_action_with_options(action, uiquery, options) ⇒ Object



488
489
490
491
492
493
494
495
496
# File 'lib/calabash-cucumber/core.rb', line 488

def query_action_with_options(action, uiquery, options)
  uiquery, options = extract_query_and_options(uiquery, options)
  views_touched = launcher.actions.send(action, options)
  unless uiquery.nil?
    msg = "#{action} could not find view: '#{uiquery}', args: #{options}"
    assert_map_results(views_touched, msg)
  end
  views_touched
end

#query_all(uiquery, *args) ⇒ Object



65
66
67
68
69
70
71
# File 'lib/calabash-cucumber/core.rb', line 65

def query_all(uiquery, *args)
  msg0 = "use the 'all' or 'visible' query language feature"
  msg1 = 'see: https://github.com/calabash/calabash-ios/wiki/05-Query-syntax'
  msg = "#{msg0}\n#{msg1}"
  _deprecated('0.9.133', msg, :warn)
  map("all #{uiquery}", :query, *args)
end

#scroll(uiquery, direction) ⇒ Object



121
122
123
124
125
126
# File 'lib/calabash-cucumber/core.rb', line 121

def scroll(uiquery, direction)
  views_touched=map(uiquery, :scroll, direction)
  msg = "could not find view to scroll: '#{uiquery}', args: #{direction}"
  assert_map_results(views_touched, msg)
  views_touched
end

#scroll_to_cell(options = {:query => 'tableView', :row => 0, :section => 0, :scroll_position => :top, :animate => true}) ⇒ Object

todo for 1.0 version - scroll_to_cell should expose required arguments section and row



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/calabash-cucumber/core.rb', line 136

def scroll_to_cell(options={:query => 'tableView',
                            :row => 0,
                            :section => 0,
                            :scroll_position => :top,
                            :animate => true})
  uiquery = options[:query] || 'tableView'
  row = options[:row]
  sec = options[:section]
  if row.nil? or sec.nil?
    raise 'You must supply both :row and :section keys to scroll_to_cell'
  end

  args = []
  if options.has_key?(:scroll_position)
    args << options[:scroll_position]
  else
    args << 'top'
  end
  if options.has_key?(:animate)
    args << options[:animate]
  end
  views_touched=map(uiquery, :scrollToRow, row.to_i, sec.to_i, *args)
  msg = "unable to scroll: '#{uiquery}' to '#{options}'"
  assert_map_results(views_touched, msg)
  views_touched
end

#scroll_to_collection_view_item(item, section, opts = {}) ⇒ Object

scrolls to item in section in a UICollectionView

calls the :collectionViewScroll server route

item and section are zero-indexed

scroll_to_collection_view_item(0, 2, {:scroll_position => :top}) #=> scroll to item 0 in section 2 to top

scroll_to_collection_view_item(5, 0, => :bottom) #=> scroll to item 5 in section 0 to bottom

allowed options

:query => a query string
    default => 'collectionView'
    example => "collectionView marked:'hit songs'"

:scroll_position => the position to scroll to
    default => :top
    allowed => {:top | :center_vertical | :bottom | :left | :center_horizontal | :right}

:animate => animate the scrolling
    default => true
    allowed => {true | false}

:failed_message => the message to display on failure
    default => nil - will display a default failure message
    allowed => any string

raises an exception if the scroll cannot be performed.

  • the :query finds no collection view

  • collection view does not contain a cell at item/section

  • :scroll_position is invalid



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
# File 'lib/calabash-cucumber/core.rb', line 243

def scroll_to_collection_view_item(item, section, opts={})
  default_options = {:query => 'collectionView',
                     :scroll_position => :top,
                     :animate => true,
                     :failed_message => nil}
  opts = default_options.merge(opts)
  uiquery = opts[:query]

  scroll_position = opts[:scroll_position]
  candidates = [:top, :center_vertical, :bottom, :left, :center_horizontal, :right]
  unless candidates.include?(scroll_position)
    raise "scroll_position '#{scroll_position}' is not one of '#{candidates}'"
  end

  animate = opts[:animate]

  views_touched=map(uiquery, :collectionViewScroll, item.to_i, section.to_i, scroll_position, animate)

  if opts[:failed_message]
    msg = opts[:failed_message]
  else
    msg = "unable to scroll: '#{uiquery}' to item '#{item}' in section '#{section}'"
  end

  assert_map_results(views_touched, msg)
  views_touched
end

#scroll_to_collection_view_item_with_mark(mark, opts = {}) ⇒ Object

scrolls to mark in a UICollectionView

calls the :collectionViewScrollToItemWithMark server route

scroll_to_collection_view_item_with_mark(mark, {:scroll_position => :top}) #=> scroll to the top of the item with the given +mark+

scroll_to_collection_view_item_with_mark(mark, => :bottom) #=> scroll to the bottom of the item with the given mark

allowed options

:query => a query string
    default => 'collectionView'
    example => "collectionView marked:'hit songs'"

:scroll_position => the position to scroll to
    default => :top
    allowed => {:top | :center_vertical | :bottom | :left | :center_horizontal | :right}

:animate => animate the scrolling
    default => true
    allowed => {true | false}

:failed_message => the message to display on failure
    default => nil - will display a default failure message
    allowed => any string

raises an exception if the scroll cannot be performed.

  • the mark is nil

  • the :query finds no collection view

  • collection view does not contain a cell with the given mark

  • :scroll_position is invalid



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/calabash-cucumber/core.rb', line 300

def scroll_to_collection_view_item_with_mark(mark, opts={})
  default_options = {:query => 'collectionView',
                     :scroll_position => :top,
                     :animate => true,
                     :failed_message => nil}
  opts = default_options.merge(opts)
  uiquery = opts[:query]

  if mark.nil?
    raise 'mark argument cannot be nil'
  end

  args = []
  scroll_position = opts[:scroll_position]
  candidates = [:top, :center_vertical, :bottom, :left, :center_horizontal, :right]
  unless candidates.include?(scroll_position)
    raise "scroll_position '#{scroll_position}' is not one of '#{candidates}'"
  end

  args << scroll_position
  args << opts[:animate]

  views_touched=map(uiquery, :collectionViewScrollToItemWithMark, mark, *args)
  msg = opts[:failed_message] || "Unable to scroll: '#{uiquery}' to cell with mark: '#{mark}' with #{opts}"
  assert_map_results(views_touched, msg)
  views_touched
end

#scroll_to_row(uiquery, number) ⇒ Object



128
129
130
131
132
133
# File 'lib/calabash-cucumber/core.rb', line 128

def scroll_to_row(uiquery, number)
  views_touched=map(uiquery, :scrollToRow, number)
  msg = "unable to scroll: '#{uiquery}' to: #{number}"
  assert_map_results(views_touched, msg)
  views_touched
end

#scroll_to_row_with_mark(mark, options = {:query => 'tableView', :scroll_position => :middle, :animate => true}) ⇒ Object

scrolls to mark in a UITableView

calls the :scrollToRowWithMark server route

scroll_to_row_with_mark(mark, {:scroll_position => :top}) #=> scroll to the top of the item with the given +mark+

scroll_to_row_with_mark(mark, => :bottom) #=> scroll to the bottom of the item with the given mark

allowed options

:query => a query string
    default => 'tableView'
    example => "tableView marked:'hit songs'"

:scroll_position => the position to scroll to
    default => :middle
    allowed => {:top | :middle | :bottom}

:animate => animate the scrolling
    default => true
    allowed => {true | false}

raises an exception if the scroll cannot be performed.

  • the mark is nil

  • the :query finds no table view

  • table view does not contain a cell with the given mark

  • :scroll_position is invalid



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/calabash-cucumber/core.rb', line 188

def scroll_to_row_with_mark(mark, options={:query => 'tableView',
                                             :scroll_position => :middle,
                                             :animate => true})
  if mark.nil?
    screenshot_and_raise 'mark argument cannot be nil'
  end

  uiquery = options[:query] || 'tableView'

  args = []
  if options.has_key?(:scroll_position)
    args << options[:scroll_position]
  else
    args << 'middle'
  end
  if options.has_key?(:animate)
    args << options[:animate]
  end

  views_touched=map(uiquery, :scrollToRowWithMark, mark, *args)
  msg = options[:failed_message] || "Unable to scroll: '#{uiquery}' to: #{options}"
  assert_map_results(views_touched, msg)
  views_touched
end

#send_app_to_background(secs) ⇒ Object



328
329
330
# File 'lib/calabash-cucumber/core.rb', line 328

def send_app_to_background(secs)
  launcher.actions.send_app_to_background(secs)
end

#server_debug_levelObject



444
445
446
# File 'lib/calabash-cucumber/core.rb', line 444

def server_debug_level
  _debug_level_response(http(:method => :get, :path => 'debug'))
end

#server_versionObject



57
58
59
# File 'lib/calabash-cucumber/core.rb', line 57

def server_version
  JSON.parse(http(:path => 'version'))
end

#set_location(options) ⇒ Object



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'lib/calabash-cucumber/core.rb', line 332

def set_location(options)
  if uia_available?
    uia_set_location(options)
  else
    if options[:place]
      res = location_for_place(options[:place])
      lat = res.latitude
      lon = res.longitude
    else
      lat = options[:latitude]
      lon = options[:longitude]
    end
    body_data = {:action => :change_location,
                 :latitude => lat,
                 :longitude => lon}

    body = http({:method => :post, :path => 'location'}, body_data)

    res = JSON.parse(body)
    if res['outcome'] != 'SUCCESS'
      screenshot_and_raise "Set location change failed, for #{lat}, #{lon} (#{body})."
    end
    res['results']

  end
end

#set_server_debug_level(level) ⇒ Object



448
449
450
# File 'lib/calabash-cucumber/core.rb', line 448

def set_server_debug_level(level)
  _debug_level_response(http({:method => :post, :path => 'debug'}, {:level => level}))
end

#shutdown_test_serverObject



473
474
475
476
# File 'lib/calabash-cucumber/core.rb', line 473

def shutdown_test_server
  # Compat with Calabash Android
  stop_test_server
end

#start_test_server_in_background(args = {}) ⇒ Object

args :app for device bundle id, for sim path to app



461
462
463
464
465
466
# File 'lib/calabash-cucumber/core.rb', line 461

def start_test_server_in_background(args={})
  stop_test_server
  @calabash_launcher = Calabash::Cucumber::Launcher.new()
  @calabash_launcher.relaunch(args)
  @calabash_launcher
end

#stop_test_serverObject



468
469
470
471
# File 'lib/calabash-cucumber/core.rb', line 468

def stop_test_server
  l = @calabash_launcher || Calabash::Cucumber::Launcher.launcher_if_used
  l.stop if l
end

#swipe(dir, options = {}) ⇒ Object



99
100
101
102
103
104
# File 'lib/calabash-cucumber/core.rb', line 99

def swipe(dir, options={})
  unless uia_available?
    options = options.merge(:status_bar_orientation => status_bar_orientation)
  end
  launcher.actions.swipe(dir.to_sym, options)
end

#touch(uiquery, options = {}) ⇒ Object



73
74
75
# File 'lib/calabash-cucumber/core.rb', line 73

def touch(uiquery, options={})
  query_action_with_options(:touch, uiquery, options)
end

#touch_hold(uiquery, options = {}) ⇒ Object



95
96
97
# File 'lib/calabash-cucumber/core.rb', line 95

def touch_hold(uiquery, options={})
  query_action_with_options(:touch_hold, uiquery, options)
end

#two_finger_tap(uiquery, options = {}) ⇒ Object



81
82
83
# File 'lib/calabash-cucumber/core.rb', line 81

def two_finger_tap(uiquery,options={})
  query_action_with_options(:two_finger_tap, uiquery, options)
end