AXElements 0.7.8 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. data/.yardopts +1 -10
  2. data/README.markdown +7 -14
  3. data/ext/accessibility/key_coder/key_coder.c +7 -0
  4. data/lib/AXElements.rb +0 -2
  5. data/lib/accessibility/core.rb +180 -123
  6. data/lib/accessibility/dsl.rb +310 -191
  7. data/lib/accessibility/enumerators.rb +9 -8
  8. data/lib/accessibility/errors.rb +7 -8
  9. data/lib/accessibility/factory.rb +16 -9
  10. data/lib/accessibility/graph.rb +68 -22
  11. data/lib/accessibility/highlighter.rb +86 -0
  12. data/lib/accessibility/pp_inspector.rb +4 -4
  13. data/lib/accessibility/qualifier.rb +11 -9
  14. data/lib/accessibility/string.rb +12 -4
  15. data/lib/accessibility/translator.rb +19 -10
  16. data/lib/accessibility/version.rb +3 -1
  17. data/lib/accessibility.rb +42 -17
  18. data/lib/ax/application.rb +90 -30
  19. data/lib/ax/button.rb +5 -2
  20. data/lib/ax/element.rb +133 -149
  21. data/lib/ax/pop_up_button.rb +12 -0
  22. data/lib/ax/radio_button.rb +5 -2
  23. data/lib/ax/row.rb +2 -2
  24. data/lib/ax/static_text.rb +5 -2
  25. data/lib/ax/systemwide.rb +24 -12
  26. data/lib/ax_elements/awesome_print.rb +13 -0
  27. data/lib/ax_elements/exception_workaround.rb +5 -0
  28. data/lib/ax_elements/nsarray_compat.rb +1 -0
  29. data/lib/ax_elements.rb +2 -1
  30. data/lib/minitest/ax_elements.rb +60 -4
  31. data/lib/mouse.rb +47 -20
  32. data/lib/rspec/expectations/ax_elements.rb +180 -88
  33. data/rakelib/doc.rake +7 -0
  34. data/test/helper.rb +2 -1
  35. data/test/integration/accessibility/test_dsl.rb +126 -18
  36. data/test/integration/accessibility/test_errors.rb +1 -1
  37. data/test/integration/ax/test_element.rb +17 -0
  38. data/test/integration/minitest/test_ax_elements.rb +33 -38
  39. data/test/integration/rspec/expectations/test_ax_elements.rb +68 -19
  40. data/test/sanity/accessibility/test_core.rb +45 -37
  41. data/test/sanity/accessibility/test_highlighter.rb +56 -0
  42. data/test/sanity/ax/test_application.rb +8 -0
  43. data/test/sanity/ax/test_element.rb +7 -3
  44. data/test/sanity/minitest/test_ax_elements.rb +2 -0
  45. data/test/sanity/rspec/expectations/test_ax_elements.rb +3 -0
  46. data/test/sanity/test_accessibility.rb +9 -0
  47. data/test/sanity/test_mouse.rb +2 -2
  48. metadata +11 -38
  49. data/docs/AccessibilityTips.markdown +0 -119
  50. data/docs/Acting.markdown +0 -340
  51. data/docs/Debugging.markdown +0 -165
  52. data/docs/Inspecting.markdown +0 -261
  53. data/docs/KeyboardEvents.markdown +0 -122
  54. data/docs/NewBehaviour.markdown +0 -151
  55. data/docs/Notifications.markdown +0 -271
  56. data/docs/Searching.markdown +0 -250
  57. data/docs/TestingExtensions.markdown +0 -52
  58. data/docs/images/all_the_buttons.jpg +0 -0
  59. data/docs/images/next_version.png +0 -0
  60. data/docs/images/ui_hierarchy.dot +0 -34
  61. data/docs/images/ui_hierarchy.png +0 -0
  62. data/lib/accessibility/debug.rb +0 -164
  63. data/test/integration/accessibility/test_debug.rb +0 -44
  64. data/test/sanity/accessibility/test_debug.rb +0 -63
