Module: Calabash::Cucumber::Core

Overview

A collection of methods that provide the core calabash behaviors.

Instance Method Summary collapse

Methods included from PlaybackHelpers

#interpolate, #playback, #record_begin, #record_end

Methods included from Logging

#calabash_info, #calabash_warn

Methods included from RotationHelpers

#recalibrate_after_rotation, #rotate, #rotate_home_button_to

Methods included from StatusBarHelpers

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

Methods included from UIA

#uia, #uia_call, #uia_call_windows, #uia_names, #uia_orientation, #uia_query, #uia_query_windows, #uia_rotate, #uia_rotate_home_button_to, #uia_set_responder_value, #uia_type_string_raw

Methods included from FailureHelpers

#fail, #screenshot, #screenshot_and_raise, #screenshot_embed

Methods included from QueryHelpers

#escape_backslashes, #escape_newlines, #escape_quotes, #escape_string

Methods included from EnvironmentHelpers

#default_device, #device_family_iphone?, #ios5?, #ios6?, #ios7?, #ios8?, #ipad?, #iphone?, #iphone_4in?, #iphone_5?, #iphone_app_emulated_on_ipad?, #ipod?, #simulator?, #uia_available?, #uia_not_available?, #xamarin_test_cloud?

Instance Method Details

#await_page(clz, *args) ⇒ Object

Instantiates a page using ‘page` and calls the page’s ‘await` method.

Examples:

Instantiating and waiting a ‘LoginPage` from a step definition

Given(/^I am about to login to a self-hosted site$/) do
    @current_page = await_page(LoginPage)
    @current_page.self_hosted_site
end

Parameters:

  • clz (Class)

    the page object class to instantiate (passing the cucumber world and ‘args`)

  • args (Array)

    optional additional arguments to pass to the page object constructor

Returns:

  • (Object)

    a fresh instance of ‘Class clz` which has been passed a reference to the cucumber World object. Calls await on the page object.

See Also:



886
887
888
# File 'lib/calabash-cucumber/core.rb', line 886

def await_page(clz,*args)
  clz.new(self,*args).await
end

#backdoor(sel, arg) ⇒ Object

Calls a method on the app’s AppDelegate object.

This is an escape hatch for calling an arbitrary hook inside (the test build) of your app. Commonly used to “go around” the UI for speed purposes or reset the app to a good known state.

You must create a method on you app delegate of the form:

- (NSString *) calabashBackdoor:(NSString *)aIgnorable;

or if you want to pass parameters

- (NSString *) calabashBackdoor:(NSDictionary *)params;

Examples:

backdoor("calabashBackdoor:", '')
backdoor("calabashBackdoor:", {example:'param'})

Parameters:

  • sel (String)

    the selector to perform on the app delegate

  • arg (Object)

    the argument to pass to the selector

Returns:

  • (Object)

    the result of performing the selector with the argument (serialized)



762
763
764
765
766
767
768
769
770
771
772
773
# File 'lib/calabash-cucumber/core.rb', line 762

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_exit(opts = {}) ⇒ Object

TODO:

Shutdown the CalabashServer and close connections.

Attempts to shut the app down gracefully by simulating the transition to closed steps. The server will attempt to ensure that the following UIApplicationDelegate methods methods are called (in order).

“‘

- (void)applicationWillResignActive:(UIApplication *)application
- (void)applicationWillTerminate:(UIApplication *)application

“‘

Parameters:

  • opts (Hash) (defaults to: {})

    Options for controlling the app shutdown process.

Options Hash (opts):

  • :post_resign_active_delay (Float) — default: 0.4

    How long to wait after calling ‘application will resign active’ before calling ‘app will terminate’.

  • :post_will_terminate_delay (Float) — default: 0.4

    How long to wait after calling ‘application will resign active’ before calling ‘exit’.

  • :exit_code (Integer)

    What code should the application exit with? This exit code may or may not be used! If the UIApplication responds to ‘terminateWithSuccess`, then that method will be called. The exit code for `terminateWithSuccess` is undefined.



796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
# File 'lib/calabash-cucumber/core.rb', line 796

def calabash_exit(opts={})
  default_opts = {:post_resign_active_delay => 0.4,
                  :post_will_terminate_delay => 0.4,
                  :exit_code => 0}
  merged_opts = default_opts.merge(opts)
  # 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]
         },  {
               :post_resign_active_delay => merged_opts[:post_resign_active_delay],
               :post_will_terminate_delay => merged_opts[:post_will_terminate_delay],
               :exit_code => merged_opts[:exit_code]
         }
    )
  rescue Errno::ECONNREFUSED, HTTPClient::KeepAliveDisconnected
    []
  end
end

#clear_text(uiquery) ⇒ Object

sets the text value of the views matched by uiquery to '' (the empty string)

using this sparingly and with caution

it is recommended that you instead do some combination of the following

  • use queries and touches to replicate with the user would

    • for text fields, implement a clear text button and touch it

    • for text views, use touches to reveal text editing popup

    see github.com/calabash/calabash-ios/issues/151

https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API

raises an error if the uiquery finds no matching queries or finds a single view that does not respond to the objc selector ‘setText’

IMPORTANT calling:

> clear_text("view")

will clear the text on all visible views that respond to ‘setText’



1010
1011
1012
1013
1014
1015
# File 'lib/calabash-cucumber/core.rb', line 1010

def clear_text(uiquery)
  views_modified = map(uiquery, :setText, '')
  msg = "query '#{uiquery}' returned no matching views that respond to 'setText'"
  assert_map_results(views_modified, msg)
  views_modified
end

#client_versionString

Returns the version of the loaded Calabash library.

Returns:

  • (String)

    the version of the loaded Calabash library.

See Also:



145
146
147
# File 'lib/calabash-cucumber/core.rb', line 145

def client_version
  Calabash::Cucumber::VERSION
end

#console_attach(uia_strategy = nil) ⇒ Calabash::Cucumber::Launcher?

Attach the current calabash launcher to a console.

Examples:

You have encountered a failing cucumber Scenario.
You open the console and want to start investigating the cause of the failure.

Use

> console_attach

to connect to the current launcher

Parameters:

  • uia_strategy (Symbol) (defaults to: nil)

    Optionally specify the uia strategy, which can be one of :shared_element, :preferences, :host. If you don’t know which to choose, don’t specify one and calabash will try deduce the correct strategy to use based on the environment variables used when starting the console.

Returns:



1091
1092
1093
1094
# File 'lib/calabash-cucumber/core.rb', line 1091

def console_attach(uia_strategy = nil)
  # setting the @calabash_launcher here for backward compatibility
  @calabash_launcher = launcher.attach({:uia_strategy => uia_strategy})
end

#double_tap(uiquery, options = {}) ⇒ Array<Hash>

Note:

This assumes the view is visible and not animating.

Performs the “double tap” gesture on the (first) view that matches query ‘uiquery`.

If the view is not visible it will fail with an error. If the view is animating it will silently fail.

By default, taps the center of the view.

Examples:

double_tap "view marked:'Third'", offset:{x:100}

Parameters:

  • uiquery (String)

    query describing view to touch.

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

Returns:

  • (Array<Hash>)

    array containing the serialized version of the tapped view.



233
234
235
# File 'lib/calabash-cucumber/core.rb', line 233

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

#flash(uiquery, *args) ⇒ Array

Causes all views matched by the ‘uiquery` to briefly change colors making them visually identifiable.

Parameters:

  • uiquery (String)

    a query specifying which objects to flash

  • args (Array)

    argument is ignored and should be deprecated

Returns:

  • (Array)

    an array of that contains the result of calling the objc selector ‘description` on each matching view.



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

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 = {}) ⇒ Array<Hash>

Note:

This assumes the view is visible and not animating.

Note:

Due to a bug in the iOS Simulator (or UIAutomation on the simulator) swiping and other ‘advanced’ gestures are not supported in certain scroll views (e.g. UITableView or UIScrollView). It does work when running on physical devices, though, Here is a link to a relevant Stack Overflow post

Performs the “flick” gesture on the (first) view that matches query ‘uiquery`.

If the view is not visible it will fail with an error. If the view is animating it will silently fail.

By default, the gesture starts at the center of the view and “flicks” according to ‘delta`.

A flick is similar to a swipe.

http://stackoverflow.com/questions/18792965/uiautomations-draginsidewithoptions-has-no-effect-on-ios7-simulator
 It is not a bug in Calabash itself but rather in UIAutomation and hence we can't just
 fix it. The work around is typically to use the scroll_to_* functions.

Examples:

flick("MKMapView", {x:100,y:50})

Parameters:

  • uiquery (String)

    query describing view to touch.

  • delta (Hash)

    coordinate describing the direction to flick

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch.

Options Hash (delta):

  • :x (Numeric) — default: 0

    optional. The force and direction of the flick on the ‘x`-axis

  • :y (Numeric) — default: 0

    optional. The force and direction of the flick on the ‘y`-axis

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

Returns:

  • (Array<Hash>)

    array containing the serialized version of the touched view.



288
289
290
291
292
293
294
295
296
# File 'lib/calabash-cucumber/core.rb', line 288

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

#html(q) ⇒ Array<String>

returns the ‘html’ property of all objects matching the query ‘q`

Parameters:

  • q (String)

    the query to execute (should be a webView query)

Returns:

  • (Array<String>)

    array containing html of all elements matching the query



943
944
945
# File 'lib/calabash-cucumber/core.rb', line 943

def html(q)
  query(q).map { |e| e['html'] }
end

#identifier(uiquery) ⇒ Array<String>

Returns all accessibilityIdentifiers of objects matching ‘uiquery`.

Parameters:

  • uiquery (String)

    query to match

Returns:

  • (Array<String>)

    Returns all accessibilityIdentifiers of objects matching ‘uiquery`.



905
906
907
# File 'lib/calabash-cucumber/core.rb', line 905

def identifier(uiquery)
  query(uiquery, :accessibilityIdentifier)
end

#label(uiquery) ⇒ Array<String>

Returns all accessibilityLabels of objects matching ‘uiquery`.

Parameters:

  • uiquery (String)

    query to match

Returns:

  • (Array<String>)

    Returns all accessibilityLabels of objects matching ‘uiquery`.



898
899
900
# File 'lib/calabash-cucumber/core.rb', line 898

def label(uiquery)
  query(uiquery, :accessibilityLabel)
end

#location_for_place(place) ⇒ Geocoder::Result::Google

Returns a geo-location search result (via Google). Requires internet.

Parameters:

  • place (String)

    a description of the place to search for

Returns:

  • (Geocoder::Result::Google)

    result of the search - see /.



678
679
680
681
682
# File 'lib/calabash-cucumber/core.rb', line 678

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

#page(clz, *args) ⇒ Object

Helper method to easily create page object instances from a cucumber execution context. The advantage of using ‘page` to instantiate a page object class is that it will automatically store a reference to the current Cucumber world which is needed in the page object methods to call Cucumber-specific methods like puts or embed.

Examples:

Instantiating a ‘LoginPage` from a step definition

Given(/^I am about to login to a self-hosted site$/) do
    @current_page = page(LoginPage).await(timeout: 30)
    @current_page.self_hosted_site
end

Parameters:

  • clz (Class)

    the page object class to instantiate (passing the cucumber world and ‘args`)

  • args (Array)

    optional additional arguments to pass to the page object constructor

Returns:

  • (Object)

    a fresh instance of ‘Class clz` which has been passed a reference to the cucumber World object.

See Also:



868
869
870
# File 'lib/calabash-cucumber/core.rb', line 868

def page(clz,*args)
  clz.new(self,*args)
end

#pan(from, to, options = {}) ⇒ Array<Hash>

Performs the “pan” or “drag-n-drop” gesture on from the ‘from` parameter to the `to` parameter (both are queries).

Examples:

q1="* marked:'Cell 3' parent tableViewCell descendant tableViewCellReorderControl"
q2="* marked:'Cell 6' parent tableViewCell descendant tableViewCellReorderControl"
pan q1, q2, duration:4

Parameters:

  • from (String)

    query describing view to start the gesture

  • to (String)

    query describing view to end the gesture

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

  • :duration (Numeric) — default: 1

    duration of the ‘pan’.

Returns:

  • (Array<Hash>)

    array containing the serialized version of the touched view.



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

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

#pinch(in_out, options = {}) ⇒ Array<Hash>, String

TODO:

‘pinch` is an old style API which doesn’t take a query as its first argument. We should migrate this.

Performs a “pinch” gesture. By default, the gesture starts at the center of the screen.

Examples:

pinch :out
pinch :in, query:"MKMapView", offset:{x:42}

Parameters:

  • in_out (String)

    the direction to pinch (‘in’ or ‘out’) (symbols can also be used).

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch.

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

  • :query (String) — default: nil

    if specified, the pinch will be made relative to this query.

Returns:

  • (Array<Hash>, String)

    array containing the serialized version of the touched view if ‘options` is given.



377
378
379
# File 'lib/calabash-cucumber/core.rb', line 377

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

#query(uiquery, *args) ⇒ Object

The core method for querying into the current visible view of the app under test. The query method takes as first parameter a String ‘:uiquery`. This string must follow the query syntax described in: / Query Syntax.

Optionally ‘query` takes a variable number of “invocation” arguments (`args` below). # If called with an empty list of `*args`, `query` will find the views specified by `uiquery` and return a serialized view (see Examples below).

If ‘*args` are given, then they should describe a valid selector invocation on the queried views. For example `query(’UILabel’, :text)‘ would perform the `:text` selector on all visible `UILabel` objects and return those as an Array of Strings.

The ‘query` method provide a powerful mechanism for `querying` app view state and can be used to reflectively call arbitrary methods on objects reachable from the view. For a full specification of `*args` see / Query Syntax.

Examples:

Basic view query

irb(main):009:0> query("UITabBarButton index:0")
[
    [0] {
          "class" => "UITabBarButton",
    "id" => nil,
    "rect" => {
        "center_x" => 40,
        "y" => 520,
        "width" => 76,
        "x" => 2,
        "center_y" => 544,
        "height" => 48
   },
    "frame" => {
        "y" => 1,
        "width" => 76,
        "x" => 2,
        "height" => 48
    },
    "label" => "Reader",
    "description" => "<UITabBarButton: 0xdabb510; frame = (2 1; 76 48); opaque = NO; layer = <CALayer: 0xdabd8e0>>"
  }
]

Simple selector

irb(main):010:0> query("UILabel", :text)
[
    [0] "The Ugly Volvo",
    [1] "Why Having a Baby Reminds me of Garfield Minus Garfield",
    [2] "I love the site Garfield Minus Garfield. If you don’t know the site Garfield minus Garfield  it’s a website run by a guy named Dan Walsh who takes Garfield comic strips and digitally erases Garfield from them.   more",
    [3] "Freshly Pressed",
    [4] "Reader",
    [5] "Notifications",
    [6] "Me"
]

Parameters:

  • uiquery (String)

    the query to perform. Must follow the query syntax: / Query Syntax.

  • args (Array)

    optional var-args list describing a chain of method selectors. Full details / Query Syntax.



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

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

#query_all(uiquery, *args) ⇒ Object

Deprecated.

use the ‘all’ or ‘visible’ modifier in query syntax

Queries all views in view hierarchy, even if not visible.



151
152
153
154
155
156
157
# File 'lib/calabash-cucumber/core.rb', line 151

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

Note:

this is implemented by calling the Obj-C ‘setContentOffset:animated:` method and can do things users cant.

Scroll a scroll view in a direction. By default scrolls half the frame size.

Examples:

scroll("UITableView", :down)

Parameters:

  • uiquery (String)

    query describing view scroll (should be UIScrollView or a web view).



396
397
398
399
400
401
# File 'lib/calabash-cucumber/core.rb', line 396

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:

should expose a non-option first argument query and required parameters ‘section`, `row`

Note:

this is implemented by calling the Obj-C ‘scrollToRowAtIndexPath:atScrollPosition:animated:` method and can do things users cant.

Scroll a table view to a section and row. Table view can have multiple sections.

Examples:

scroll_to_cell query:"UITableView", row:4, section:0, animate: false

Parameters:

  • options (Hash) (defaults to: {:query => 'tableView', :row => 0, :section => 0, :scroll_position => :top, :animate => true})

    specifies details of the scroll

Options Hash (options):

  • :query (String) — default: 'tableView'

    query specifying which table view to scroll

  • :section (Fixnum)

    section to scroll to

  • :row (Fixnum)

    row to scroll to

  • :scroll_position (String)

    position to scroll to

  • :animated (Boolean) — default: true

    animate or not

See Also:



434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/calabash-cucumber/core.rb', line 434

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

Note:

item and section are zero-indexed

Scrolls to an item in a section of a UICollectionView.

Examples:

Scroll to item 0 in section 2 to top.

scroll_to_collection_view_item(0, 2, {:scroll_position => :top})

Scroll to item 5 in section 0 to bottom.

scroll_to_collection_view_item(5, 0, {:scroll_position => :bottom})

The following are the allowed :scroll_position values.

{:top | :center_vertical | :bottom | :left | :center_horizontal | :right}

Parameters:

  • item (Integer)

    the index of the item to scroll to

  • section (Integer)

    the section of the item to scroll to

  • opts (Hash) (defaults to: {})

    options for controlling the collection view query and scroll behavior

Options Hash (opts):

  • :query (String) — default: 'collectionView'

    the query that is used to identify which collection view to scroll

  • :scroll_position (Symbol) — default: top

    the position in the collection view to scroll the item to

  • :animate (Boolean) — default: true

    should the scrolling be animated

  • :failed_message (String) — default: nil

    a custom error message to display if the scrolling fails - if not specified, a generic failure will be displayed

Raises:

  • (RuntimeException)

    if the scroll cannot be performed

  • (RuntimeException)

    :query finds no collection view

  • (RuntimeException)

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

  • (RuntimeException)

    :scroll_position is invalid



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
# File 'lib/calabash-cucumber/core.rb', line 545

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.

Examples:

Scroll to the top of the item with the given mark.

scroll_to_collection_view_item_with_mark('cat', {:scroll_position => :top})

Scroll to the bottom of the item with the given mark.

scroll_to_collection_view_item_with_mark('dog', {:scroll_position => :bottom})

The following are the allowed :scroll_position values.

{:top | :center_vertical | :bottom | :left | :center_horizontal | :right}

Parameters:

  • mark (String)

    an accessibility ‘| identifier` or text in or on the item

  • opts (Hash) (defaults to: {})

    options for controlling the collection view query and scroll behavior

Options Hash (opts):

  • :query (String) — default: 'collectionView'

    the query that is used to identify which collection view to scroll

  • :scroll_position (Symbol) — default: :top

    the position in the collection view to scroll the item to

  • :animate (Boolean) — default: true

    should the scroll be animated

  • :failed_message (String) — default: nil

    a custom error message to display if the scrolling fails - if not specified, a generic failure will be displayed

Raises:

  • (RuntimeException)

    if the scroll cannot be performed

  • (RuntimeException)

    if the mark is nil

  • (RuntimeException)

    :query finds no collection view

  • (RuntimeException)

    the collection view does not contain a cell with the mark

  • (RuntimeException)

    :scroll_position is invalid



605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
# File 'lib/calabash-cucumber/core.rb', line 605

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

Note:

this is implemented by calling the Obj-C ‘scrollToRowAtIndexPath:atScrollPosition:animated:` method and can do things users cant.

Scroll a table view to a row. Table view should have only one section.

Examples:

scroll_to_row "UITableView", 2

Parameters:

  • uiquery (String)

    query describing view scroll (should be UIScrollView or a web view).

See Also:



411
412
413
414
415
416
# File 'lib/calabash-cucumber/core.rb', line 411

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 a mark in a UITableView.

Examples:

Scroll to the top of the item with the given mark.

scroll_to_row_with_mark('settings', {:scroll_position => :top})

Scroll to the bottom of the item with the given mark.

scroll_to_row_with_mark('about', {:scroll_position => :bottom})

Parameters:

  • mark (String)

    an accessibility ‘| identifier` or text in or on the row

  • options (Hash) (defaults to: {:query => 'tableView', :scroll_position => :middle, :animate => true})

    controls the query and and scroll behavior

Options Hash (options):

  • :query (String) — default: 'tableView'

    the query that should be used to location the table

  • :scroll_position (Symbol) — default: :middle

    the table position to scroll the row to - allowed values ‘| :top | :bottom`

  • :animate (Boolean) — default: true

    should the scrolling be animated

Raises:

  • (RuntimeError)

    if the scroll cannot be performed

  • (RuntimeError)

    if the mark is nil

  • (RuntimeError)

    if the table query finds no table view

  • (RuntimeError)

    if the scroll position is invalid



485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/calabash-cucumber/core.rb', line 485

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

Sends app to background. Simulates pressing the home button.

Parameters:

  • secs (Fixnum)

    number of seconds to be in the background ‘should not be more than 60 secs`



636
637
638
# File 'lib/calabash-cucumber/core.rb', line 636

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

#server_log_levelString

Get the Calabash server log level.

Returns:

  • (String)

    the current log level



822
823
824
# File 'lib/calabash-cucumber/core.rb', line 822

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

#server_versionString

Returns the version of the running calabash server.

Returns:

  • (String)

    version of the running calabash server.



138
139
140
# File 'lib/calabash-cucumber/core.rb', line 138

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

#set_location(options) ⇒ Object

Note:

Seems UIAutomation is broken here on physical devices on iOS 7.1

Simulates gps location of the device/simulator.

Examples:

set_location place:'Tower of London'

Parameters:

  • options (Hash)

    specifies which location to simulate

Options Hash (options):

  • :place (String)

    a description of a place (resolved via Google maps api), e.g. “Tower of London”

  • :latitude (Numeric)

    latitude of a gps coordinate (same coordinate system as Google maps)

  • :longitude (Numeric)

    longitude of a gps coordinate (same coordinate system as Google maps)



648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'lib/calabash-cucumber/core.rb', line 648

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_log_level(level) ⇒ Object

Set the Calabash server log level.

Parameters:

  • level (String)

    the log level to set (debug, info, warn, error)



828
829
830
# File 'lib/calabash-cucumber/core.rb', line 828

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

#set_text(uiquery, txt) ⇒ Object

Deprecated.

since 0.9.145

sets the text value of the views matched by uiquery to txt

we have stopped testing this method. you have been warned.

  • to enter text using the native keyboard use ‘keyboard_enter_text’

  • to delete text use ‘keyboard_enter_text(’Delete’)“

  • to clear a text field or text view:

    • RECOMMENDED: use queries and touches to replicate what the user would do

    • use ‘clear_text’

https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API

raises an error if the uiquery finds no matching queries or finds a view that does not respond to the objc selector ‘setText’



965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
# File 'lib/calabash-cucumber/core.rb', line 965

def set_text(uiquery, txt)
  msgs = ["'set_text' is deprecated and its behavior is now unpredictable",
          "* to enter text using the native keyboard use 'keyboard_enter_text'",
          "* to delete text use 'keyboard_enter_text('Delete')",
          '* to clear a text field or text view:',
          '  - RECOMMENDED: use queries and touches to replicate what the user would do',
          '    * for text fields, implement a clear text button and touch it',
          '    * for text views, use touches to reveal text editing popup',
          '    see https://github.com/calabash/calabash-ios/issues/151',
          "  - use 'clear_text'",
          'https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API']
  msg = msgs.join("\n")
  _deprecated('0.9.145', msg, :warn)

  text_fields_modified = map(uiquery, :setText, txt)

  msg = "query '#{uiquery}' returned no matching views that respond to 'setText'"
  assert_map_results(text_fields_modified, msg)
  text_fields_modified
end

#set_user_pref(key, val) ⇒ Object

Sets user preference (NSUserDefaults) value of key ‘key` to `val`.

Examples:

set_user_pref 'foo', {lastname: "Krukow"}
# returns
[
    {
    "lastname" => "Krukow"
    },
   {
    "firstname" => "Karl"
   }
]

Parameters:

  • key (String)

    the set to set

  • val (Object)

    the (JSON_ serializable) value to set

Returns:

  • (Object)

    the current user preferences



1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
# File 'lib/calabash-cucumber/core.rb', line 1034

def set_user_pref(key, val)
  res = http({:method => :post, :path => 'userprefs'},
             {:key=> key, :value => val})
  res = JSON.parse(res)
  if res['outcome'] != 'SUCCESS'
    screenshot_and_raise "set_user_pref #{key} = #{val} failed because: #{res['reason']}\n#{res['details']}"
  end

  res['results']
end

#start_test_server_in_background(args = {}) ⇒ Calabash::Cucumber::Launcher

Note:

It is not recommended to call this method outside of the calabash console. Call ‘Calabash::Cucumber::Launcher#relaunch instead.

Starts the app and Calabash test server in the console.

Returns:

See Also:



846
847
848
849
850
851
# File 'lib/calabash-cucumber/core.rb', line 846

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

#swipe(dir, options = {}) ⇒ Array<Hash>, String

TODO:

‘swipe` is an old style API which doesn’t take a query as its first argument. We should migrate this.

Note:

Due to a bug in Apple’s UIAutomation, swipe is broken on certain views in the iOS Simulator. Swiping works on devices. https://github.com/calabash/calabash-ios/issues/253

Performs a “swipe” gesture. By default, the gesture starts at the center of the screen.

Examples:

swipe :left
swipe :down, offset:{x:10,y:50}, query:"MKMapView"

Parameters:

  • dir (String)

    the direction to swipe (symbols can also be used).

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch.

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

  • :query (String) — default: nil

    if specified, the swipe will be made relative to this query.

Returns:

  • (Array<Hash>, String)

    array containing the serialized version of the touched view if ‘options` is given.



340
341
342
343
344
345
# File 'lib/calabash-cucumber/core.rb', line 340

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

#tap(hash_or_string, *args) ⇒ Array<Hash>

Deprecated.

In later Calabash versions we will change the semantics of ‘tap` to take a general query (instead of a ’mark’ now). We’re deprecating this now to prepare people for a breaking change.

taps a view with mark ‘hash_or_string`

Parameters:

  • hash_or_string (String)

    mark to pass to call ‘tap_mark(hash_or_string)`.

Returns:

  • (Array<Hash>)

    array containing the serialized version of the tapped view.



920
921
922
923
924
925
926
927
928
929
930
# File 'lib/calabash-cucumber/core.rb', line 920

def tap(hash_or_string, *args)
  deprecation_msg = 'Use tap_mark instead. In later Calabash versions we will change the semantics of `tap` to take a general query.'
  _deprecated('0.10.0', deprecation_msg, :warn)
  if hash_or_string.is_a?(String)
    tap_mark(hash_or_string, *args)
  elsif hash_or_string.respond_to?(:[])
    wait_tap(hash_or_string[:query], hash_or_string)
  else
    raise(ArgumentError, "first parameter to tap must be a string or a hash. Was: #{hash_or_string.class}, #{hash_or_string}")
  end
end

#tap_mark(label, *args) ⇒ Array<Hash>

taps a view with mark ‘label`. Equivalent to `touch(“* marked:’##label‘”)`

Parameters:

  • label (String)

    the mark of the view to tap

  • args (Array)

    optional additional arguments to pass to ‘touch`.

Returns:

  • (Array<Hash>)

    array containing the serialized version of the tapped view.



936
937
938
# File 'lib/calabash-cucumber/core.rb', line 936

def tap_mark(label, *args)
  touch("view marked:'#{label}'", *args)
end

#tap_point(x, y) ⇒ Boolean

Performs the ‘tap` gesture on an absolute coordinate.

Parameters:

  • x (Numeric)

    x-coordinate to tap

  • y (Numeric)

    y-coordinate to tap

Returns:

  • (Boolean)

    ‘true`

See Also:



187
188
189
# File 'lib/calabash-cucumber/core.rb', line 187

def tap_point(x,y)
  touch(nil, offset: {x:x, y:y})
end

#touch(uiquery, options = {}) ⇒ Array<Hash>

Performs the ‘tap` gesture on the (first) view that matches query `uiquery`. Note that `touch` assumes the view is visible and not animating. If the view is not visible `touch` will fail. If the view is animating `touch` will silently fail. By default, taps the center of the view.

Parameters:

  • uiquery (String)

    query describing view to tap. Note ‘nil` is allowed and is interpreted as `tap_point(options[:x],options[:y])`

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

Returns:

  • (Array<Hash>)

    array containing the serialized version of the tapped view.

See Also:



173
174
175
176
177
178
# File 'lib/calabash-cucumber/core.rb', line 173

def touch(uiquery, options={})
  if uiquery.nil? && options[:offset].nil?
    raise "called touch(nil) without specifying an offset in options (#{options})"
  end
  query_action_with_options(:touch, uiquery, options)
end

#touch_hold(uiquery, options = {}) ⇒ Array<Hash>

Note:

This assumes the view is visible and not animating.

Performs the “long press” or “touch and hold” gesture on the (first) view that matches query ‘uiquery`.

If the view is not visible it will fail with an error. If the view is animating it will silently fail.

By default, the gesture starts at the center of the view.

Examples:

touch_hold "webView css:'input'", duration:10, offset:{x: -40}

Parameters:

  • uiquery (String)

    query describing view to touch.

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch.

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

  • :duration (Numeric) — default: 3

    duration of the ‘hold’.

Returns:

  • (Array<Hash>)

    array containing the serialized version of the touched view.



316
317
318
# File 'lib/calabash-cucumber/core.rb', line 316

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

#two_finger_tap(uiquery, options = {}) ⇒ Array<Hash>

Note:

This assumes the view is visible and not animating.

Performs the “two-finger tap” gesture on the (first) view that matches query ‘uiquery`.

If the view is not visible it will fail with an error. If the view is animating it will silently fail.

By default, taps the center of the view.

Examples:

two_finger_tap "view marked:'Third'", offset:{x:100}

Parameters:

  • uiquery (String)

    query describing view to touch.

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch.

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to touch point. Offset supports an ‘:x` and `:y` key and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset, offset)`).

Returns:

  • (Array<Hash>)

    array containing the serialized version of the tapped view.



254
255
256
# File 'lib/calabash-cucumber/core.rb', line 254

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

#user_pref(key) ⇒ Object

Gets the user preference (NSUserDefaults) value for a key.

Parameters:

  • key (String)

    the read

Returns:

  • (Object)

    the current user preferences value for ‘key`



1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
# File 'lib/calabash-cucumber/core.rb', line 1048

def user_pref(key)
  res = http({:method => :get, :raw => true, :path => 'userprefs'},
             {:key=> key})
  res = JSON.parse(res)
  if res['outcome'] != 'SUCCESS'
    screenshot_and_raise "get user_pref #{key} failed because: #{res['reason']}\n#{res['details']}"
  end

  res['results'].first
end

#wait_tap(uiquery, options = {}) ⇒ Array<Hash>

Performs the ‘tap` gesture on the (first) view that matches query `uiquery`.

As opposed to ‘touch`, `wait_tap` is a high-level method that combines:

  1. waiting for the view to appear,

  2. waiting for animations to complete on the view (and it’s parents) and

  3. actually tapping the view.

This removes the common boiler-plate trio: ‘wait_for_element_exists`, `wait_for_none_animating`, `touch`.

By default, taps the center of the view.

Parameters:

  • uiquery (String)

    query describing view to tap. Note ‘nil` is not allowed.

  • options (Hash) (defaults to: {})

    option for modifying the details of the touch

Options Hash (options):

  • :offset (Hash) — default: nil

    optional offset to tap point. Offset has an ‘:x` and `:y` key the tap will be performed on the center of the view plus the offset.

  • :timeout (Hash) — default: 30

    maximum number of seconds to wait for the view to appear

  • :frequency (Hash) — default: 0.2

    polling frequency to for checking if the view is present (>= 0.1)

Returns:

  • (Array<Hash>)

    serialized version of the tapped view

See Also:



212
213
214
215
216
# File 'lib/calabash-cucumber/core.rb', line 212

def wait_tap(uiquery, options={})
  # noinspection RubyUnusedLocalVariable
  _uiquery, options = extract_query_and_options(uiquery, options)
  launcher.actions.wait_tap(options)
end