Module: Calabash::Cucumber::WaitHelpers

Includes:
Core, TestsHelpers
Included in:
Operations
Defined in:
lib/calabash-cucumber/wait_helpers.rb

Overview

A collection of methods that help you wait for things.

Defined Under Namespace

Classes: WaitError

Constant Summary

CALABASH_CONDITIONS =

Currently two conditions that can be waited for using wait_for_condition: :none_animating no UIKit object is animating and :no_network_indicator status bar network indicator not showing.

{:none_animating => 'NONE_ANIMATING',
:no_network_indicator => 'NO_NETWORK_INDICATOR'}
DEFAULT_OPTS =

The default options used in the “wait*” methods

{
      # default upper limit on how long to wait
      :timeout => 30,
      # default polling frequency for waiting
      :retry_frequency => 0.3,
      # default extra wait after the condition becomes true
      :post_timeout => 0,
      # default message if timeout occurs
      :timeout_message => 'Timed out waiting...',
      # Calabash will generate a screenshot by default if waiting times out
      :screenshot_on_error => true
}

Instance Method Summary collapse

Methods included from TestsHelpers

#check_element_does_not_exist, #check_element_exists, #check_view_with_mark_exists, #classes, #each_cell, #element_does_not_exist, #element_exists, #view_with_mark_exists

Methods included from FailureHelpers

#fail, #screenshot, #screenshot_and_raise, #screenshot_embed

Methods included from Core

#await_page, #backdoor, #calabash_exit, #calabash_info, #calabash_warn, #clear_text, #client_version, #console_attach, #deprecated, #device_agent, #dismiss_ipad_keyboard, #double_tap, #flash, #flick, #html, #identifier, #keyboard_enter_char, #keyboard_enter_text, #label, #location_for_place, #page, #pan, #pan_coordinates, #pinch, #query, #rotate, #rotate_home_button_to, #scroll, #scroll_to_cell, #scroll_to_collection_view_item, #scroll_to_collection_view_item_with_mark, #scroll_to_mark, #scroll_to_row, #scroll_to_row_with_mark, #send_app_to_background, #server_log_level, #server_version, #set_location, #set_server_log_level, #set_text, #set_user_pref, #shake, #slider_set_value, #start_test_server_in_background, #swipe, #tap_keyboard_action_key, #tap_keyboard_delete_key, #tap_mark, #tap_point, #touch, #touch_hold, #two_finger_tap, #user_pref

Methods included from KeyboardHelpers

#docked_keyboard_visible?, #keyboard_visible?, #lookup_key_name, #split_keyboard_visible?, #undocked_keyboard_visible?, #wait_for_keyboard, #wait_for_no_keyboard

Methods included from StatusBarHelpers

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

Methods included from UIA

#uia, #uia_call, #uia_call_windows, #uia_keyboard_visible?, #uia_names, #uia_orientation, #uia_query, #uia_query_windows, #uia_rotate, #uia_rotate_home_button_to, #uia_set_responder_value, #uia_wait_for_keyboard

Methods included from QueryHelpers

#escape_backslashes, #escape_newlines, #escape_quotes, #escape_string

Methods included from EnvironmentHelpers

#default_device, #device_family_iphone?, #ios10?, #ios5?, #ios6?, #ios7?, #ios8?, #ios9?, #ios_version, #ipad?, #ipad_pro?, #iphone?, #iphone_35in?, #iphone_4in?, #iphone_6?, #iphone_6_plus?, #iphone_app_emulated_on_ipad?, #ipod?, #screen_dimensions, #simulator?, #uia_available?, #uia_not_available?, #xamarin_test_cloud?

Instance Method Details

#touch_transition(touch_q, done_queries, check_options = {}, animation_options = {}) ⇒ Object

Combines touching an element and wait_for_transition

Parameters:

  • touch_q (String)

    the Calabash query to touch

  • done_queries (Array)

    passed to wait_for_transition

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

    ({}) passed to wait_for_transition

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

    ({}) passed to wait_for_transition

See Also:



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

def touch_transition(touch_q, done_queries,check_options={},animation_options={})
  touch(touch_q)
  wait_for_transition(done_queries,check_options,animation_options)