data/lib/ax/element.rb CHANGED
@@ -1,18 +1,22 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require 'ax_elements/vendor/inflector'
3
+ require 'accessibility/core'
4
+ require 'accessibility/factory'
5
+ require 'accessibility/translator'
4
6
  require 'accessibility/enumerators'
5
7
  require 'accessibility/qualifier'
6
8
  require 'accessibility/errors'
7
9
  require 'accessibility/pp_inspector'
8
- require 'accessibility/factory'
9
- require 'accessibility/core'
10
10
 
11
11
  ##
12
12
  # @abstract
13
13
  #
14
- # The abstract base class for all accessibility objects. This class
15
- # provides generic functionality that all accessibility objects require.
14
+ # The abstract base class for all accessibility objects. `AX::Element`
15
+ # composes low level `AXUIElementRef` objects into a more Rubyish
16
+ # interface.
17
+ #
18
+ # This abstract base class provides generic functionality that all
19
+ # accessibility objects require.
16
20
  class AX::Element
17
21
  include Accessibility::PPInspector
18
22
  include Accessibility::Factory
@@ -39,10 +43,11 @@ class AX::Element
39
43
  end
40
44
 
41
45
  ##
42
- # @todo Consider returning `nil` if the element does not have
43
- # the given attribute.
44
- #
45
- # Get the value of an attribute.
46
+ # Get the value of an attribute. This method will return `nil` if
47
+ # the attribute does not have a value, if the element does not have
48
+ # the attribute, or if the element is dead. There is an execption
49
+ # for the `:children` attribute which is always guaranteed to return
50
+ # an array.
46
51
  #
47
52
  # @example
48
53
  #
@@ -54,9 +59,12 @@ class AX::Element
54
59
  end
55
60
 
56
61
  ##
57
- # Needed to override inherited `NSObject#description` as some
58
- # elements have a `description` attribute. If you want a description
59
- # of the object then you should use {#inspect} instead.
62
+ # Get the accessibility description for the element.
63
+ #
64
+ # This overrides the inherited `NSObject#description`. If you want a
65
+ # description of the object then you should use {#inspect} instead.
66
+ #
67
+ # @return [String]
60
68
  def description
61
69
  attribute :description
62
70
  end
@@ -71,20 +79,24 @@ class AX::Element
71
79
  end
72
80
 
73
81
  ##
74
- # Return the `#size` of an attribute. This only works for attributes
75
- # that are a collection. This exists because it is _much_ more
76
- # efficient to find out how many `children` exist using this API
77
- # instead of getting the children array and asking for the size.
82
+ # Get a list of elements, starting with the receiver and riding
83
+ # the hierarchy up to the top level object (i.e. the {AX::Application}).
78
84
  #
79
85
  # @example
80
86
  #
81
- # table.size_of :rows # => 111
82
- # window.size_of :children # => 16
87
+ # element = AX::DOCK.list.application_dock_item
88
+ # element.ancestry
89
+ # # => [#<AX::ApplicationDockItem...>, #<AX::List...>, #<AX::Application...>]
83
90
  #
84
- # @param [#to_sym]
85
- # @return [Number]
86
- def size_of attr
87
- @ref.size_of TRANSLATOR.cocoaify attr
91
+ # @return [Array<AX::Element>]
92
+ def ancestry *elements
93
+ elements = [self] if elements.empty?
94
+ element = elements.last
95
+ if element.attributes.include? :parent
96
+ ancestry(elements << element.parent)
97
+ else
98
+ elements
99
+ end
88
100
  end
89
101
 
90
102
  ##
@@ -100,6 +112,23 @@ class AX::Element
100
112
  @ref.pid
101
113
  end
102
114
 
115
+ ##
116
+ # Return the `#size` of an attribute. This only works for attributes
117
+ # that are a collection. This exists because it is _much_ more
118
+ # efficient to find out how many `children` exist using this API
119
+ # instead of getting the children array and asking for the size.
120
+ #
121
+ # @example
122
+ #
123
+ # table.size_of :rows # => 111
124
+ # window.size_of :children # => 16
125
+ #
126
+ # @param [#to_sym]
127
+ # @return [Number]
128
+ def size_of attr
129
+ @ref.size_of TRANSLATOR.cocoaify attr
130
+ end
131
+
103
132
  ##
