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 collapse

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?, #ios11?, #ios5?, #ios6?, #ios7?, #ios8?, #ios9?, #ios_gte_11?, #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_error(msg) ⇒ WaitError, Object

if msg is a String, a new WaitError is returned. Otherwise msg itself is returned.

Parameters:

  • msg (String, Object)

    a message to raise

Returns:

  • (WaitError)

    if msg is a String, returns a new WaitError

  • (Object)

    if msg is anything else, returns msg



476
477
478
# File 'lib/calabash-cucumber/wait_helpers.rb', line 476

def wait_error(msg)
  (msg.is_a?(String) ? WaitError.new(msg) : msg)
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