Module: Accessibility::DSL

Defined in:
lib/accessibility/dsl.rb

Overview

DSL methods for AXElements.

The DSL for AXElements is designed to pull actions out from an object and put them in front of object to make communicating test steps seem more like human instructions.

You can read more about the DSL in the Acting section of the AXElements wiki.

Actions collapse

Polling collapse

Mouse Manipulation collapse

Debug Helpers collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object

We assume that any method that has the first argument with a type of AX::Element is intended to be an action and so #method_missing will forward the message to the element.

Parameters:

  • meth (String)

    an action constant

Raises:

  • (NoMethodError)

37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/accessibility/dsl.rb', line 37

def method_missing meth, *args
  arg = args.first
  if arg.kind_of? AX::Element
    return arg.perform meth if arg.actions.include? meth
    raise ArgumentError, "`#{meth}' is not an action of #{self}:#{self.class}"
  end
  # @todo do we still need this? we should just call super
  # should be able to just call super, but there is a bug in MacRuby (#1320)
  # so we just recreate what should be happening
  message = "undefined method `#{meth}' for #{self}:#{self.class}"
  raise NoMethodError, message, caller(1)
end

Instance Method Details

#app_with_bundle_identifier(id) ⇒ AX::Application? Also known as: app_with_bundle_id, launch

Find the application with the given bundle identifier. If the application is not already running, it will be launched.

Examples:


app_with_bundle_identifier 'com.apple.finder'
launch                     'com.apple.mail'

Parameters:

Returns:


883
884
885
# File 'lib/accessibility/dsl.rb', line 883

def app_with_bundle_identifier id
  AX::Application.new id
end

#app_with_name(name) ⇒ AX::Application?

Find the application with the given name. If the application is not already running, it will NOT be launched and this method will return nil.

Examples:


app_with_name 'Finder'

Parameters:

Returns:


900
901
902
# File 'lib/accessibility/dsl.rb', line 900

def app_with_name name
  AX::Application.new name
end

#app_with_pid(pid) ⇒ AX::Application

Find the application with the given process identifier. An invalid PID will cause an exception to be raised.

Examples:


app_with_pid 35843

Parameters:

  • pid (Fixnum)

Returns:


914
915
916
# File 'lib/accessibility/dsl.rb', line 914

def app_with_pid pid
  AX::Application.new pid
end

#cancel(element) ⇒ Boolean

Try to perform the cancel action on the given element.

Parameters:

Returns:

  • (Boolean)

118
119
120
# File 'lib/accessibility/dsl.rb', line 118

def cancel element
  element.perform :cancel
end

#click(obj = nil, wait = 0.2) { ... } ⇒ Object

Perform a regular click.

If a parameter is provided then the mouse will move to that point first; the argument must respond to #to_point.

If a block is given, it will be yielded to between the click down and click up event.

Examples:


click
click window.close_button
click do
  move_mouse_to [0,0]
end