104
133
  # Check whether or not an attribute is writable.
105
134
  #
@@ -125,7 +154,7 @@ class AX::Element
125
154
  # @return the value that you were setting is returned
126
155
  def set attr, value
127
156
  unless writable? attr
128
- raise NoMethodError, "#{attr} is read-only for #{inspect}"
157
+ raise ArgumentError, "#{attr} is read-only for #{inspect}"
129
158
  end
130
159
  value = value.relative_to(@ref.value.size) if value.kind_of? Range
131
160
  @ref.set TRANSLATOR.cocoaify(attr), value
@@ -153,14 +182,12 @@ class AX::Element
153
182
  #
154
183
  # @example
155
184
  #
156
- # text_field.attribute :string_for_range, for_param: (2..8).relative_to(10)
185
+ # text_field.parameterized_attribute :string_for_range, 2..8
157
186
  #
158
187
  # @param [#to_sym]
159
- def attribute attr, for_parameter: param
160
- if rattr = TRANSLATOR.cocoaify(attr)
161
- param = param.relative_to(@ref.value.size) if value.kind_of? Range
162
- process @ref.attribute(rattr, for_parameter: param)
163
- end
188
+ def parameterized_attribute attr, param
189
+ param = param.relative_to(@ref.value.size) if value.kind_of? Range
190
+ process @ref.parameterized_attribute(TRANSLATOR.cocoaify(attr), param)
164
191
  end
165
192
 
166
193
 
@@ -196,11 +223,7 @@ class AX::Element
196
223
  # @param [#to_sym]
197
224
  # @return [Boolean] true if successful
198
225
  def perform action
199
- if raction = TRANSLATOR.cocoaify(action)
200
- @ref.perform raction
201
- else
202
- false
203
- end
226
+ @ref.perform TRANSLATOR.cocoaify action
204
227
  end
205
228
 
206
229
 
@@ -208,14 +231,15 @@ class AX::Element
208
231
 
209
232
  ##
210
233
  # Perform a breadth first search through the view hierarchy rooted at
211
- # the current element.
234
+ # the current element. If you are concerned about the return value of
235
+ # this method, you can call {#blank?} on the return object.
212
236
  #
213
- # See the {file:docs/Searching.markdown Searching} tutorial for the
214
- # details on searching.
237
+ # See the [Searching Tutorial](http://github.com/Marketcircle/AXElements/wiki/Searching)
238
+ # for the details on search semantics.
215
239
  #
216
240
  # @example Find the dock icon for the Finder app
217
241
  #
218
- # AX::DOCK.search( :application_dock_item, title:'Finder' )
242
+ # AX::DOCK.search(:application_dock_item, title:'Finder')
219
243
  #
220
244
  # @param [#to_s]
221
245
  # @param [Hash{Symbol=>Object}]
@@ -233,7 +257,7 @@ class AX::Element
233
257
  end
234
258
 
235
259
  ##
236
- # Search for an ancestor of the current elemenet.
260
+ # Search for an ancestor of the current element.
237
261
  #
238
262
  # As the opposite of {#search}, this also takes filters, and can
239
263
  # be used to find a specific ancestor for the current element.
@@ -261,22 +285,30 @@ class AX::Element
261
285
  # lookup is always tried first, followed by a parameterized attribute
262
286
  # lookup, and then finally a search.
263
287
  #
264
- # Failing all lookups, this method calls `super`.
288
+ # Failing all lookups, this method calls `super`, which will probably
289
+ # raise an exception; however, most elements have children and so it
290
+ # is more likely that you will get an {Accessibility::SearchFailure}
291
+ # in cases where you sholud get a `NoMethodError`.
265
292
  #
266
293
  # @example
267
294
  #
268
- # mail = AX::Application.application_with_bundle_identifier 'com.apple.mail'
295
+ # mail = Accessibility.application_with_bundle_identifier 'com.apple.mail'
269
296
  #
