AXElements 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -98,13 +98,13 @@ module Accessibility::Core
98
98
  def attribute name
99
99
  ptr = Pointer.new :id
100
100
  case code = AXUIElementCopyAttributeValue(self, name, ptr)
101
- when 0 then ptr.value.to_ruby
102
- when KAXErrorNoValue then nil
103
- when KAXErrorInvalidUIElement
101
+ when 0
102
+ ptr.value.to_ruby
103
+ when KAXErrorNoValue, KAXErrorAttributeUnsupported,
104
+ KAXErrorFailure, KAXErrorInvalidUIElement then
104
105
  name == KAXChildrenAttribute ? [] : nil
105
- when KAXErrorFailure
106
- name == KAXChildrenAttribute ? [] : handle_error(code, name)
107
- else handle_error code, name
106
+ else
107
+ handle_error code, name
108
108
  end
109
109
  end
110
110
 
@@ -177,10 +177,13 @@ module Accessibility::Core
177
177
  def size_of name
178
178
  ptr = Pointer.new :long_long
179
179
  case code = AXUIElementGetAttributeValueCount(self, name, ptr)
180
- when 0 then ptr.value
180
+ when 0
181
+ ptr.value
181
182
  when KAXErrorFailure, KAXErrorAttributeUnsupported,
182
- KAXErrorInvalidUIElement then 0
183
- else handle_error code, name
183
+ KAXErrorNoValue, KAXErrorInvalidUIElement
184
+ 0
185
+ else
186
+ handle_error code, name
184
187
  end
185
188
  end
186
189
 
@@ -196,9 +199,13 @@ module Accessibility::Core
196
199
  def writable? name
197
200
  ptr = Pointer.new :bool
198
201
  case code = AXUIElementIsAttributeSettable(self, name, ptr)
199
- when 0 then ptr.value
200
- when KAXErrorInvalidUIElement then false
201
- else handle_error code, name
202
+ when 0
203
+ ptr.value
204
+ when KAXErrorFailure, KAXErrorAttributeUnsupported,
205
+ KAXErrorNoValue, KAXErrorInvalidUIElement
206
+ false
207
+ else
208
+ handle_error code, name
202
209
  end
203
210
  end
204
211
 
@@ -223,8 +230,11 @@ module Accessibility::Core
223
230
  # @param [String] name an attribute constant
224
231
  def set name, value
225
232
  code = AXUIElementSetAttributeValue(self, name, value.to_ax)
226
- return value if code.zero?
227
- handle_error code, name, value
233
+ if code.zero?
234
+ value
235
+ else
236
+ handle_error code, name, value
237
+ end
228
238
  end
229
239
 
230
240
 
@@ -270,12 +280,15 @@ module Accessibility::Core
270
280
  # @param [String] attr an attribute constant
271
281
  # @param [Object] param
272
282
  def attribute name, for_parameter: param
273
- ptr = Pointer.new :id
274
- param = param.to_ax
275
- case code = AXUIElementCopyParameterizedAttributeValue(self,name,param,ptr)
276
- when 0 then ptr.value.to_ruby
277
- when KAXErrorNoValue, KAXErrorInvalidUIElement then nil
278
- else handle_error code, name, param
283
+ ptr = Pointer.new :id
284
+ case code = AXUIElementCopyParameterizedAttributeValue(self, name, param.to_ax, ptr)
285
+ when 0
286
+ ptr.value.to_ruby
287
+ when KAXErrorFailure, KAXErrorAttributeUnsupported,
288
+ KAXErrorNoValue, KAXErrorInvalidUIElement
289
+ nil
290
+ else
291
+ handle_error code, name, param
279
292
  end
280
293
  end
281
294
 
@@ -318,8 +331,11 @@ module Accessibility::Core
318
331
  # @return [Boolean]
319
332
  def perform action
320
333
  code = AXUIElementPerformAction(self, action)
321
- return true if code.zero?
322
- handle_error code, action
334
+ if code.zero?
335
+ true
336
+ else
337
+ handle_error code, action
338
+ end
323
339
  end
324
340
 
325
341
  ##
@@ -398,9 +414,14 @@ module Accessibility::Core
398
414
  def element_at point
399
415
  ptr = Pointer.new ELEMENT
400
416
  case code = AXUIElementCopyElementAtPosition(self, *point.to_point, ptr)