end

#until_element_does_not_exist(uiquery, opts = {}) ⇒ Object

Performs a lambda action until the element (a query string) disappears. The default action is to do nothing.

Raises an error if no uiquery is specified.

Examples:

until_element_does_not_exist("button", :action => lambda { swipe("up") })

Parameters:

  • uiquery (String)

    the Calabash query to wait for disappearing.

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

See Also:



401
402
403
404
405
406
407
408
# File 'lib/calabash-cucumber/wait_helpers.rb', line 401

def until_element_does_not_exist(uiquery, opts = {})
  condition = lambda {element_does_not_exist(uiquery)}
  extra_opts = { :until => condition, :action => lambda {} }
  opts = DEFAULT_OPTS.merge(extra_opts).merge(opts)
  wait_poll(opts) do
    opts[:action].call
  end
end

#until_element_exists(uiquery, opts = {}) ⇒ Object

Performs a lambda action until the element (a query string) appears. The default action is to do nothing. Similar to wait_poll.

Raises an error if no uiquery is specified.

Examples:

until_element_exists("button", :action => lambda { swipe("up") })

Parameters:

  • uiquery (String)

    the Calabash query to wait for

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

See Also:



382
383
384
385
386
387
388
# File 'lib/calabash-cucumber/wait_helpers.rb', line 382

def until_element_exists(uiquery, opts = {})
  extra_opts = { :until_exists => uiquery, :action => lambda {} }
  opts = DEFAULT_OPTS.merge(extra_opts).merge(opts)
  wait_poll(opts) do
    opts[:action].call
  end
end

#wait_for(options_or_timeout = DEFAULT_OPTS, &block) ⇒ nil

Waits for a condition to be true. The condition is specified by a given block that is called repeatedly. If the block returns a 'trueish' value the condition is considered true and wait_for immediately returns. There is a :timeout option that specifies a maximum number of seconds to wait. If the given block doesn't return a 'trueish' value before the :timeout seconds has elapsed, the waiting fails and raises a WaitError error.

The options hash controls the details of waiting (see options_or_timeout below). DEFAULT_OPTS specifies the default waiting options.

wait_for is a low-level building-block for waiting and often there are higher-level waiting methods what use wait_for in their implementation (e.g. wait_for_element_exists).

Examples:

Waiting for an element (see also wait_for_element_exists)

wait_for(timeout: 60,
         timeout_message: "Could not find 'Sign in' button") do
  element_exists("button marked:'Sign in'")
end

Parameters:

  • options_or_timeout (Hash) (defaults to: DEFAULT_OPTS)

    options for controlling the details of the wait. Note for backwards compatibility with old Calabash versions can also be a number which is then interpreted as a timeout.

Options Hash (options_or_timeout):

  • :timeout (Numeric) — default: 30

    upper limit on how long to wait (in seconds)

  • :retry_frequency (Numeric) — default: 0.3

    how often to poll (i.e., call the given block)

  • :post_timeout (Numeric) — default: 0

    if positive, an extra wait is made after the condition is satisfied

  • :timeout_message (String)

    the error message to use if condition is not satisfied in time

  • :screenshot_on_error (Boolean)

    generate a screenshot on error

Returns:

  • (nil)

    when the condition is satisfied

Raises:

See Also:



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/calabash-cucumber/wait_helpers.rb', line 115

def wait_for(options_or_timeout=DEFAULT_OPTS, &block)
  #note Hash is preferred, number acceptable for backwards compat
  default_timeout = 30
  timeout = options_or_timeout || default_timeout
  post_timeout=0
  retry_frequency=0.3
  timeout_message = nil
  screenshot_on_error = true

  if options_or_timeout.is_a?(Hash)
    timeout = options_or_timeout[:timeout] || default_timeout
    retry_frequency = options_or_timeout[:retry_frequency] || retry_frequency
    post_timeout = options_or_timeout[:post_timeout] || post_timeout
    timeout_message = options_or_timeout[:timeout_message]
    if options_or_timeout.key?(:screenshot_on_error)
      screenshot_on_error = options_or_timeout[:screenshot_on_error]
    end
  end

  begin
    Timeout::timeout(timeout, WaitError) do
      sleep(retry_frequency) until yield
    end
    sleep(post_timeout) if post_timeout > 0
  rescue WaitError => e
    msg = timeout_message || e
    if screenshot_on_error
      sleep(retry_frequency)
      return screenshot_and_retry(msg, &block)
    else
      raise wait_error(msg)
    end
  rescue => e
    handle_error_with_options(e, nil, screenshot_on_error)
  end
end

#wait_for_element_does_not_exist(element_query, options = {}) ⇒ nil Also known as: wait_for_element_does_not_exists

Waits for a Calabash query to return an empty result (typically a UI element to disappear). Uses wait_for.

Parameters:

  • element_query (String)

    a Calabash query to be empty (i.e. element_does_not_exist(element_query))

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

Returns:

  • (nil)

    when the condition is satisfied

Raises:

See Also:



247
248
249
250
# File 'lib/calabash-cucumber/wait_helpers.rb', line 247

def wait_for_element_does_not_exist(element_query, options={})
  options[:timeout_message] = options[:timeout_message] || "Timeout waiting for element to not exist: #{element_query}"
  wait_for(options) { element_does_not_exist(element_query) }
end

#wait_for_element_exists(element_query, options = {}) ⇒ nil

Waits for a Calabash query to return a non-empty result (typically a UI element to be visible). Uses wait_for.

Examples:

Waiting for an element to be visible

wait_for_element_exists("button marked:'foo'", timeout: 60)

Parameters:

  • element_query (String)

    a Calabash query to wait for (i.e. element_exists(element_query))

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

Returns:

  • (nil)

    when the condition is satisfied

Raises:

See Also:



210
211
212
213
# File 'lib/calabash-cucumber/wait_helpers.rb', line 210

def wait_for_element_exists(element_query, options={})
  options[:timeout_message] = options[:timeout_message] || "Timeout waiting for element: #{element_query}"
  wait_for(options) { element_exists(element_query) }
end

#wait_for_elements_do_not_exist(elements_arr, options = {}) ⇒ nil

Waits for one or more Calabash queries to all return empty results (typically a UI elements to disappear). Uses wait_for.

Parameters:

  • elements_arr (Array<String>)

    an Array of Calabash queries to be empty (i.e. element_does_not_exist(element_query))

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

Returns:

  • (nil)

    when the condition is satisfied

Raises:

See Also:



265
266
267
268
269
270
271
272
273
# File 'lib/calabash-cucumber/wait_helpers.rb', line 265

def wait_for_elements_do_not_exist(elements_arr, options={})
  if elements_arr.is_a?(String)
    elements_arr = [elements_arr]
  end
  options[:timeout_message] = options[:timeout_message] || "Timeout waiting for no elements matching: #{elements_arr.join(",")}"
  wait_for(options) do
    elements_arr.none? { |q| element_exists(q) }
  end
end

#wait_for_elements_exist(elements_arr, options = {}) ⇒ nil

Waits for one or more Calabash queries to all return non-empty results (typically a UI elements to be visible). Uses wait_for.

Parameters:

  • elements_arr (Array<String>)

    an Array of Calabash queries to wait for (i.e. element_exists(element_query))

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

Returns:

  • (nil)

    when the condition is satisfied

Raises:

See Also:



226
227
228
229
230
231
232
233
234
# File 'lib/calabash-cucumber/wait_helpers.rb', line 226

def wait_for_elements_exist(elements_arr, options={})
  if elements_arr.is_a?(String)
    elements_arr = [elements_arr]
  end
  options[:timeout_message] = options[:timeout_message] || "Timeout waiting for elements: #{elements_arr.join(',')}"
  wait_for(options) do
    elements_arr.all? { |q| element_exists(q) }
  end
end

#wait_for_no_network_indicator(options = {}) ⇒ nil

Waits for the status-bar network indicator to stop animating (network activity done).

Parameters:

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

    options for controlling the details of the wait.

Options Hash (options):

  • :timeout (Numeric) — default: 30

    maximum time to wait

Returns:

  • (nil)

    when the condition is satisfied