270
297
  # # attribute lookup
271
298
  # window = mail.focused_window
272
299
  # # is equivalent to
273
300
  # window = mail.attribute :focused_window
274
301
  #
302
+ # # attribute setting
303
+ # window.position = CGPoint.new(100, 100)
304
+ # # is equivalent to
305
+ # window.set :position, CGPoint.new(100, 100)
306
+ #
275
307
  # # parameterized attribute lookup
276
- # window.title_ui_element.string_for_range (1..10).relative_to(100)
308
+ # window.title_ui_element.string_for_range 1..10
277
309
  # # is equivalent to
278
310
  # title = window.attribute :title_ui_element
279
- # title.param_attribute :string_for_range, for_param: (1..10).relative_to(100)
311
+ # title.parameterized_attribute :string_for_range, 1..10
280
312
  #
281
313
  # # simple single element search
282
314
  # window.button # => You want the first Button that is found
@@ -293,7 +325,7 @@ class AX::Element
293
325
  # # is equivalent to
294
326
  # window.search :button, title: 'Log In'
295
327
  #
296
- # # attribute and element search failure
328
+ # # searching from #method_missing will #raise if nothing is found
297
329
  # window.application # => SearchFailure is raised
298
330
  #
299
331
  def method_missing method, *args, &block
@@ -301,10 +333,10 @@ class AX::Element
301
333
 
302
334
  key = TRANSLATOR.cocoaify method
303
335
  if @ref.attributes.include? key
304
- return attribute method
336
+ return attribute(method)
305
337
 
306
338
  elsif @ref.parameterized_attributes.include? key
307
- return attribute(method, for_parameter: args.first)
339
+ return paramaterized_attribute(method, args.first)
308
340
 
309
341
  elsif @ref.attributes.include? KAXChildrenAttribute
310
342
  if (result = search(method, *args, &block)).blank?
@@ -319,78 +351,11 @@ class AX::Element
319
351
  end
320
352
  end
321
353
 
322
-
323
- # @group Notifications
324
-
325
- def notifs
326
- @notifs ||= {}
327
- end
328
-
329
- ##
330
- # Register to receive notification of the given event being completed
331
- # by the given element.
332
- #
333
- # {file:docs/Notifications.markdown Notifications} are a way to put
334
- # non-polling delays into your scripts.
335
- #
336
- # Use this method to register to be notified of the specified event in
337
- # an application.
338
- #
339
- # The block is optional. The block will be given the sender of the
340
- # notification, which will almost always be `self`, and also the name
341
- # of the notification being received. The block should return a
342
- # boolean value that decides if the notification received is the
343
- # expected one.
344
- #
345
- # @example
346
- #
347
- # on_notification(:window_created) { |sender|
348
- # puts "#{sender.inspect} sent the ':window_created' notification"
349
- # true
350
- # }
351
- #
352
- # @param [#to_s] notif the name of the notification
353
- # @yield Validate the notification; the block should return truthy if
354
- # the notification received is the expected one and the script can
355
- # stop waiting, otherwise should return falsy.
356
- # @yieldparam [String] notif the name of the notification
357
- # @yieldparam [AXUIElementRef] element the element that sent the notification
358
- # @yieldreturn [Boolean]
359
- # @return [Array(Observer, String, CFRunLoopSource)]
360
- def on_notification name, &block
361
- notif = TRANSLATOR.guess_notification name
362
- observer = @ref.observer &notif_callback_for(&block)
363
- source = @ref.run_loop_source_for observer
364
- @ref.register observer, to_receive: notif
365
- CFRunLoopAddSource(CFRunLoopGetCurrent(), source, KCFRunLoopDefaultMode)
366
- notifs[name] = [observer, notif, source]
367
- end
368
-
369
- def unregister_notification name
370
- unless notifs.has_key? name
371
- raise ArgumentError, "You have no registrations for #{name}"
372
- end
373
- _unregister_notification *notifs.delete(name)
374
- end
375
-
376
- ##
377
- # Cancel _all_ notification registrations for this object. Simple and
378
- # clean, but a blunt tool at best. This will have to do for the time
379
- # being...
380
- #
381
- # @return [nil]
382
- def unregister_all
383
- notifs.keys.each do |notif|
384
- unregister_notification notif
385
- end
386
- nil
387
- end
388
-
389
354
  # @endgroup
