AXElements 0.9.0 → 1.0.0.alpha
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.
- data/.yardopts +0 -4
- data/README.markdown +22 -17
- data/Rakefile +1 -1
- data/ext/accessibility/key_coder/extconf.rb +1 -1
- data/ext/accessibility/key_coder/key_coder.c +2 -4
- data/lib/accessibility.rb +3 -3
- data/lib/accessibility/core.rb +948 -0
- data/lib/accessibility/dsl.rb +30 -186
- data/lib/accessibility/enumerators.rb +1 -0
- data/lib/accessibility/factory.rb +78 -134
- data/lib/accessibility/graph.rb +5 -9
- data/lib/accessibility/highlighter.rb +86 -0
- data/lib/accessibility/{pretty_printer.rb → pp_inspector.rb} +4 -3
- data/lib/accessibility/qualifier.rb +3 -5
- data/lib/accessibility/screen_recorder.rb +217 -0
- data/lib/accessibility/statistics.rb +57 -0
- data/lib/accessibility/translator.rb +23 -32
- data/lib/accessibility/version.rb +2 -22
- data/lib/ax/application.rb +20 -159
- data/lib/ax/element.rb +42 -32
- data/lib/ax/scroll_area.rb +5 -6
- data/lib/ax/systemwide.rb +1 -33
- data/lib/ax_elements.rb +1 -9
- data/lib/ax_elements/core_graphics_workaround.rb +5 -0
- data/lib/ax_elements/nsarray_compat.rb +17 -97
- data/lib/ax_elements/vendor/inflection_data.rb +66 -0
- data/lib/ax_elements/vendor/inflections.rb +176 -0
- data/lib/ax_elements/vendor/inflector.rb +306 -0
- data/lib/minitest/ax_elements.rb +180 -0
- data/lib/mouse.rb +227 -0
- data/lib/rspec/expectations/ax_elements.rb +234 -0
- data/rakelib/gem.rake +3 -12
- data/rakelib/test.rake +15 -0
- data/test/helper.rb +20 -10
- data/test/integration/accessibility/test_core.rb +18 -0
- data/test/integration/accessibility/test_dsl.rb +40 -38
- data/test/integration/accessibility/test_enumerators.rb +1 -0
- data/test/integration/accessibility/test_graph.rb +0 -1
- data/test/integration/accessibility/test_qualifier.rb +2 -2
- data/test/integration/ax/test_application.rb +2 -9
- data/test/integration/ax/test_element.rb +0 -40
- data/test/integration/minitest/test_ax_elements.rb +89 -0
- data/test/integration/rspec/expectations/test_ax_elements.rb +102 -0
- data/test/sanity/accessibility/test_factory.rb +2 -2
- data/test/sanity/accessibility/test_highlighter.rb +56 -0
- data/test/sanity/accessibility/{test_pretty_printer.rb → test_pp_inspector.rb} +9 -9
- data/test/sanity/accessibility/test_statistics.rb +57 -0
- data/test/sanity/ax/test_application.rb +1 -16
- data/test/sanity/ax/test_element.rb +2 -2
- data/test/sanity/ax_elements/test_nsobject_inspect.rb +2 -4
- data/test/sanity/minitest/test_ax_elements.rb +17 -0
- data/test/sanity/rspec/expectations/test_ax_elements.rb +15 -0
- data/test/sanity/test_mouse.rb +22 -0
- data/test/test_core.rb +454 -0
- metadata +44 -69
- data/History.markdown +0 -41
- data/lib/accessibility/system_info.rb +0 -230
- data/lib/ax_elements/active_support_selections.rb +0 -10
- data/lib/ax_elements/mri.rb +0 -57
- data/test/sanity/accessibility/test_version.rb +0 -15
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'accessibility/version'
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
ActiveSupport::Inflector.inflections do |inflect|
|
6
|
-
# Related to accessibility
|
7
|
-
inflect.acronym('UI')
|
8
|
-
inflect.acronym('RTF')
|
9
|
-
inflect.acronym('URL')
|
10
|
-
end
|
2
|
+
require 'ax_elements/vendor/inflector'
|
3
|
+
|
4
|
+
framework 'ApplicationServices'
|
11
5
|
|
12
|
-
|
6
|
+
unless Object.const_defined? :KAXIdentifierAttribute
|
7
|
+
##
|
8
|
+
# Added for backwards compatability with Snow Leopard.
|
9
|
+
# This attribute is standard with Lion and newer. AXElements depends
|
10
|
+
# on it being defined.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
KAXIdentifierAttribute = 'AXIdentifier'
|
14
|
+
end
|
13
15
|
|
14
16
|
|
15
17
|
##
|
@@ -70,9 +72,7 @@ class Accessibility::Translator
|
|
70
72
|
# @param keys [Array<String>]
|
71
73
|
# @return [Array<Symbol>]
|
72
74
|
def rubyize keys
|
73
|
-
keys
|
74
|
-
keys.flatten!
|
75
|
-
keys
|
75
|
+
keys.map { |x| @rubyisms[x] }
|
76
76
|
end
|
77
77
|
|
78
78
|
##
|
@@ -133,17 +133,6 @@ class Accessibility::Translator
|
|
133
133
|
|
134
134
|
private
|
135
135
|
|
136
|
-
def preloads
|
137
|
-
{
|
138
|
-
# basic preloads
|
139
|
-
id: KAXIdentifierAttribute,
|
140
|
-
placeholder: KAXPlaceholderValueAttribute,
|
141
|
-
# workarounds for known case where AX uses "Is" for a boolean attribute
|
142
|
-
application_running: KAXIsApplicationRunningAttribute,
|
143
|
-
application_running?: KAXIsApplicationRunningAttribute,
|
144
|
-
}
|
145
|
-
end
|
146
|
-
|
147
136
|
# @return [Hash{String=>String}]
|
148
137
|
def init_unprefixes
|
149
138
|
@unprefixes = Hash.new do |hash, key|
|
@@ -154,32 +143,34 @@ class Accessibility::Translator
|
|
154
143
|
# @return [Hash{String=>Symbol}]
|
155
144
|
def init_rubyisms
|
156
145
|
@rubyisms = Hash.new do |hash, key|
|
157
|
-
hash[key] =
|
146
|
+
hash[key] = Accessibility::Inflector.underscore(@unprefixes[key]).to_sym
|
158
147
|
end
|
159
|
-
preloads.each_pair do |k,v| @rubyisms[v] << k end
|
160
148
|
end
|
161
149
|
|
162
150
|
# @return [Hash{Symbol=>String}]
|
163
151
|
def init_cocoaifications
|
164
152
|
@cocoaifications = Hash.new do |hash, key|
|
165
|
-
|
166
|
-
str_key.chomp! QUESTION_MARK
|
167
|
-
hash[key] = "AX#{ActiveSupport::Inflector.camelize(str_key)}"
|
153
|
+
hash[key] = "AX#{Accessibility::Inflector.camelize(key.chomp QUESTION_MARK)}"
|
168
154
|
end
|
169
|
-
|
155
|
+
# preload the table
|
156
|
+
@cocoaifications[:id] = KAXIdentifierAttribute
|
157
|
+
@cocoaifications[:placeholder] = KAXPlaceholderValueAttribute
|
158
|
+
# workaround the one known case where AX uses "Is" for a boolean attribute
|
159
|
+
@cocoaifications[:application_running] = # let the value all fall through
|
160
|
+
@cocoaifications[:application_running?] = KAXIsApplicationRunningAttribute
|
170
161
|
end
|
171
162
|
|
172
163
|
# @return [Hash{String=>String}]
|
173
164
|
def init_classifications
|
174
165
|
@classifications = Hash.new do |hash, key|
|
175
|
-
hash[key] =
|
166
|
+
hash[key] = Accessibility::Inflector.classify(key)
|
176
167
|
end
|
177
168
|
end
|
178
169
|
|
179
170
|
# @return [Hash{String=>String}]
|
180
171
|
def init_singularizations
|
181
172
|
@singularizations = Hash.new do |hash, key|
|
182
|
-
hash[key] =
|
173
|
+
hash[key] = Accessibility::Inflector.singularize(key)
|
183
174
|
end
|
184
175
|
end
|
185
176
|
|
@@ -4,28 +4,8 @@
|
|
4
4
|
# The main AXElements namespace.
|
5
5
|
module Accessibility
|
6
6
|
# @return [String]
|
7
|
-
VERSION = '0.
|
7
|
+
VERSION = '1.0.0.alpha'
|
8
8
|
|
9
9
|
# @return [String]
|
10
|
-
CODE_NAME = '
|
11
|
-
|
12
|
-
# @return [String]
|
13
|
-
ENGINE = case RUBY_ENGINE
|
14
|
-
when 'macruby' then 'サンダース'
|
15
|
-
when 'ruby' then 'ブースター'
|
16
|
-
when 'rbx' then 'ブラッキー' # for when rbx has good cext support
|
17
|
-
else 'シャワーズ' # vapor(ware)eon
|
18
|
-
end
|
19
|
-
|
20
|
-
##
|
21
|
-
# The complete version string for AXElements
|
22
|
-
#
|
23
|
-
# This differs from {Accessibility::VERSION} in that it also
|
24
|
-
# includes `RUBY_ENGINE` information.
|
25
|
-
#
|
26
|
-
# @return [String]
|
27
|
-
def self.version
|
28
|
-
"#{VERSION}-#{ENGINE}"
|
29
|
-
end
|
30
|
-
|
10
|
+
CODE_NAME = 'ルナトーン'
|
31
11
|
end
|
data/lib/ax/application.rb
CHANGED
@@ -11,102 +11,12 @@ require 'accessibility/string'
|
|
11
11
|
class AX::Application < AX::Element
|
12
12
|
include Accessibility::String
|
13
13
|
|
14
|
-
class << self
|
15
|
-
##
|
16
|
-
# Asynchronously launch an application with given the bundle identifier
|
17
|
-
#
|
18
|
-
# @param bundle [String] bundle identifier for the app
|
19
|
-
# @return [Boolean]
|
20
|
-
def launch bundle
|
21
|
-
NSWorkspace.sharedWorkspace.launchAppWithBundleIdentifier bundle,
|
22
|
-
options: NSWorkspace::NSWorkspaceLaunchAsync,
|
23
|
-
additionalEventParamDescriptor: nil,
|
24
|
-
launchIdentifier: nil
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# Find and return the dock application
|
29
|
-
#
|
30
|
-
# @return [AX::Application]
|
31
|
-
def dock
|
32
|
-
new 'com.apple.dock'
|
33
|
-
end
|
34
|
-
|
35
|
-
##
|
36
|
-
# Find and return the dock application
|
37
|
-
#
|
38
|
-
# @return [AX::Application]
|
39
|
-
def finder
|
40
|
-
new 'com.apple.finder'
|
41
|
-
end
|
42
|
-
|
43
|
-
##
|
44
|
-
# Find and return the notification center UI app
|
45
|
-
#
|
46
|
-
# Obviously, this will only work on OS X 10.8+
|
47
|
-
#
|
48
|
-
# @return [AX::Application]
|
49
|
-
def notification_center
|
50
|
-
new 'com.apple.notificationcenterui'
|
51
|
-
end
|
52
|
-
|
53
|
-
##
|
54
|
-
# Find and return the application which is frontmost
|
55
|
-
#
|
56
|
-
# This is often, but not necessarily, the same as the app that
|
57
|
-
# owns the menu bar.
|
58
|
-
#
|
59
|
-
# @return [AX::Application]
|
60
|
-
def frontmost_application
|
61
|
-
new NSWorkspace.sharedWorkspace.frontmostApplication
|
62
|
-
end
|
63
|
-
alias_method :frontmost_app, :frontmost_application
|
64
|
-
|
65
|
-
##
|
66
|
-
# Find and return the application which owns the menu bar
|
67
|
-
#
|
68
|
-
# This is often, but not necessarily, the same as the app that
|
69
|
-
# is frontmost.
|
70
|
-
#
|
71
|
-
# @return [AX::Application]
|
72
|
-
def menu_bar_owner
|
73
|
-
new NSWorkspace.sharedWorkspace.menuBarOwningApplication
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
14
|
##
|
78
|
-
# Standard way of creating a new application object
|
79
|
-
#
|
80
15
|
# You can initialize an application object with either the process
|
81
16
|
# identifier (pid) of the application, the name of the application,
|
82
17
|
# an `NSRunningApplication` instance for the application, or an
|
83
18
|
# accessibility (`AXUIElementRef`) token.
|
84
19
|
#
|
85
|
-
# Given a PID, we try to lookup the application and wrap it.
|
86
|
-
#
|
87
|
-
# Given an `NSRunningApplication` instance, we simply wrap it.
|
88
|
-
#
|
89
|
-
# Given a string we do some complicated magic to try and figure out if
|
90
|
-
# the string is a bundle identifier or the localized name of the
|
91
|
-
# application. Given a bundle identifier we try to launch the app if
|
92
|
-
# it is not already running, given a localized name we search the running
|
93
|
-
# applications for the app. We wrap what we get back if we get anything
|
94
|
-
# back.
|
95
|
-
#
|
96
|
-
# Note however, given a bundle identifier to launch the application our
|
97
|
-
# implementation is a bit of a hack; I've tried to register for
|
98
|
-
# notifications, launch synchronously, etc., but there is always a problem
|
99
|
-
# with accessibility not being ready right away, so we will poll the app
|
100
|
-
# to see when it is ready with a timeout of ~10 seconds.
|
101
|
-
#
|
102
|
-
# If this method fails to find an app then an exception will be raised.
|
103
|
-
#
|
104
|
-
# @example
|
105
|
-
#
|
106
|
-
# AX::Application.new 'com.apple.mail'
|
107
|
-
# AX::Application.new 'Mail'
|
108
|
-
# AX::Application.new 43567
|
109
|
-
#
|
110
20
|
# @param arg [Number,String,NSRunningApplication]
|
111
21
|
def initialize arg
|
112
22
|
case arg
|
@@ -114,29 +24,14 @@ class AX::Application < AX::Element
|
|
114
24
|
super Accessibility::Element.application_for arg
|
115
25
|
@app = NSRunningApplication.runningApplicationWithProcessIdentifier arg
|
116
26
|
when String
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
app
|
122
|
-
|
123
|
-
|
124
|
-
spin
|
125
|
-
NSWorkspace.sharedWorkspace.runningApplications.find { |app|
|
126
|
-
app.localizedName == arg
|
127
|
-
}
|
128
|
-
|
129
|
-
) || (
|
130
|
-
count ||= 0
|
131
|
-
if AX::Application.launch arg
|
132
|
-
spin 1
|
133
|
-
count += 1
|
134
|
-
raise "#{arg} failed to launch in time" if count == 10
|
135
|
-
else
|
136
|
-
raise "#{arg} is not a registered bundle identifier for the system"
|
137
|
-
end
|
27
|
+
@app =
|
28
|
+
NSRunningApplication.runningApplicationsWithBundleIdentifier(arg).first ||
|
29
|
+
(
|
30
|
+
spin_run_loop
|
31
|
+
NSWorkspace.sharedWorkspace.runningApplications.find { |app|
|
32
|
+
app.localizedName == arg
|
33
|
+
}
|
138
34
|
)
|
139
|
-
end
|
140
35
|
super Accessibility::Element.application_for @app.processIdentifier
|
141
36
|
when NSRunningApplication
|
142
37
|
super Accessibility::Element.application_for arg.processIdentifier
|
@@ -172,7 +67,7 @@ class AX::Application < AX::Element
|
|
172
67
|
# to the dynamic `#focused?` method, but might make more sense to use
|
173
68
|
# in some cases.
|
174
69
|
def active?
|
175
|
-
|
70
|
+
spin_run_loop
|
176
71
|
@app.active?
|
177
72
|
end
|
178
73
|
alias_method :focused, :active?
|
@@ -181,14 +76,14 @@ class AX::Application < AX::Element
|
|
181
76
|
##
|
182
77
|
# Ask the app whether or not it is hidden.
|
183
78
|
def hidden?
|
184
|
-
|
79
|
+
spin_run_loop
|
185
80
|
@app.hidden?
|
186
81
|
end
|
187
82
|
|
188
83
|
##
|
189
84
|
# Ask the app whether or not it is still running.
|
190
85
|
def terminated?
|
191
|
-
|
86
|
+
spin_run_loop
|
192
87
|
@app.terminated?
|
193
88
|
end
|
194
89
|
|
@@ -247,62 +142,23 @@ class AX::Application < AX::Element
|
|
247
142
|
|
248
143
|
# @group Actions
|
249
144
|
|
250
|
-
##
|
251
|
-
# @note This is often async and may return before the action is completed
|
252
|
-
#
|
253
|
-
# Ask the app to quit
|
254
|
-
#
|
255
|
-
# @return [Boolean]
|
256
|
-
def terminate
|
257
|
-
perform :terminate
|
258
|
-
end
|
259
|
-
|
260
|
-
##
|
261
|
-
# @note This is often async and may return before the action is completed
|
262
|
-
#
|
263
|
-
# Force the app to quit
|
264
|
-
#
|
265
|
-
# @return [Boolean]
|
266
|
-
def terminate!
|
267
|
-
perform :force_terminate
|
268
|
-
end
|
269
|
-
|
270
|
-
##
|
271
|
-
# @note This is often async and may return before the action is completed
|
272
|
-
#
|
273
|
-
# Ask the app to hide itself
|
274
|
-
#
|
275
|
-
# @return [Boolean]
|
276
|
-
def hide
|
277
|
-
perform :hide
|
278
|
-
end
|
279
|
-
|
280
|
-
##
|
281
|
-
# @note This is often async and may return before the action is completed
|
282
|
-
#
|
283
|
-
# As the app to unhide itself and bring to front
|
284
|
-
#
|
285
|
-
# @return [Boolean]
|
286
|
-
def unhide
|
287
|
-
perform :unhide
|
288
|
-
end
|
289
145
|
|
290
146
|
# (see AX::Element#perform)
|
291
147
|
def perform name
|
292
148
|
case name
|
293
149
|
when :terminate
|
294
150
|
return true if terminated?
|
295
|
-
@app.terminate;
|
151
|
+
@app.terminate; sleep 0.2; terminated?
|
296
152
|
when :force_terminate
|
297
153
|
return true if terminated?
|
298
|
-
@app.forceTerminate;
|
154
|
+
@app.forceTerminate; sleep 0.2; terminated?
|
299
155
|
when :hide
|
300
156
|
return true if hidden?
|
301
|
-
@app.hide;
|
157
|
+
@app.hide; sleep 0.2; hidden?
|
302
158
|
when :unhide
|
303
159
|
return true if active?
|
304
|
-
@app.activateWithOptions(
|
305
|
-
|
160
|
+
@app.activateWithOptions(NSApplicationActivateIgnoringOtherApps)
|
161
|
+
sleep 0.2; active?
|
306
162
|
else
|
307
163
|
super
|
308
164
|
end
|
@@ -432,6 +288,11 @@ class AX::Application < AX::Element
|
|
432
288
|
|
433
289
|
private
|
434
290
|
|
291
|
+
# @return [nil]
|
292
|
+
def spin_run_loop
|
293
|
+
NSRunLoop.currentRunLoop.runUntilDate Time.now
|
294
|
+
end
|
295
|
+
|
435
296
|
# @return [NSBundle]
|
436
297
|
def bundle
|
437
298
|
@bundle ||= NSBundle.bundleWithURL @app.bundleURL
|
data/lib/ax/element.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
require 'active_support/core_ext/object/blank'
|
4
3
|
require 'accessibility/core'
|
5
4
|
require 'accessibility/factory'
|
6
5
|
require 'accessibility/translator'
|
7
6
|
require 'accessibility/enumerators'
|
8
7
|
require 'accessibility/qualifier'
|
9
8
|
require 'accessibility/errors'
|
10
|
-
require 'accessibility/
|
9
|
+
require 'accessibility/pp_inspector'
|
11
10
|
|
12
11
|
|
13
12
|
##
|
@@ -20,7 +19,7 @@ require 'accessibility/pretty_printer'
|
|
20
19
|
# This abstract base class provides generic functionality that all
|
21
20
|
# accessibility objects require.
|
22
21
|
class AX::Element
|
23
|
-
include Accessibility::
|
22
|
+
include Accessibility::PPInspector
|
24
23
|
|
25
24
|
# @param ref [AXUIElementRef]
|
26
25
|
def initialize ref
|
@@ -55,7 +54,7 @@ class AX::Element
|
|
55
54
|
#
|
56
55
|
# @param attr [#to_sym]
|
57
56
|
def attribute attr
|
58
|
-
@ref.attribute
|
57
|
+
@ref.attribute TRANSLATOR.cocoaify(attr)
|
59
58
|
end
|
60
59
|
|
61
60
|
##
|
@@ -66,7 +65,7 @@ class AX::Element
|
|
66
65
|
#
|
67
66
|
# @return [String]
|
68
67
|
def description
|
69
|
-
attribute
|
68
|
+
attribute :description
|
70
69
|
end
|
71
70
|
|
72
71
|
##
|
@@ -74,12 +73,12 @@ class AX::Element
|
|
74
73
|
#
|
75
74
|
# @return [Array<AX::Element>]
|
76
75
|
def children
|
77
|
-
|
76
|
+
attribute :children
|
78
77
|
end
|
79
78
|
|
80
79
|
##
|
81
80
|
# Get a list of elements, starting with the receiver and riding
|
82
|
-
# the hierarchy up to the top level object (i.e. the {AX::Application})
|
81
|
+
# the hierarchy up to the top level object (i.e. the {AX::Application}).
|
83
82
|
#
|
84
83
|
# @example
|
85
84
|
#
|
@@ -88,16 +87,15 @@ class AX::Element
|
|
88
87
|
# # => [#<AX::ApplicationDockItem...>, #<AX::List...>, #<AX::Application...>]
|
89
88
|
#
|
90
89
|
# @return [Array<AX::Element>]
|
91
|
-
def ancestry elements
|
92
|
-
elements =
|
90
|
+
def ancestry *elements
|
91
|
+
elements = [self] if elements.empty?
|
93
92
|
element = elements.last
|
94
93
|
if element.attributes.include? :parent
|
95
|
-
ancestry(elements << element.
|
94
|
+
ancestry(elements << element.parent)
|
96
95
|
else
|
97
96
|
elements
|
98
97
|
end
|
99
98
|
end
|
100
|
-
alias_method :lineage, :ancestry
|
101
99
|
|
102
100
|
##
|
103
101
|
# Get the process identifier for the application that the element
|
@@ -187,8 +185,8 @@ class AX::Element
|
|
187
185
|
# @param attr [#to_sym]
|
188
186
|
# @param param [Object]
|
189
187
|
def parameterized_attribute attr, param
|
190
|
-
param = param.relative_to(@ref.value.size) if
|
191
|
-
@ref.parameterized_attribute
|
188
|
+
param = param.relative_to(@ref.value.size) if value.kind_of? Range
|
189
|
+
@ref.parameterized_attribute TRANSLATOR.cocoaify(attr), param
|
192
190
|
end
|
193
191
|
|
194
192
|
|
@@ -264,8 +262,6 @@ class AX::Element
|
|
264
262
|
# As the opposite of {#search}, this also takes filters, and can
|
265
263
|
# be used to find a specific ancestor for the current element.
|
266
264
|
#
|
267
|
-
# Returns `nil` if no ancestor is found.
|
268
|
-
#
|
269
265
|
# @example
|
270
266
|
#
|
271
267
|
# button.ancestor :window # => #<AX::StandardWindow>
|
@@ -274,13 +270,12 @@ class AX::Element
|
|
274
270
|
# @param kind [#to_s]
|
275
271
|
# @param filters [Hash{Symbol=>Object}]
|
276
272
|
# @yield Optional block used for search filtering
|
277
|
-
# @return [AX::Element
|
273
|
+
# @return [AX::Element]
|
278
274
|
def ancestor kind, filters = {}, &block
|
279
275
|
qualifier = Accessibility::Qualifier.new(kind, filters, &block)
|
280
|
-
element =
|
276
|
+
element = attribute :parent
|
281
277
|
until qualifier.qualifies? element
|
282
278
|
element = element.attribute :parent
|
283
|
-
return nil unless element
|
284
279
|
end
|
285
280
|
element
|
286
281
|
end
|
@@ -342,7 +337,7 @@ class AX::Element
|
|
342
337
|
return attribute(method)
|
343
338
|
|
344
339
|
elsif @ref.parameterized_attributes.include? key
|
345
|
-
return
|
340
|
+
return paramaterized_attribute(method, args.first)
|
346
341
|
|
347
342
|
elsif @ref.attributes.include? KAXChildrenAttribute
|
348
343
|
if (result = search(method, *args, &block)).blank?
|
@@ -365,7 +360,7 @@ class AX::Element
|
|
365
360
|
#
|
366
361
|
# @return [String]
|
367
362
|
def inspect
|
368
|
-
msg = "#<#{self.class}" << pp_identifier
|
363
|
+
msg = "#<#{self.class}" << pp_identifier
|
369
364
|
msg << pp_position if attributes.include? :position
|
370
365
|
msg << pp_children if attributes.include? :children
|
371
366
|
msg << pp_checkbox(:enabled) if attributes.include? :enabled
|
@@ -435,7 +430,7 @@ class AX::Element
|
|
435
430
|
def bounds
|
436
431
|
CGRect.new(attribute(:position), attribute(:size))
|
437
432
|
end
|
438
|
-
alias_method :
|
433
|
+
alias_method :rect, :bounds
|
439
434
|
|
440
435
|
##
|
441
436
|
# Get the application object for the element.
|
@@ -461,17 +456,11 @@ class AX::Element
|
|
461
456
|
@ref.invalid?
|
462
457
|
end
|
463
458
|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
super.concat(attributes).concat(parameterized_attributes)
|
470
|
-
end
|
471
|
-
else
|
472
|
-
def methods include_super = true
|
473
|
-
super.concat(attributes).concat(parameterized_attributes)
|
474
|
-
end
|
459
|
+
##
|
460
|
+
# Like {#respond_to?}, this is overriden to include attribute methods.
|
461
|
+
# Though, it does include dynamic predicate methods at the moment.
|
462
|
+
def methods include_super = true, include_objc_super = false
|
463
|
+
super.concat(attributes).concat(parameterized_attributes)
|
475
464
|
end
|
476
465
|
|
477
466
|
##
|
@@ -496,3 +485,24 @@ class AX::Element
|
|
496
485
|
TRANSLATOR = Accessibility::Translator.instance
|
497
486
|
|
498
487
|
end
|
488
|
+
|
489
|
+
|
490
|
+
# Extensions so checking `#blank?` on search result "just works".
|
491
|
+
class NSArray
|
492
|
+
# (see NilClass#blank?)
|
493
|
+
alias_method :blank?, :empty?
|
494
|
+
end
|
495
|
+
|
496
|
+
# Extensions so checking `#blank?` on search result "just works".
|
497
|
+
class NilClass
|
498
|
+
##
|
499
|
+
# Whether or not the object is "blank". The concept of blankness
|
500
|
+
# borrowed from `Active Support` and is true if the object is falsey
|
501
|
+
# or `#empty?`.
|
502
|
+
#
|
503
|
+
# This method is used by implicit searching in AXElements to
|
504
|
+
# determine if searches yielded responses.
|
505
|
+
def blank?
|
506
|
+
true
|
507
|
+
end
|
508
|
+
end
|