401
- when 0 then ptr.value
402
- when KAXErrorNoValue then nil
403
- else handle_error code, point, nil, nil
417
+ when 0
418
+ ptr.value
419
+ when KAXErrorNoValue
420
+ nil
421
+ when KAXErrorInvalidUIElement
422
+ system_wide.element_at point unless self == system_wide
423
+ else
424
+ handle_error code, point, nil, nil
404
425
  end
405
426
  end
406
427
 
@@ -453,9 +474,11 @@ module Accessibility::Core
453
474
  raise ArgumentError, 'A callback is required' unless block_given?
454
475
  ptr = Pointer.new OBSERVER
455
476
  callback = proc { |obsrvr, sender, notif, ctx| yield obsrvr, sender, notif }
456
- case code = AXObserverCreate(pid, callback, ptr)
457
- when 0 then ptr.value
458
- else handle_error code, callback
477
+ code = AXObserverCreate(pid, callback, ptr)
478
+ if code.zero?
479
+ ptr.value
480
+ else
481
+ handle_error code, callback
459
482
  end
460
483
  end
461
484
 
@@ -540,12 +563,14 @@ module Accessibility::Core
540
563
  # @return [Fixnum]
541
564
  def pid
542
565
  @pid ||= (
543
- ptr = Pointer.new :int
566
+ ptr = Pointer.new :int
544
567
  case code = AXUIElementGetPid(self, ptr)
545
- when 0 then ptr.value
568
+ when 0
569
+ ptr.value
546
570
  when KAXErrorInvalidUIElement
547
571
  self == system_wide ? 0 : handle_error(code)
548
- else handle_error code
572
+ else
573
+ handle_error code
549
574
  end
550
575
  )
551
576
  end
@@ -889,9 +914,3 @@ class CGPoint
889
914
  # @return [CGPoint]
890
915
  def to_point; self end
891
916
  end
892
-
893
- ##
894
- # Cached reference to the system wide object.
895
- #
896
- # @return [AXUIElementRef]
897
- SYSTEMWIDE = AXUIElementCreateSystemWide()
@@ -210,7 +210,7 @@ module Accessibility::DSL
210
210
  #
211
211
  # @param [AX::Element]
212
212
  def set_focus_to element
213
- element.set(:focused, true) if element.respond_to? :focused?
213
+ element.set(:focused, true) if element.respond_to? :focused
214
214
  end
215
215
  alias_method :set_focus, :set_focus_to
216
216
 
@@ -243,7 +243,7 @@ module Accessibility::DSL
243
243
  # @return [nil] do not rely on a return value
244
244
  def set element, change
245
245
  if element.respond_to? :focused
246
- if element.attribute_writable? :focused
246
+ if element.writable? :focused
247
247
  element.set :focused, true
248
248
  end
249
249
  end
@@ -66,16 +66,11 @@ module Accessibility::Factory
66
66
  # @param [AXUIElementRef]
67
67
  # @return [AX::Element]
68
68
  def process_element ref
69
- role = TRANSLATOR.unprefix ref.role
70
- attrs = ref.attributes
71
- klass = if attrs.include? KAXSubroleAttribute
72
- subrole = ref.subrole
73
- # Some objects claim to have a subrole but return nil
74
- if subrole
75
- class_for TRANSLATOR.unprefix(subrole), and: role
76
- else
77
- class_for role
78
- end
69
+ role = TRANSLATOR.unprefix ref.role
70
+
71
+ # Some objects claim to have a subrole but return nil
72
+ klass = if subrole = ref.subrole
73
+ class_for TRANSLATOR.unprefix(subrole), and: role
79
74
  else
80
75
  class_for role
81
76
  end
@@ -87,9 +82,9 @@ module Accessibility::Factory
87
82
  #
88
83
  # @return [Array]
89
84
  def process_array vals
90
- return vals if vals.empty?
91
- return vals if CFGetTypeID(vals.first) != REF_TYPE
92
- return vals.map { |val| process_element val }
85
+ (vals.empty? && vals) ||
86
+ (CFGetTypeID(vals.first) != REF_TYPE && vals) ||
87
+ vals.map { |val| process_element val }
93
88
  end
94
89
 
95
90
  ##
@@ -137,7 +132,7 @@ module Accessibility::Factory
137
132
 