390
355
 
391
356
 
392
357
  ##
393
- # Overriden to produce cleaner output.
358
+ # Get relevant details about the current object.
394
359
  #
395
360
  # @return [String]
396
361
  def inspect
@@ -413,6 +378,25 @@ class AX::Element
413
378
  inspect
414
379
  end
415
380
 
381
+ ##
382
+ # Get the relevant details about the receiver and also the children
383
+ # and further descendents of the receiver. Each generation down the
384
+ # tree will be indented one level further.
385
+ #
386
+ # @example
387
+ #
388
+ # puts app.inspect_subtree
389
+ #
390
+ # @return [String]
391
+ def inspect_subtree
392
+ output = self.inspect + "\n"
393
+ enum = Accessibility::Enumerators::DepthFirst.new self
394
+ enum.each_with_level do |element, depth|
395
+ output << "\t"*depth + element.inspect + "\n"
396
+ end
397
+ output
398
+ end
399
+
416
400
  ##
417
401
  # Overriden to respond properly with regards to dynamic attribute
418
402
  # lookups, but will return false for potential implicit searches.
@@ -430,22 +414,22 @@ class AX::Element
430
414
  #
431
415
  # @return [CGPoint]
432
416
  def to_point
433
- size = attribute :size
434
- point = attribute :position
417
+ size = attribute :size
418
+ point = attribute :position
435
419
  point.x += size.width / 2
436
420
  point.y += size.height / 2
437
421
  point
438
422
  end
423
+ alias_method :hitpoint, :to_point
439
424
 
440
425
  ##
441
426
  # Get the bounding rectangle for the element.
442
427
  #
443
428
  # @return [CGRect]
444
429
  def bounds
445
- point = attribute :position
446
- size = attribute :size
447
- CGRectMake(*point, *size)
430
+ CGRect.new(attribute(:position), attribute(:size))
448
431
  end
432
+ alias_method :rect, :bounds
449
433
 
450
434
  ##
451
435
  # Get the application object for the element.
@@ -455,24 +439,31 @@ class AX::Element
455
439
  process @ref.application
456
440
  end
457
441
 
458
- ##
459
- # Concept borrowed from `Active Support`. It is used during implicit
460
- # searches to determine if searches yielded responses.
442
+ # (see NilClass#blank?)
461
443
  def blank?
462
444
  false
463
445
  end
464
446
 
465
447
  ##
466
- # @todo Need to add '?' to predicate methods, but how?
448
+ # Return whether or not the receiver is "dead".
467
449
  #
450
+ # A dead element is one that is no longer in the app's view
451
+ # hierarchy, which is not necessarily related to visibility.
452
+ def invalid?
453
+ @ref.role.nil?
454
+ end
455
+
456
+ ##
468
457
  # Like {#respond_to?}, this is overriden to include attribute methods.
458
+ # Though, it does include dynamic predicate methods at the moment.
469
459
  def methods include_super = true, include_objc_super = false
470
460
  super.concat(attributes).concat(parameterized_attributes)
471
461
  end
472
462
 
473
463
  ##
474
- # Overridden so that equality testing would work. A hack, but the only
475
- # sane way I can think of to test for equivalency.
464
+ # Overridden so that equality testing would work.
465
+ #
466
+ # A hack, but the only sane way I can think of to test for equivalency.
476
467
  def == other
477
468
  @ref == other.instance_variable_get(:@ref)
478
469
  end
@@ -482,36 +473,29 @@ class AX::Element
482
473
 
483
474
  private
484
475
 
485
- ##
486
476
  # @private
487
- #
488
- # Performance hack.
489
- #
490
477
  # @return [String]
491
478
  EQUALS = '='
492
479
 
493
- def notif_callback_for
494
- # we are ignoring the context pointer since this is OO
495
- Proc.new do |observer, sender, notif, _|
496
- break unless yield(process sender) if block_given?
497
- _unregister_notification observer, notif, run_loop_source_for(observer)
498
- CFRunLoopStop(CFRunLoopGetCurrent())
499
- end
500
- end
480
+ end
481
+
501
482
 
483
+ # Extensions so checking `#blank?` on search result "just works".
484
+ class NSArray
485
+ # (see NilClass#blank?)
486
+ alias_method :blank?, :empty?
487
+ end
488
+
489
+ # Extensions so checking `#blank?` on search result "just works".
490
+ class NilClass
502
491
  ##
503
- # @todo What are the implications of removing the run loop source?
504
- # Taking it out would clobber other notifications that are using
505
- # the same source, so we would have to check if we can remove it.
492
+ # Whether or not the object is "blank". The concept of blankness
493
+ # borrowed from `Active Support` and is true if the object is falsey
494
+ # or `#empty?`.
506
495
  #
507
- def _unregister_notification observer, notif, source
508
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, KCFRunLoopDefaultMode)
509
- @ref.unregister observer, from_receiving: notif
496
+ # This method is used by implicit searching in AXElements to
497
+ # determine if searches yielded responses.
498
+ def blank?
499
+ true
510
500
  end
511
-
512
501
  end
513
-
514
-
515
- # Extensions so checking #blank? on search result "just works".
516
- class NSArray; alias_method :blank?, :empty? end
517
- class NilClass; def blank?; true end end
@@ -0,0 +1,12 @@
1
+ require 'ax/element'
2
+
3
+ ##
4
+ # UI Element for pop up buttons.
5
+ class AX::PopUpButton < AX::Element
6
+ end
7
+
8
+ ##
9
+ # An alias for {AX::PopUpButton}.
10
+ #
11
+ # @return [Class]
12
+ AX::PopUp = AX::PopUpButton
@@ -13,8 +13,11 @@ class AX::RadioButton < AX::Element
13
13
  #
14
14
  # @return [Boolean]
15
15
  def == other
16
- return attribute(:title) == other if other.kind_of? NSString
17
- return super
16
+ if other.kind_of? NSString
17
+ attribute(:title) == other
18
+ else
19
+ super
20
+ end
18
21
  end
19
22
 
20
23
  end
data/lib/ax/row.rb CHANGED
@@ -2,13 +2,13 @@ require 'ax/element'
2
2
  require 'accessibility/qualifier'
3
3
 
4
4
  ##
5
- # UI Element for the row in a table, outline, etc.
5
+ # UI Element for the row in a table, outline view, etc.
6
6
  class AX::Row < AX::Element
7
7
 
8
8
  ##
9
9
  # Retrieve the child in a row that corresponds to a specific column.
10
10
  # You must pass filters here in the same way that you would for a
11
- # search.
11
+ # search or wait.
12
12
  #
13
13
  # This is useful for tables where it is difficult to identify which
14
14
  # row item is the one you want based on the row items themselves.
@@ -12,8 +12,11 @@ class AX::StaticText < AX::Element
12
12
  #
13
13
  # @return [Boolean]
14
14
  def == other
15
- return super unless other.kind_of? NSString
16
- return attribute(:value) == other
15
+ if other.kind_of? NSString
16
+ attribute(:value) == other
17
+ else
18
+ super
19
+ end
17
20
  end
18
21
 
19
22
  end
data/lib/ax/systemwide.rb CHANGED
@@ -23,25 +23,37 @@ class AX::SystemWide < AX::Element
23
23
  #
24
24
  # Generate keyboard events by simulating keyboard input.
25
25
  #
26
- # See the {file:docs/KeyboardEvents.markdown Keyboard} documentation for
27
- # more information on how to format strings.
26
+ # See the
27
+ # [Keyboarding documentation](http://github.com/Marketcircle/AXElements/wiki/Keyboarding)
28
+ # for more information on how to format strings.
28
29
  #