Parameters:

  • obj (#to_point) (defaults to: nil)

Yields:

  • Optionally take a block that is executed between click down and click up events.


599
600
601
602
603
604
605
606
# File 'lib/accessibility/dsl.rb', line 599

def click obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.click_down
  yield if block_given?
ensure
  Mouse.click_up
  sleep wait
end

#confirm(element) ⇒ Boolean

Try to perform the confirm action on the given element.

Parameters:

Returns:

  • (Boolean)

91
92
93
# File 'lib/accessibility/dsl.rb', line 91

def confirm element
  element.perform :confirm
end

#contextual_menuAX::Menu?

Note:

This is a hack to workaround an AXAPI deficiency

Note:

This method may move or be renamed in the next release, though it will not be removed

Find a contextual menu that is open near the mouses current position

This method assumes that it is being called in the block of a call to #right_click, and that the contextual menu is going to be very close to the mouse pointer.

Returns:


327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/accessibility/dsl.rb', line 327

def contextual_menu
  # CAST, just like high school trigonometry! :P
  c, a, s, t = quads = Array.new(4) { Mouse.current_position }
  c.x -= 10; c.y += 10
  a.x += 10; a.y += 10
  s.x += 10; s.y -= 10
  t.x -= 10; t.y -= 10
  elements = quads.map { |quad| element_at_point quad }
  elements.uniq!
  elements.map! { |el| el.kind_of?(AX::Menu) ? el : el.ancestor(:menu) }
  elements.find { |element| element.present? }
end

#decrement(element) ⇒ Boolean

Try to perform the decrement action on the given element.

Parameters:

Returns:

  • (Boolean)

82
83
84
# File 'lib/accessibility/dsl.rb', line 82

def decrement element
  element.perform :decrement
end

#delete(element) ⇒ Boolean

Try to perform the delete action on the given element.

Parameters:

Returns:

  • (Boolean)

109
110
111
# File 'lib/accessibility/dsl.rb', line 109

def delete element
  element.perform :delete
end

#double_click(obj = nil, wait = 0.2) ⇒ Object

Perform a double click action.

If an argument is provided then the mouse will move to that point first; the argument must respond to #to_point.

Parameters:

  • obj (#to_point) (defaults to: nil)

638
639
640
641
642
# File 'lib/accessibility/dsl.rb', line 638

def double_click obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.double_click
  sleep wait
end

#drag_mouse_to(arg, opts = {}) ⇒ Object

Click and drag the mouse from its current position to the given position.

There are many reasons why you would want to cause a drag event with the mouse. Perhaps you want to drag an object to another place, or maybe you want to select a group of objects on the screen.

Examples:


drag_mouse_to [100,100]
drag_mouse_to drop_zone, from: desktop_icon

Parameters:

  • arg (#to_point)
  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :from (#to_point)

    a point to move to before dragging

  • :duration (Number) — default: 0.2

    in seconds

  • :wait (Number) — default: 0.2

    in seconds


533
534
535
536
537
# File 'lib/accessibility/dsl.rb', line 533

def drag_mouse_to arg, opts = {}
  move_mouse_to opts[:from] if opts[:from]
  Mouse.drag_to arg.to_point, (opts[:duration] || 0.2)
  sleep(opts[:wait] || 0.2)
end

#element_at_point(point, opts = {}) ⇒ AX::Element Also known as: element_at

Get the top most object at an arbitrary point on the screen for the given application. The given point can be a CGPoint, an Array, or anything else that responds to #to_point.

Optionally, you can look for the top-most element for a specific application by passing an AX::Application object using the for: key.

Examples:


element_at [100, 456]
element_at CGPoint.new(33, 45), for: safari

element_at window # find out what is in the middle of the window

Parameters:

  • point (#to_point)
  • opts (Hash) (defaults to: {})

Options Hash (opts):

Returns:


956
957
958
959
# File 'lib/accessibility/dsl.rb', line 956

def element_at_point point, opts = {}
  base = opts[:for] || system_wide
  base.element_at point
end

#element_under_mouseAX::Element

Return the top most element at the current mouse position.

See #element_at_point for more details.

Returns:


932
933
934
# File 'lib/accessibility/dsl.rb', line 932

def element_under_mouse
  element_at_point Mouse.current_position
end

#graph(element) ⇒ String Also known as: graph_for

Note:

This method is currently experimental

Note:

You will need to have GraphViz command line tools installed in order for this to work.

Make and open a dot format graph of the tree, meant for graphing with GraphViz.

Examples:


graph app.main_window

Parameters:

Returns:

  • (String)

    path to the saved image


795
796
797
798
799
800
801
# File 'lib/accessibility/dsl.rb', line 795

def graph element
  require 'accessibility/graph'
  graph = Accessibility::Graph.new(element)
  path  = graph.generate_png!
  `open #{path}`
  path
end

#hide(app) ⇒ Boolean

Tell an app to hide itself.

Parameters:

Returns:

  • (Boolean)

144
145
146
# File 'lib/accessibility/dsl.rb', line 144

def hide app
  app.perform :hide
end

#highlight(obj, opts = {}) ⇒ Accessibility::Highlighter

Highlight an element on screen. You can optionally specify the highlight colour or pass a timeout to automatically have the highlighter disappear.

The highlighter is actually a window, so if you do not set a timeout, you will need to call #stop or #close on the returned highlighter object in order to get rid of the highlighter.

You could use this method to highlight an arbitrary number of elements on screen, with a rainbow of colours. Great for debugging.

Examples:


highlighter = highlight window.outline
# wait a few seconds...
highlighter.stop

# highlighter automatically turns off after 5 seconds
highlight window.outline.row, colour: NSColor.greenColor, timeout: 5

Parameters:

  • obj (#bounds)
  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :timeout (Number)
  • :colour (NSColor) — default: NSColor.magentaColor

Returns:

  • (Accessibility::Highlighter)

777
778
779
# File 'lib/accessibility/dsl.rb', line 777

def highlight obj, opts = {}
  Accessibility::Highlighter.new obj.bounds, opts
end

#horizontal_scroll(lines, obj = nil, wait = 0.1) ⇒ Object

TODO:

Need to expose the units option? Would allow scrolling by pixel.

Horizontally scrolls an arbitrary number of lines at the mouses current point on the screen

Use a positive number to scroll left, and a negative number to scroll right.

If the second argument is provided then the mouse will move to that point first; the argument must respond to #to_point.

Parameters:

  • lines (Number)
  • obj (#to_point) (defaults to: nil)
  • wait (Number) (defaults to: 0.1)

573
574
575
576
577
# File 'lib/accessibility/dsl.rb', line 573

def horizontal_scroll lines, obj = nil, wait = 0.1
  move_mouse_to obj, wait: 0 if obj
  Mouse.horizontal_scroll lines
  sleep wait
end

#increment(element) ⇒ Boolean

Try to perform the increment action on the given element.

Parameters:

Returns:

  • (Boolean)

100
101
102
# File 'lib/accessibility/dsl.rb', line 100

def increment element
  element.perform :increment
end

#move_mouse_to(arg, opts = {}) ⇒ Object

Move the mouse cursor to the given point or object on the screen.

Examples:


move_mouse_to button
move_mouse_to [344, 516]
move_mouse_to CGPoint.new(100, 100)

Parameters:

  • arg (#to_point)
  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :duration (Number) — default: 0.2

    in seconds

  • :wait (Number) — default: 0.2

    in seconds


506
507
508
509
510
511
512
513
# File 'lib/accessibility/dsl.rb', line 506

def move_mouse_to arg, opts = {}
  duration = opts[:duration] || 0.2
  if Accessibility.debug? && arg.kind_of?(AX::Element)
    highlight arg, timeout: duration, color: NSColor.orangeColor
  end
  Mouse.move_to arg.to_point, duration
  sleep(opts[:wait] || 0.2)
end

#pick(element) ⇒ Boolean

Try to perform the pick action on the given element.

Parameters:

Returns:

  • (Boolean)

73
74
75
# File 'lib/accessibility/dsl.rb', line 73

def pick element
  element.perform :pick
end

#pinch(direction, magnification = 1, obj = nil, wait = 0.2) ⇒ Object

Perform a pinch gesture in the given direction

You can optionally specify the magnification factor and position for the pinch event. * Available pinch directions are:

  • :zoom or :expand
  • :unzoom or :contract

Magnification is a relative magnification setting. A zoom value of 1.0 means 1.0 more than the current zoom level. 2.0 would be 2.0 levels higher than the current zoom.

You can also optionally specify an object/point on screen for the mouse pointer to be moved to before the gesture begins.

Parameters:

  • direction (Symbol)
  • magnification (Float) (defaults to: 1)
  • obj (#to_point) (defaults to: nil)

703
704
705
706
707
# File 'lib/accessibility/dsl.rb', line 703

def pinch direction, magnification = 1, obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.pinch direction, magnification
  sleep wait
end

#press(element) ⇒ Boolean

Try to perform the press action on the given element.

Parameters:

Returns:

  • (Boolean)

55
56
57
# File 'lib/accessibility/dsl.rb', line 55

def press element
  element.perform :press
end

#raise(element) ⇒ Boolean #raise(exception[, message[, backtrace]]) ⇒ Object

Note:

This method overrides Kernel#raise so we have to check the class of the first argument to decide which code path to take.

Try to perform the raise action on the given element.

Overloads:

  • #raise(element) ⇒ Boolean

    Parameters:

    Returns:

    • (Boolean)
  • #raise(exception[, message[, backtrace]]) ⇒ Object

    The normal way to raise an exception.


134
135
136
137
# File 'lib/accessibility/dsl.rb', line 134

def raise *args
  arg = args.first
  arg.kind_of?(AX::Element) ? arg.perform(:raise) : Kernel.raise(*args)
end

#record(file = nil) {|recorder| ... } ⇒ String

See (ScreenRecorder)[http://rdoc.info/gems/screen_recorder/frames] for details on the screen recording options

Examples:


file = record do
  run_tests
end
`open '#{file}'`

Parameters:

  • file (String) (defaults to: nil)

Yields:

Yield Parameters:

  • recorder (ScreenRecorder)

Returns:


860
861
862
863
864
865
866
867
# File 'lib/accessibility/dsl.rb', line 860

def record file = nil, &block
  require 'screen_recorder'
  if file
    ScreenRecorder.record file, &block
  else
    ScreenRecorder.record &block
  end
end

#right_click(obj = nil, wait = 0.2) { ... } ⇒ Object Also known as: secondary_click

Perform a right (a.k.a. secondary) click action.

If an argument is provided then the mouse will move to that point first; the argument must respond to #to_point.

If a block is given, it will be yielded to between the click down and click up event. This behaviour is the same as passing a block to #click.

Parameters:

  • obj (#to_point) (defaults to: nil)

Yields:

  • Optionally take a block that is executed between click down and click up events.


621
622
623
624
625
626
627
628
# File 'lib/accessibility/dsl.rb', line 621

def right_click obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.right_click_down
  yield if block_given?
ensure
  Mouse.right_click_up
  sleep wait
end

#rotate(direction, angle, obj = nil, wait = 0.2) ⇒ Object

Perform a rotation gesture in the given direction the given angle degrees

Possible directions are:

  • :cw, ':clockwise, ':clock_wise to rotate in the clockwise direction
  • :ccw, ':counter_clockwise,:counter_clock_wise` to rotate in the the counter clockwise direction

The angle parameter is a number of degrees to rotate. There are 360 degrees in a full rotation, as you would expect in Euclidian geometry.

You can also optionally specify an object/point on screen for the mouse pointer to be moved to before the gesture begins. The movement will be instantaneous.

Parameters:

  • direction (Symbol)
  • angle (Float)
  • obj (#to_point) (defaults to: nil)

729
730
731
732
733
# File 'lib/accessibility/dsl.rb', line 729

def rotate direction, angle, obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.rotate direction, angle
  sleep wait
end

#screenshot(name = "AXElements-ScreenShot", dir = '~/Desktop') ⇒ String Also known as: capture_screen

Take a screen shot and save it to disk. If a file name and path are not given then default values will be used; given paths will be expanded automatically.A timestamp and file extension will always automatically be appended to the file name.

Examples:


screenshot
  # => "~/Desktop/AXElements-ScreenShot-20120422184650.png"

screenshot app.title
  # => "~/Desktop/Safari-20120422184650.png"

screenshot app.title, "/Volumes/SecretStash"
  # => "/Volumes/SecretStash/Safari-20120422184650.png"

Parameters:

  • name (#to_s) (defaults to: "AXElements-ScreenShot")
  • dir (#to_s) (defaults to: '~/Desktop')

Returns:

  • (String)

    path to the screenshot


824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
# File 'lib/accessibility/dsl.rb', line 824

def screenshot name = "AXElements-ScreenShot", dir = '~/Desktop'
  # @todo this could move to its own class, much like
  #       {Accessibility::Highlighter} and expose more options
  #       while retaining good defaults
  dir  = File.expand_path dir.to_s
  file = "#{dir}/#{name}-#{Time.now.strftime '%Y%m%d%H%M%S'}.png"

  cg_image = CGWindowListCreateImage(CGRectInfinite,
                                     KCGWindowListOptionOnScreenOnly,
                                     KCGNullWindowID,
                                     KCGWindowImageDefault)
  NSBitmapImageRep
    .alloc
    .initWithCGImage(cg_image)
    .representationUsingType(NSPNGFileType, properties: nil)
    .writeToFile(file, atomically: false)

  file
end

#scroll(lines, obj = nil, wait = 0.1) ⇒ Object

TODO:

Need to expose the units option? Would allow scrolling by pixel.

Scrolls an arbitrary number of lines at the mouses current point on the screen. Use a positive number to scroll down, and a negative number to scroll up.

If the second argument is provided then the mouse will move to that point first; the argument must respond to #to_point.

Parameters:

  • lines (Number)
  • obj (#to_point) (defaults to: nil)
  • wait (Number) (defaults to: 0.1)

552
553
554
555
556
# File 'lib/accessibility/dsl.rb', line 552

def scroll lines, obj = nil, wait = 0.1
  move_mouse_to obj, wait: 0 if obj
  Mouse.scroll lines
  sleep wait
end

#scroll_menu_to(element)

This method returns an undefined value.

Scroll a menu to an item in the menu and then move the mouse pointer to that item.

Examples:


click window.pop_up do
  scroll_menu_to pop_up.menu.item(title: "Expensive Cake")
end

Parameters:


311
312
313
# File 'lib/accessibility/dsl.rb', line 311

def scroll_menu_to element
  element.ancestor(:menu).scroll_to element
end

#scroll_to(element) Also known as: scroll_to_visible

This method returns an undefined value.

Scroll through a scroll area until the given element is visible.

If you need to scroll an unknown amount of units through a table or another type of object contained in as scroll area, you can just pass the element that you are trying to get to and this method will scroll to it for you.

Examples:


scroll_to table.rows.last

Parameters:


294
295
296
# File 'lib/accessibility/dsl.rb', line 294

def scroll_to element
  element.ancestor(:scroll_area).scroll_to element
end

#select_menu_item(app, *path) ⇒ Boolean

Navigate the menu bar menus for the given application and select the last item in the chain.

Examples:


mail = app_with_name 'Mail'
select_menu_item mail, 'View', 'Sort By', 'Subject'
select_menu_item mail, 'Edit', /Spelling/, /show spelling/i

Parameters:

Returns:

  • (Boolean)

253
254
255
# File 'lib/accessibility/dsl.rb', line 253

def select_menu_item app, *path
  app.application.select_menu_item *path
end

#set(element, attribute_name: new_value) ⇒ Object #set(element, new_value) ⇒ Object

Set the value of an attribute on an element.

This method will try to set focus to the element first; this is to compensate for cases where app developers assumed an element would have to have focus before a user could change the value.

Examples:


set text_field, selected_text_range: 1..10

set text_field,   'Mark Rada'
set radio_button, 1

Overloads:

  • #set(element, attribute_name: new_value) ⇒ Object

    Set a specified attribute to a new value

    Parameters:

    • element (AX::Element)
    • change (Hash{attribute_name=>new_value})
  • #set(element, new_value) ⇒ Object

    Set the value attribute to a new value

    Parameters:


204
205
206
207
208
209
210
211
212
# File 'lib/accessibility/dsl.rb', line 204

def set element, change
  set_focus_to element

  if change.kind_of? Hash
    element.set *change.first
  else
    element.set :value, change
  end
end

#set_focus_to(element) ⇒ Object Also known as: set_focus

Focus an element on the screen, but only if it can be directly focused. It is safe to pass any element into this method as nothing will happen if it does not have a writable focused state attribute.

Parameters:


173
174
175
# File 'lib/accessibility/dsl.rb', line 173

def set_focus_to element
  element.set(:focused, true) if element.writable? :focused
end

#show_about_window_for(app) ⇒ AX::Window

Show the "About" window for an app. Returns the window that is opened.

Parameters:

Returns:

  • (AX::Window)

263
264
265
# File 'lib/accessibility/dsl.rb', line 263

def show_about_window_for app
  app.show_about_window
end

#show_menu(element) ⇒ Boolean

Try to perform the show_menu action on the given element.

Parameters:

Returns:

  • (Boolean)

64
65
66
# File 'lib/accessibility/dsl.rb', line 64

def show_menu element
  element.perform :show_menu
end

#show_preferences_window_for(app) ⇒ AX::Window

Note:

This method assumes that the app has setup the standard CMD+, hotkey to open the pref window

Try to open the preferences for an app. Returns the window that is opened.

Parameters:

Returns:

  • (AX::Window)

276
277
278
# File 'lib/accessibility/dsl.rb', line 276

def show_preferences_window_for app
  app.application.show_preferences_window
end

#smart_magnify(obj = nil, wait = 0.2) ⇒ Object

Perform a smart magnify (double tap on trackpad)

You can optionally specify an object/point on the screen where to perform the smart magnification. The mouse will move to this point first

Parameters:

  • obj (#to_point) (defaults to: nil)

742
743
744
745
746
# File 'lib/accessibility/dsl.rb', line 742

def smart_magnify obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.smart_magnify
  sleep wait
end

#swipe(direction, obj = nil, wait = 0.2) ⇒ Object

Perform a swipe gesture in the given direction

Valid directions are:

  • :up
  • :down
  • :left
  • :right

An optional second argument can be provided. If the argument is provided then the mouse pointer will move to that point first.

Examples:


swipe :left, safari.web_area

Parameters:

  • direction (Symbol)
  • obj (#to_point) (defaults to: nil)

676
677
678
679
680
# File 'lib/accessibility/dsl.rb', line 676

def swipe direction, obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.swipe direction
  sleep wait
end

#system_wideAX::SystemWide

Synonym for AX::SystemWide.new.

Returns:


922
923
924
# File 'lib/accessibility/dsl.rb', line 922

def system_wide
  AX::SystemWide.new
end

#terminate(app) ⇒ Boolean

Tell an app to quit.

Parameters:

Returns:

  • (Boolean)

163
164
165
# File 'lib/accessibility/dsl.rb', line 163

def terminate app
  app.perform :terminate
end

#triple_click(obj = nil, wait = 0.2) ⇒ Object

Perform a triple click action

If an argument is provided then the mouse will move to that point first; the argument must respond to #to_point.

Parameters:

  • obj (#to_point) (defaults to: nil)

651
652
653
654
655
# File 'lib/accessibility/dsl.rb', line 651

def triple_click obj = nil, wait = 0.2
  move_mouse_to obj, wait: 0 if obj
  Mouse.triple_click
  sleep wait
end

#type(string) ⇒ Object #type(string, app) ⇒ Object Also known as: type_string

Simulate keyboard input by typing out the given string. To learn more about how to encode modifier keys (e.g. Command), see the dedicated documentation page on Keyboard Events wiki page.

Examples:


type "Hello, world!"

Overloads:

  • #type(string) ⇒ Object

    Send input to the currently focused application

    Parameters:

  • #type(string, app) ⇒ Object

    Send input to a specific application

    Parameters:


234
235
236
237
# File 'lib/accessibility/dsl.rb', line 234

def type string, app = system_wide
  sleep 0.1
  app.type string.to_s
end

#unhide(app) ⇒ Boolean Also known as: show

Tell an app to unhide itself.

Parameters:

Returns:

  • (Boolean)

153
154
155
# File 'lib/accessibility/dsl.rb', line 153

def unhide app
  app.perform :unhide
end

#wait_for(element, filters = {}) { ... } ⇒ AX::Element?

Simply wait around for something to show up. This method is similar to performing an explicit search on an element except that the search filters take two extra options which can control the timeout period and the search subtree. You MUST supply either the parent or ancestor option to specify where to search from. Searching from the parent implies that what you are waiting for is a child of the parent and not a more distant descendant.

This is an alternative to using the notifications system. It is far easier to use than notifications in most cases, but it will perform more slowly (and without all the fun crashes).

Examples:


# Waiting for a dialog window to show up
wait_for :dialog, parent: app

# Waiting for a hypothetical email from Mark Rada to appear
wait_for :static_text, value: 'Mark Rada', ancestor: mail.main_window

# Waiting for something that will never show up
wait_for :a_million_dollars, ancestor: fruit_basket, timeout: 1000000

Parameters:

  • element (#to_s)
  • filters (Hash) (defaults to: {})

Options Hash (filters):

Yields:

  • Optional block used as a search filter

Returns:


374
375
376
377
378
379
380
381
382
# File 'lib/accessibility/dsl.rb', line 374

def wait_for element, filters = {}, &block
  if filters.has_key? :ancestor
    wait_for_descendant element, filters.delete(:ancestor), filters, &block
  elsif filters.has_key? :parent
    wait_for_child element, filters.delete(:parent), filters, &block
  else
    raise ArgumentError, 'parent/ancestor filter required'
  end
end

#wait_for_child(child, parent, filters, &block) ⇒ AX::Element?

Note:

This is really just an optimized case of #wait_for_descendant when you know what you are waiting for is a child of a particular element. Use #wait_for_descendant if you are unsure of the relationship.

Wait around for particular element and then return that element. The parent argument must be the parent of the element you are waiting for, this method will not look further down the hierarchy. The options you pass to this method can be any search filter that you can normally use.

See #wait_for for more details.

Parameters:

Returns:


425
426
427
428
429
430
431
432
433
434
435
# File 'lib/accessibility/dsl.rb', line 425

def wait_for_child child, parent, filters, &block
  timeout = filters.delete(:timeout) || 5
  start   = Time.now
  q       = Accessibility::Qualifier.new(child, filters, &block)
  until Time.now - start > timeout
    result = parent.children.find { |x| q.qualifies? x }
    return result unless result.blank?
    sleep 0.1
  end
  nil
end

#wait_for_descendant(descendant, ancestor, filters, &block) ⇒ AX::Element? Also known as: wait_for_descendent

Wait around for particular element and then return that element. The options you pass to this method can be any search filter that you can normally use.

See #wait_for for more details.

Parameters:

  • descendant (#to_s)
  • ancestor (AX::Element)
  • filters (Hash)

Returns:


395
396
397
398
399
400
401
402
403
404
# File 'lib/accessibility/dsl.rb', line 395

def wait_for_descendant descendant, ancestor, filters, &block
  timeout = filters.delete(:timeout) || 5
  start   = Time.now
  until Time.now - start > timeout
    result = ancestor.search(descendant, filters, &block)
    return result unless result.blank?
    sleep 0.1
  end
  nil
end

#wait_for_invalidation_of(element) ⇒ Boolean #wait_for_invalidation_of(kind, filters = {}, &block) ⇒ Boolean Also known as: wait_for_invalidation, wait_for_invalid

Simply wait for an element to disappear. Optionally wait for the element to appear first.

Like #wait_for, you can pass any search filters that you normally would, including blocks. However, this method also supports the ability to pass an AX::Element and simply wait for it to become invalid.

An example usage would be typing into a search field and then waiting for the busy indicator to disappear and indicate that all search results have been returned.

Examples:


wait_for_invalidation_of table.row(static_text: { value: 'Cake' })

wait_for_invalidation_of :row, parent: table, static_text: { value: 'Cake' }

Parameters:

  • element (AX::Element)
  • filters (Hash) (defaults to: {})
  • element (#to_s)
  • filters (Hash) (defaults to: {})

Options Hash (filters):

  • :timeout (Number) — default: 5

    in seconds

  • :timeout (Number) — default: 5

    in seconds

Returns:

  • (Boolean)
  • (Boolean)
  • (Boolean)

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# File 'lib/accessibility/dsl.rb', line 471

def wait_for_invalidation_of element, filters = {}, &block
  timeout = filters[:timeout] || 5
  start   = Time.now

  unless element.kind_of? AX::Element
    element = wait_for element, filters, &block
    # this is a tricky situation,
    return true unless element
  end

  until Time.now - start > timeout
    return true if element.invalid?
    sleep 0.1
  end
  false
end