138
133
  ##
139
134
  # Create a new class in the {AX} namesapce that has the given
140
- # `superklass` as the superclass..
135
+ # `superklass` as the superclass.
141
136
  #
142
137
  # @param [#to_s] name
143
138
  # @param [#to_s] superklass
@@ -18,7 +18,6 @@ module Accessibility::PPInspector
18
18
  #
19
19
  # @return [String]
20
20
  def pp_identifier
21
- # @todo Break this method up into chunks
22
21
  # @note use, or lack of use, of #inspect is intentional for visual effect
23
22
 
24
23
  if attributes.include? :value
@@ -1,6 +1,6 @@
1
1
  module Accessibility
2
2
  # @return [String]
3
- VERSION = '0.7.5'
3
+ VERSION = '0.7.6'
4
4
 
5
5
  # @return [String]
6
6
  CODE_NAME = 'Clefairy'
@@ -9,6 +9,13 @@ require 'accessibility/string'
9
9
  class AX::Application < AX::Element
10
10
  include Accessibility::String
11
11
 
12
+ ##
13
+ # @private
14
+ # Cached reference to the system wide object.
15
+ #
16
+ # @return [AXUIElementRef]
17
+ SYSTEMWIDE = AXUIElementCreateSystemWide()
18
+
12
19
  ##
13
20
  # Overridden so that we can also cache the `NSRunningApplication`
14
21
  # instance for this object.
@@ -81,7 +88,7 @@ class AX::Application < AX::Element
81
88
  # Overridden to handle the {Accessibility::Language#set_focus} case.
82
89
  #
83
90
  # (see AX::Element#set:to:)
84
- def set attr, to: value
91
+ def set attr, value
85
92
  case attr
86
93
  when :focused
87
94
  perform(value ? :unhide : :hide)
data/lib/ax/element.rb CHANGED
@@ -17,6 +17,7 @@ class AX::Element
17
17
  include Accessibility::PPInspector
18
18
  include Accessibility::Factory
19
19
 
20
+
20
21
  # @param [AXUIElementRef]
21
22
  def initialize ref
22
23
  @ref = ref
@@ -34,7 +35,7 @@ class AX::Element
34
35
  #
35
36
  # @return [Array<Symbol>]
36
37
  def attributes
37
- @attributes ||= TRANSLATOR.rubyize @ref.attributes
38
+ @attrs ||= TRANSLATOR.rubyize @ref.attributes
38
39
  end
39
40
 
40
41
  ##
@@ -49,14 +50,15 @@ class AX::Element
49
50
  #
50
51
  # @param [#to_sym]
51
52
  def attribute name
52
- if rattr = lookup(name, @ref.attributes)
53
+ if rattr = TRANSLATOR.lookup(name, @ref.attributes)
53
54
  process @ref.attribute(rattr)
54
55
  end
55
56
  end
56
57
 
57
58
  ##
58
- # Needed to override inherited `NSObject#description`. If you want a
59
- # description of the object then you should use {#inspect} instead.
59
+ # Needed to override inherited `NSObject#description` as some
60
+ # elements have a `description` attribute. If you want a description
61
+ # of the object then you should use {#inspect} instead.
60
62
  def description
61
63
  attribute :description
62
64
  end
@@ -75,7 +77,7 @@ class AX::Element
75
77
  # @param [#to_sym]
76
78
  # @return [Number]
77
79
  def size_of attr
78
- if rattr = lookup(attr, @ref.attributes)
80
+ if rattr = TRANSLATOR.lookup(attr, @ref.attributes)
79
81
  @ref.size_of rattr
80
82
  else
81
83
  0
@@ -105,7 +107,7 @@ class AX::Element
105
107
  #
106
108
  # @param [#to_sym]
107
109
  def writable? attr
108
- if rattr = lookup(attr, @ref.attributes)
110
+ if rattr = TRANSLATOR.lookup(attr, @ref.attributes)
109
111
  @ref.writable? rattr
110
112
  else
111
113
  false
@@ -127,9 +129,7 @@ class AX::Element
127
129
  raise NoMethodError, "#{attr} is read-only for #{inspect}"
128
130
  end
129
131
  value = value.relative_to(@ref.value.size) if value.kind_of? Range