29
30
  # @return [Boolean]
30
31
  def type string
31
32
  @ref.post keyboard_events_for string
32
33
  true
33
34
  end
35
+ alias_method :type_string, :type
34
36
 
35
- # @todo doc and cleanup
36
- def keydown modifier
37
- @ref.post [[EventGenerator::CUSTOM[modifier], true]]
38
- true
39
- end
40
-
41
- # @todo doc and cleanup
42
- def keyup modifier
43
- @ref.post [[EventGenerator::CUSTOM[modifier], false]]
44
- true
37
+ ##
38
+ # Press the given modifier key and hold it down while yielding to the
39
+ # given block.
40
+ #
41
+ # @example
42
+ #
43
+ # hold_key "\\CONTROL" do
44
+ # drag_mouse_to point
45
+ # end
46
+ #
47
+ # @param [String]
48
+ # @return [Number,nil]
49
+ def hold_modifier key
50
+ code = EventGenerator::CUSTOM[key]
51
+ raise ArgumentError, "Invalid modifier `#{key}' given" unless code
52
+ @ref.post [[code, true]]
53
+ yield
54
+ ensure # if block raises the button might stuck, so ensure it is released
55
+ @ref.post [[code,false]] if code
56
+ code
45
57
  end
46
58
 
47
59
  ##
@@ -1,12 +1,21 @@
1
1
  require 'awesome_print'
2
2
 
3
+ ##
4
+ # `AwesomePrint` extension for AXElements.
3
5
  module AwesomePrint::AXElements
4
6
 
7
+ ##
8
+ # Perform the silly `alias_method_chain` stuff that AwesomePrint
9
+ # expects.
5
10
  def self.included base
6
11
  base.send :alias_method, :cast_without_ax_elements, :cast
7
12
  base.send :alias_method, :cast, :cast_with_ax_elements
8
13
  end
9
14
 
15
+ ##
16
+ # Format {AX::Element} objects for AwesomePrint. For the time
17
+ # being, just work-around the default AwesomePrint output by
18
+ # using the default `#inpspect` for {AX::Element}.
10
19
  def cast_with_ax_elements object, type
11
20
  cast = cast_without_ax_elements object, type
12
21
  cast = :ax_element if object.kind_of? ::AX::Element
@@ -16,6 +25,10 @@ module AwesomePrint::AXElements
16
25
 
17
26
  private
18
27
 
28
+ ##
29
+ # Give the awesome output for an {AX::Element} object.
30
+ #
31
+ # @return [String]
19
32
  def awesome_ax_element object
20
33
  object.inspect
21
34
  end
@@ -2,6 +2,11 @@
2
2
  # Workaround for MacRuby ticket #1334
3
3
  class Exception
4
4
  alias_method :original_message, :message
5
+ #
6
+ # Override the message method to force the backtrace to be
7
+ # included.
8
+ #
9
+ # @return [String]
5
10
  def message
6
11
  "#{original_message}\n\t#{backtrace.join("\n\t")}"
7
12
  end
@@ -53,6 +53,7 @@ module Accessibility::NSArrayCompat
53
53
  private
54
54
 
55
55
  # @private
56
+ # @return [Accessibility::Translator]
56
57
  TRANSLATOR = Accessibility::Translator.instance
57
58
 
58
59
  end
data/lib/ax_elements.rb CHANGED
@@ -6,13 +6,14 @@ include Accessibility::DSL
6
6
  # The Mac OS X dock application.
7
7
  #
8
8
  # @return [AX::Application]
9
- AX::DOCK = app_with_bundle_identifier 'com.apple.dock'
9
+ AX::DOCK = AX::Application.new('com.apple.dock')
10
10
 
11
11
  # Load explicitly defined elements that are optional
12
12
  require 'ax/button'
13
13
  require 'ax/radio_button'
14
14
  require 'ax/row'
15
15
  require 'ax/static_text'
16
+ require 'ax/pop_up_button'
16
17
 
17
18
  # Misc things that we need to load
18
19
  require 'ax_elements/nsarray_compat'