Raises:



344
345
346
347
# File 'lib/calabash-cucumber/wait_helpers.rb', line 344

def wait_for_no_network_indicator(options = {})
  options[:condition] = CALABASH_CONDITIONS[:no_network_indicator]
  wait_for_condition(options)
end

#wait_for_none_animating(options = {}) ⇒ nil

Waits for all elements to stop animating (EXPERIMENTAL).

Parameters:

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

    options for controlling the details of the wait.

Options Hash (options):

  • :timeout (Numeric) — default: 30

    maximum time to wait

Returns:

  • (nil)

    when the condition is satisfied

Raises:



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

def wait_for_none_animating(options = {})
  options[:condition] = CALABASH_CONDITIONS[:none_animating]
  wait_for_condition(options)
end

#wait_for_transition(done_queries, check_options = {}, animation_options = {}) ⇒ Object

Combines waiting for elements and waiting for animations.

Parameters:

  • done_queries (Array)

    Calabash queries to wait for (one or more).

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

    ({}) options used for wait_for_elements_exists(done_queries, check_options)

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

    ({}) options used for wait_for_none_animating(animation_options)



353
354
355
356
357
# File 'lib/calabash-cucumber/wait_helpers.rb', line 353

def wait_for_transition(done_queries, check_options={},animation_options={})
  done_queries = [*done_queries]
  wait_for_elements_exist(done_queries,check_options)
  wait_for_none_animating(animation_options)
end

#wait_poll(opts, &block) ⇒ nil

Repeatedly runs an action (for side-effects) until a condition is satisfied. Similar to wait_for but specifies both a condition to wait for and an action to repeatedly perform to make the condition true (e.g. scrolling). The return value of the action is ignored.

The block represents the action and options :until or :until_exists specify the condition to wait for. Same options as wait_for can be provided.

Examples:

Scrolling until we find an element

wait_poll(timeout: 10,
          timeout_message: 'Unable to find "Example"',
          until_exists: "* marked:'Example'") do
  scroll("tableView", :down)
end

Win the battle

wait_poll(timeout: 60,
          timeout_message: 'Defeat!',
          until: lambda { enemy_defeated? }) do
  launch_the_missiles!
end

Parameters:

  • opts (Hash)

    options for controlling the details of the wait in addition to the options specified below, all options in DEFAULT_OPTS also apply and can be overridden.

Options Hash (opts):

  • :until (Proc)

    if specified this lambda/Proc becomes the condition to wait for.

  • :until_exists (String)

    if specified, a calabash query to wait for. Exactly one of :until and :until_exists must be specified

Returns:

  • (nil)

    when the condition is satisfied

Raises:

See Also:



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/calabash-cucumber/wait_helpers.rb', line 181

def wait_poll(opts, &block)
  test = opts[:until]
  if test.nil?
    cond = opts[:until_exists]
    raise 'Must provide :until or :until_exists' unless cond
    test = lambda { element_exists(cond) }
  end
  wait_for(opts) do
    if test.call()
      true
    else
      yield
      false
    end
  end
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 replaces the common pattern:

wait_for_none_animating
wait_for_element_exists("* marked:'log in'")
touch("* marked:'log in'")

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:



77
78
79
80
81
# File 'lib/calabash-cucumber/wait_helpers.rb', line 77

def wait_tap(uiquery, options={})
  wait_for_none_animating
  wait_for_element_exists(uiquery, options)
  touch(uiquery, options)
end

#when_element_exists(uiquery, opts = {}) ⇒ Object

Performs a lambda action once the element exists. The default behavior is to touch the specified element.

Raises an error if no uiquery is specified.

Examples:

when_element_exists("button", :timeout => 10)

Parameters:

  • uiquery (String)

    the Calabash query to wait for.

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

    options for controlling the details of the wait. The same options as DEFAULT_OPTS apply.

See Also:



421
422
423
424
425
# File 'lib/calabash-cucumber/wait_helpers.rb', line 421

def when_element_exists(uiquery, opts = {})
  action = opts[:action] || lambda { touch(uiquery) }
  wait_for_element_exists(uiquery, opts)
  action.call
end