130
- rattr = lookup(attr, @ref.attributes)
131
- @ref.set rattr, value
132
- value
132
+ @ref.set TRANSLATOR.lookup(attr, @ref.attributes), value
133
133
  end
134
134
 
135
135
 
@@ -146,7 +146,7 @@ class AX::Element
146
146
  #
147
147
  # @return [Array<Symbol>]
148
148
  def parameterized_attributes
149
- TRANSLATOR.rubyize @ref.parameterized_attributes
149
+ @param_attrs ||= TRANSLATOR.rubyize @ref.parameterized_attributes
150
150
  end
151
151
 
152
152
  ##
@@ -158,7 +158,7 @@ class AX::Element
158
158
  #
159
159
  # @param [#to_sym]
160
160
  def attribute attr, for_parameter: param
161
- if rattr = lookup(attr, @ref.parameterized_attributes)
161
+ if rattr = TRANSLATOR.lookup(attr, @ref.parameterized_attributes)
162
162
  param = param.relative_to(@ref.value.size) if value.kind_of? Range
163
163
  process @ref.attribute(rattr, for_parameter: param)
164
164
  end
@@ -178,7 +178,7 @@ class AX::Element
178
178
  #
179
179
  # @return [Array<Symbol>]
180
180
  def actions
181
- TRANSLATOR.rubyize @ref.actions
181
+ @actions ||= TRANSLATOR.rubyize @ref.actions
182
182
  end
183
183
 
184
184
  ##
@@ -191,12 +191,13 @@ class AX::Element
191
191
  #
192
192
  # @example
193
193
  #
194
- # button.perform :press # => true
194
+ # button.perform :press # => true
195
+ # button.perform :make_pie # => false
195
196
  #
196
197
  # @param [#to_sym]
197
198
  # @return [Boolean] true if successful
198
199
  def perform action
199
- if raction = lookup(action, @ref.actions)
200
+ if raction = TRANSLATOR.lookup(action, @ref.actions)
200
201
  @ref.perform raction
201
202
  else
202
203
  false
@@ -226,7 +227,7 @@ class AX::Element
226
227
  tree = Accessibility::Enumerators::BreadthFirst.new(self)
227
228
 
228
229
  if TRANSLATOR.singularize(kind) == kind
229
- tree.find { |element| qualifier.qualifies? element }
230
+ tree.find { |element| qualifier.qualifies? element }
230
231
  else
231
232
  tree.find_all { |element| qualifier.qualifies? element }
232
233
  end
@@ -300,16 +301,18 @@ class AX::Element
300
301
  if method[-1] == EQUALS
301
302
  return set(method.chomp(EQUALS), args.first)
302
303
 
303
- elsif attr = lookup(method, @ref.attributes)
304
- return process @ref.attribute(attr)
304
+ elsif attributes.include? method
305
+ return attribute method
305
306
 
306
- elsif attr = lookup(method, @ref.parameterized_attributes)
307
- return process @ref.attribute(attr, for_parameter: args.first)
307
+ elsif parameterized_attributes.include? method
308
+ return attribute method, for_parameter: args.first
308
309
 
309
- elsif @ref.attributes.include? KAXChildrenAttribute
310
- result = search method, *args, &block
311
- return result unless result.blank?
312
- raise Accessibility::SearchFailure.new(self, method, args.first)
310
+ elsif attributes.include? :children
311
+ if (result = search method, *args, &block).blank?
312
+ raise Accessibility::SearchFailure.new(self, method, args.first)
313
+ else
314
+ return result
315
+ end
313
316
 
314
317
  else
315
318
  super
@@ -416,8 +419,8 @@ class AX::Element
416
419
  # Overriden to respond properly with regards to dynamic attribute
417
420
  # lookups, but will return false for potential implicit searches.
418
421
  def respond_to? name
419
- lookup(name.chomp(EQUALS), @ref.attributes) ||
420
- lookup(name, @ref.parameterized_attributes) ||
422
+ attributes.include?(name) ||
423
+ parameterized_attributes.include?(name) ||
421
424
  super
422
425
  end
423
426
 
@@ -486,11 +489,6 @@ class AX::Element
486
489
  # @return [String]
487
490
  EQUALS = '='
488
491
 
489
- def lookup key, values
490
- value = TRANSLATOR.lookup key, values
491
- return value if values.include? value
492
- end
493
-
494
492
  def notif_callback_for
