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:



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

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:



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

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:



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

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



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

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:



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

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:



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

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)`



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

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:



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

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