495
493
  # we are ignoring the context pointer since this is OO
496
494
  Proc.new do |observer, sender, notif, _|
@@ -59,6 +59,22 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
59
59
  assert_equal app, dsl.app_with_pid(PID)
60
60
  end
61
61
 
62
+ def test_set_focus_to
63
+ assert dsl.set_focus_to app
64
+ assert dsl.set_focus app
65
+ assert dsl.set_focus_to app.main_window.search_field
66
+ assert dsl.set_focus app.main_window.search_field
67
+ end
68
+
69
+ def test_set
70
+ expected = 'Octocat is not Hello Kitty!'
71
+ field = app.main_window.search_field
72
+ dsl.set field, expected
73
+ assert_equal expected, field.value
74
+ ensure
75
+ field.set :value, '' if field
76
+ end
77
+
62
78
  def test_typing_human_string
63
79
  try_typing "A sentence, with punctuation and num8ers. LOL!\tA 'quoted' string--then some @#*$."
64
80
  end
@@ -17,12 +17,12 @@ class TestAXApplication < MiniTest::Unit::TestCase
17
17
  end
18
18
 
19
19
  def test_can_set_focus_and_blur_app # lol, blur
20
- assert app.set :focused, to: false
20
+ assert app.set :focused, false
21
21
  refute app.active?
22
22
  refute app.attribute :focused
23
23
  refute app.attribute :focused?
24
24
 
25
- assert app.set :focused, to: true
25
+ assert app.set :focused, true
26
26
  assert app.active?
27
27
  assert app.attribute :focused
28
28
  assert app.attribute :focused?
@@ -32,10 +32,10 @@ class TestAXApplication < MiniTest::Unit::TestCase
32
32
  end
33
33
 
34
34
  def test_can_hide_and_unhide_app
35
- assert app.set :hidden, to: true
35
+ assert app.set :hidden, true
36
36
  assert app.hidden?
37
37
 
38
- assert app.set :hidden, to: false
38
+ assert app.set :hidden, false
39
39
  refute app.hidden?
40
40
 
41
41
  assert app.perform :hide
@@ -48,6 +48,10 @@ class TestAXApplication < MiniTest::Unit::TestCase
48
48
  running_app.activateWithOptions NSApplicationActivateIgnoringOtherApps
49
49
  end
50
50
 
51
+ def test_set_calls_super
52
+ assert app.set(:enhanced_user_interface, true)
53
+ end
54
+
51
55
  def test_element_at_point
52
56
  button = app.main_window.close_button
53
57
  assert_equal button, app.element_at_point(button)
@@ -39,8 +39,4 @@ class TestAXElement < MiniTest::Unit::TestCase
39
39
  box.set :value, '' if box
40
40
  end
41
41
 
42
- # @todo test setting selected text
43
- # def test_setting
44
- # end
45
-
46
42
  end
@@ -70,7 +70,7 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
70
70
  assert_equal 10..19, window.attribute("AXPie" )
71
71
  end
72
72
 
73
- def test_attribute_is_nil_when_no_value
73
+ def test_attribute_when_no_value
74
74
  assert_nil window.attribute(KAXGrowAreaAttribute)
75
75
  end
76
76
 
@@ -79,8 +79,8 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
79
79
  assert_empty invalid_ref.attribute(KAXChildrenAttribute)
80
80
  end
81
81
 
82
- def test_attribute_handles_errors
83
- assert_raises(ArgumentError) { REF.attribute 'MADEUPATTRIBUTE' }
82
+ def test_attribute_when_not_supported_attribute
83
+ assert_nil REF.attribute('MADEUPATTRIBUTE')
84
84
  end
85
85
 
86
86
  def test_role
@@ -120,8 +120,8 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
120
120
  refute invalid_ref.writable? KAXRoleAttribute
121
121
  end
122
122
 
123
- def test_writable_handles_errors
124
- assert_raises(ArgumentError) { REF.writable? 'FAKE' }
123
+ def test_writable_false_for_bad_attributes
124
+ refute REF.writable? 'FAKE'
125
125
  end
126
126
 
127
127
  def test_set_number
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: AXElements
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.7.5
5
+ version: 0.7.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mark Rada
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-04 00:00:00 Z
12
+ date: 2012-04-06 00:00:00 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest