AXElements 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.yardopts +4 -0
  2. data/History.markdown +41 -0
  3. data/README.markdown +59 -62
  4. data/Rakefile +1 -1
  5. data/ext/accessibility/key_coder/extconf.rb +1 -1
  6. data/ext/accessibility/key_coder/key_coder.c +8 -5
  7. data/lib/accessibility/dsl.rb +261 -87
  8. data/lib/accessibility/enumerators.rb +14 -11
  9. data/lib/accessibility/errors.rb +4 -3
  10. data/lib/accessibility/factory.rb +159 -108
  11. data/lib/accessibility/graph.rb +13 -9
  12. data/lib/accessibility/{pp_inspector.rb → pretty_printer.rb} +4 -5
  13. data/lib/accessibility/qualifier.rb +23 -13
  14. data/lib/accessibility/string.rb +4 -4
  15. data/lib/accessibility/system_info.rb +230 -0
  16. data/lib/accessibility/translator.rb +38 -28
  17. data/lib/accessibility/version.rb +24 -2
  18. data/lib/accessibility.rb +25 -8
  19. data/lib/ax/application.rb +207 -77
  20. data/lib/ax/element.rb +62 -65
  21. data/lib/ax/menu.rb +5 -1
  22. data/lib/ax/row.rb +1 -1
  23. data/lib/ax/scroll_area.rb +7 -6
  24. data/lib/ax/systemwide.rb +38 -5
  25. data/lib/ax_elements/active_support_selections.rb +10 -0
  26. data/lib/ax_elements/mri.rb +57 -0
  27. data/lib/ax_elements/nsarray_compat.rb +97 -17
  28. data/lib/ax_elements.rb +9 -1
  29. data/rakelib/gem.rake +11 -11
  30. data/rakelib/test.rake +0 -9
  31. data/test/helper.rb +10 -18
  32. data/test/integration/accessibility/test_dsl.rb +52 -42
  33. data/test/integration/accessibility/test_enumerators.rb +0 -1
  34. data/test/integration/accessibility/test_graph.rb +1 -0
  35. data/test/integration/accessibility/test_qualifier.rb +2 -2
  36. data/test/integration/ax/test_application.rb +9 -2
  37. data/test/integration/ax/test_element.rb +41 -1
  38. data/test/sanity/accessibility/test_factory.rb +23 -56
  39. data/test/sanity/accessibility/{test_pp_inspector.rb → test_pretty_printer.rb} +9 -9
  40. data/test/sanity/accessibility/test_translator.rb +2 -5
  41. data/test/sanity/accessibility/test_version.rb +15 -0
  42. data/test/sanity/ax/test_application.rb +17 -2
  43. data/test/sanity/ax/test_element.rb +2 -2
  44. data/test/sanity/ax_elements/test_nsobject_inspect.rb +4 -2
  45. data/test/sanity/test_ax_elements.rb +1 -0
  46. metadata +69 -39
  47. data/lib/accessibility/core.rb +0 -973
  48. data/lib/accessibility/highlighter.rb +0 -86
  49. data/lib/ax_elements/vendor/inflection_data.rb +0 -66
  50. data/lib/ax_elements/vendor/inflections.rb +0 -172
  51. data/lib/ax_elements/vendor/inflector.rb +0 -306
  52. data/lib/minitest/ax_elements.rb +0 -175
  53. data/lib/mouse.rb +0 -223
  54. data/lib/rspec/expectations/ax_elements.rb +0 -234
  55. data/test/integration/accessibility/test_core.rb +0 -18
  56. data/test/integration/minitest/test_ax_elements.rb +0 -89
  57. data/test/integration/rspec/expectations/test_ax_elements.rb +0 -102
  58. data/test/sanity/accessibility/test_core.rb +0 -561
  59. data/test/sanity/accessibility/test_highlighter.rb +0 -56
  60. data/test/sanity/minitest/test_ax_elements.rb +0 -17
  61. data/test/sanity/rspec/expectations/test_ax_elements.rb +0 -15
  62. data/test/sanity/test_mouse.rb +0 -19
@@ -1,175 +0,0 @@
1
- require 'ax/element'
2
- require 'accessibility/qualifier'
3
- require 'accessibility/dsl'
4
-
5
- ##
6
- # AXElements assertions for MiniTest.
7
- # [Learn more about minitest.](https://github.com/seattlerb/minitest)
8
- class MiniTest::Assertions
9
-
10
- ##
11
- # Test that an element has a specific child. For example, test
12
- # that a table has a row with certain contents. You can pass any
13
- # filters that you normally would during a search, including a block.
14
- #
15
- # @example
16
- #
17
- # assert_has_child table, :row, static_text: { value: 'Mark' }
18
- #
19
- # @param [AX::Element]
20
- # @param [#to_s]
21
- # @param [Hash]
22
- # @return [AX::Element]
23
- def assert_has_child parent, kind, filters = {}, &block
24
- msg = message {
25
- child = ax_search_id kind, filters, block
26
- "Expected #{parent.inspect} to have #{child} as a child"
27
- }
28
- result = ax_check_children parent, kind, filters, block
29
- refute result.blank?, msg
30
- result
31
- end
32
-
33
- ##
34
- # Test that an element has a specifc descendent. For example, test
35
- # that a window contains a specific label. You can pass any filters
36
- # that you normally would during a search, including a block.
37
- #
38
- # @example
39
- #
40
- # assert_has_descendent window, :static_text, value: /Cake/
41
- #
42
- # @param [AX::Element]
43
- # @param [#to_s]
44
- # @param [Hash]
45
- # @return [AX::Element]
46
- def assert_has_descendent ancestor, kind, filters = {}, &block
47
- msg = message {
48
- descendent = ax_search_id kind, filters, block
49
- "Expected #{ancestor.inspect} to have #{descendent} as a descendent"
50
- }
51
- result = ax_check_descendent ancestor, kind, filters, block
52
- refute result.blank?, msg
53
- result
54
- end
55
- alias_method :assert_has_descendant, :assert_has_descendent
56
-
57
- ##
58
- # Test that an element will have a child/descendent soon. This method
59
- # will block until the element is found or a timeout occurs.
60
- #
61
- # This is a minitest front end to using {DSL#wait_for}, so any
62
- # parameters you would normally pass to that method will work here.
63
- # This also means that you must include either a `parent` key or an
64
- # `ancestor` key as one of the filters.
65
- #
66
- # @param [#to_s]
67
- # @param [Hash]
68
- # @yield An optional block to be used in the search qualifier
69
- def assert_shortly_has kind, filters = {}, &block
70
- # need to know if parent/ancestor now because wait_for eats some keys
71
- (ancest = filters[:ancestor]) || (parent = filters[:parent])
72
- msg = message {
73
- descend = ax_search_id kind, filters, block
74
- if ancest
75
- "Expected #{ancest.inspect} to have descendent #{descend} before a timeout occurred"
76
- else
77
- "Expected #{parent.inspect} to have child #{descend} before a timeout occurred"
78
- end
79
- }
80
- result = wait_for kind, filters, &block
81
- refute result.blank?, msg
82
- result
83
- end
84
-
85
- ##
86
- # Test that an element _does not_ have a specific child. For example,
87
- # test that a row is no longer in a table. You can pass any filters
88
- # that you normally would during a search, including a block.
89
- #
90
- # @example
91
- #
92
- # refute_has_child table, :row, id: 'MyRow'
93
- #
94
- # @param [AX::Element]
95
- # @param [#to_s]
96
- # @param [Hash]
97
- # @return [nil]
98
- def refute_has_child parent, kind, filters = {}, &block
99
- result = ax_check_children parent, kind, filters, block
100
- msg = message {
101
- "Expected #{parent.inspect} NOT to have #{result} as a child"
102
- }
103
- assert result.blank?, msg
104
- result
105
- end
106
-
107
- ##
108
- # Test that an element _does not_ have a specific descendent. For
109
- # example, test that a window does not contain a spinning progress
110
- # indicator anymore.
111
- #
112
- # @example
113
- #
114
- # refute_has_descendent window, :busy_indicator
115
- #
116
- # @param [AX::Element]
117
- # @param [#to_s]
118
- # @param [Hash]
119
- # @return [nil,Array()]
120
- def refute_has_descendent ancestor, kind, filters = {}, &block
121
- result = ax_check_descendent ancestor, kind, filters, block
122
- msg = message {
123
- "Expected #{ancestor.inspect} NOT to have #{result} as a descendent"
124
- }
125
- assert result.blank?, msg
126
- result
127
- end
128
- alias_method :refute_has_descendant, :refute_has_descendent
129
-
130
- ##
131
- # @todo Does having this assertion make sense? I've only added it
132
- # for the time being because OCD demands it.
133
- #
134
- # Test that an element will NOT have a child/descendent soon. This
135
- # method will block until the element is found or a timeout occurs.
136
- #
137
- # This is a minitest front end to using {DSL#wait_for}, so any
138
- # parameters you would normally pass to that method will work here.
139
- # This also means that you must include either a `parent` key or an
140
- # `ancestor` key as one of the filters.
141
- #
142
- # @param [#to_s]
143
- # @param [Hash]
144
- # @yield An optional block to be used in the search qualifier
145
- def refute_shortly_has kind, filters = {}, &block
146
- result = wait_for kind, filters, &block
147
- msg = message {
148
- if ancest = filters[:ancestor]
149
- "Expected #{ancest.inspect} NOT to have #{result.inspect} as a descendent"
150
- else
151
- parent = filters[:parent]
152
- "Expected #{parent.inspect} NOT to have #{result.inspect} as a child"
153
- end
154
- }
155
- assert result.blank?, msg
156
- result
157
- end
158
-
159
-
160
- private
161
-
162
- def ax_search_id kind, filters, block
163
- Accessibility::Qualifier.new(kind, filters, &block).describe
164
- end
165
-
166
- def ax_check_children parent, kind, filters, block
167
- q = Accessibility::Qualifier.new(kind, filters, &block)
168
- parent.children.find { |x| q.qualifies? x }
169
- end
170
-
171
- def ax_check_descendent ancestor, kind, filters, block
172
- ancestor.search(kind, filters, &block)
173
- end
174
-
175
- end
data/lib/mouse.rb DELETED
@@ -1,223 +0,0 @@
1
- framework 'ApplicationServices'
2
-
3
- ##
4
- # This is a first attempt at writing a wrapper around the CoreGraphics event
5
- # taps API provided by OS X. The module provides a simple Ruby interface to
6
- # performing mouse interactions such as moving and clicking.
7
- #
8
- # [Reference](http://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html).
9
- #
10
- # A rewrite is in the works, but in the mean time this code base still works
11
- # despite its warts.
12
- module Mouse
13
- extend self
14
-
15
- ##
16
- # Number of animation steps per second.
17
- #
18
- # @return [Number]
19
- FPS = 120
20
-
21
- ##
22
- # @note We keep the number as a rational to try and avoid rounding
23
- # error introduced by the floats, especially MacRuby floats.
24
- #
25
- # Smallest unit of time allowed for an animation step.
26
- #
27
- # @return [Number]
28
- QUANTUM = Rational(1, FPS)
29
-
30
- ##
31
- # Available constants for the type of units to use when scrolling.
32
- #
33
- # @return [Hash{Symbol=>Fixnum}]
34
- UNIT = {
35
- line: KCGScrollEventUnitLine,
36
- pixel: KCGScrollEventUnitPixel
37
- }
38
-
39
- ##
40
- # The coordinates of the mouse using the flipped coordinate system
41
- # (origin in top left).
42
- #
43
- # @return [CGPoint]
44
- def current_position
45
- CGEventGetLocation(CGEventCreate(nil))
46
- end
47
-
48
- ##
49
- # Move the mouse from the current position to the given point.
50
- #
51
- # @param [CGPoint]
52
- # @param [Float] duration animation duration, in seconds
53
- def move_to point, duration = 0.2
54
- animate KCGEventMouseMoved, KCGMouseButtonLeft, current_position, point, duration
55
- end
56
-
57
- ##
58
- # Click and drag from the current position to the given point.
59
- #
60
- # @param [CGPoint]
61
- # @param [Float] duration animation duration, in seconds
62
- def drag_to point, duration = 0.2
63
- post new_event(KCGEventLeftMouseDown, current_position, KCGMouseButtonLeft)
64
-
65
- animate KCGEventLeftMouseDragged, KCGMouseButtonLeft, current_position, point, duration
66
-
67
- post new_event(KCGEventLeftMouseUp, current_position, KCGMouseButtonLeft)
68
- end
69
-
70
- ##
71
- # @todo Need to double check to see if I introduce any inaccuracies.
72
- #
73
- # Scroll at the current position the given amount of units.
74
- #
75
- # Scrolling too much or too little in a period of time will cause the
76
- # animation to look weird, possibly causing the app to mess things up.
77
- #
78
- # @param [Fixnum] amount number of units to scroll; positive to scroll
79
- # up or negative to scroll down
80
- # @param [Float] duration animation duration, in seconds
81
- # @param [Symbol] units `:line` scrolls by line, `:pixel` scrolls by pixel
82
- def scroll amount, duration = 0.2, units = :line
83
- units = UNIT[units] || raise(ArgumentError, "#{units} is not a valid unit")
84
- steps = (FPS * duration).round
85
- current = 0.0
86
- steps.times do |step|
87
- done = (step+1).to_f / steps
88
- scroll = ((done - current)*amount).floor
89
- post new_scroll_event(units, 1, scroll)
90
- sleep QUANTUM
91
- current += scroll.to_f / amount
92
- end
93
- end
94
-
95
- ##
96
- # Perform a down click. You should follow this up with a call to
97
- # {#click_up} to finish the click.
98
- #
99
- # @param [CGPoint]
100
- def click_down point = current_position, duration = 12
101
- event = new_event KCGEventLeftMouseDown, point, KCGMouseButtonLeft
102
- post event
103
- sleep QUANTUM*duration
104
- end
105
-
106
- ##
107
- # Perform an up click. This should only be called after a call to
108
- # {#click_down} to finish the click event.
109
- #
110
- # @param [CGPoint]
111
- def click_up point = current_position
112
- event = new_event KCGEventLeftMouseUp, point, KCGMouseButtonLeft
113
- post event
114
- end
115
-
116
- ##
117
- # Standard secondary click. Default position is the current position.
118
- #
119
- # @param [CGPoint]
120
- def secondary_click point = current_position, duration = 12
121
- event = new_event KCGEventRightMouseDown, point, KCGMouseButtonRight
122
- post event
123
- sleep QUANTUM*duration
124
- set_type event, KCGEventRightMouseUp
125
- post event
126
- end
127
- alias_method :right_click, :secondary_click
128
-
129
- ##
130
- # A standard double click. Defaults to clicking at the current position.
131
- #
132
- # @param [CGPoint]
133
- def double_click point = current_position
134
- event = new_event KCGEventLeftMouseDown, point, KCGMouseButtonLeft
135
- post event
136
- set_type event, KCGEventLeftMouseUp
137
- post event
138
-
139
- CGEventSetIntegerValueField(event, KCGMouseEventClickState, 2)
140
- set_type event, KCGEventLeftMouseDown
141
- post event
142
- set_type event, KCGEventLeftMouseUp
143
- post event
144
- end
145
-
146
- ##
147
- # Click with an arbitrary mouse button, using numbers to represent
148
- # the mouse button. At the time of writing, the documented values are:
149
- #
150
- # - KCGMouseButtonLeft = 0
151
- # - KCGMouseButtonRight = 1
152
- # - KCGMouseButtonCenter = 2
153
- #
154
- # And the rest are not documented! Though they should be easy enough
155
- # to figure out. See the `CGMouseButton` enum in the reference
156
- # documentation for the most up to date list.
157
- #
158
- # @param [CGPoint]
159
- # @param [Number]
160
- def arbitrary_click point = current_position, button = KCGMouseButtonCenter, duration = 12
161
- event = new_event KCGEventOtherMouseDown, point, button
162
- post event
163
- sleep QUANTUM*duration
164
- set_type event, KCGEventOtherMouseUp
165
- post event
166
- end
167
- alias_method :other_click, :arbitrary_click
168
-
169
-
170
- private
171
-
172
- ##
173
- # Executes a mouse movement animation. It can be a simple cursor
174
- # move or a drag depending on what is passed to `type`.
175
- def animate type, button, from, to, duration
176
- current = current_position
177
- xstep = (to.x - current.x) / (FPS * duration)
178
- ystep = (to.y - current.y) / (FPS * duration)
179
- start = NSDate.date
180
-
181
- until close_enough?(current, to)
182
- remaining = to.x - current.x
183
- current.x += xstep.abs > remaining.abs ? remaining : xstep
184
-
185
- remaining = to.y - current.y
186
- current.y += ystep.abs > remaining.abs ? remaining : ystep
187
-
188
- post new_event(type, current, button)
189
-
190
- sleep QUANTUM
191
- break if NSDate.date.timeIntervalSinceDate(start) > 5.0
192
- current = current_position
193
- end
194
- end
195
-
196
- def close_enough? current, target
197
- x = current.x - target.x
198
- y = current.y - target.y
199
- delta = Math.sqrt((x**2) + (y**2))
200
- delta <= 1.0
201
- end
202
-
203
- def new_event event, position, button
204
- CGEventCreateMouseEvent(nil, event, position, button)
205
- end
206
-
207
- # @param [Fixnum] wheel which scroll wheel to use (value between 1-3)
208
- def new_scroll_event units, wheel, amount
209
- CGEventCreateScrollWheelEvent(nil, units, wheel, amount)
210
- end
211
-
212
- def post event
213
- CGEventPost(KCGHIDEventTap, event)
214
- end
215
-
216
- ##
217
- # Change the event type for an instance of an event. This is how you would
218
- # reuse a specific event. In most cases, reusing events is a necessity.
219
- def set_type event, state
220
- CGEventSetType(event, state)
221
- end
222
-
223
- end
@@ -1,234 +0,0 @@
1
- require 'accessibility/dsl'
2
- require 'accessibility/qualifier'
3
- require 'ax/element'
4
-
5
- module Accessibility
6
-
7
- ##
8
- # @abstract
9
- #
10
- # Base class for RSpec matchers used with AXElements.
11
- class AbstractMatcher
12
-
13
- # @return [#to_s]
14
- attr_reader :kind
15
-
16
- # @return [Hash{Symbol=>Object}]
17
- attr_reader :filters
18
-
19
- # @return [Proc]
20
- attr_reader :block
21
-
22
- # @param [#to_s]
23
- # @param [Hash]
24
- # @yield
25
- def initialize kind, filters, &block
26
- @kind, @filters, @block = kind, filters, block
27
- end
28
-
29
- # @param [AX::Element]
30
- def does_not_match? element
31
- !matches?(element)
32
- end
33
-
34
-
35
- private
36
-
37
- # @return [Accessibility::Qualifier]
38
- def qualifier
39
- @qualifier ||= Accessibility::Qualifier.new(kind, filters, &block)
40
- end
41
- end
42
-
43
- ##
44
- # Custom matcher for RSpec to check if an element has the specified
45
- # child element.
46
- class HasChildMatcher < AbstractMatcher
47
- # @param [AX::Element]
48
- def matches? parent
49
- @parent = parent
50
- @result = parent.children.find { |x| qualifier.qualifies? x }
51
- !@result.blank?
52
- end
53
-
54
- # @return [String]
55
- def failure_message_for_should
56
- "Expected #@parent to have child #{qualifier.describe}"
57
- end
58
-
59
- # @return [String]
60
- def failure_message_for_should_not
61
- "Expected #@parent to NOT have child #@result"
62
- end
63
-
64
- # @return [String]
65
- def description
66
- "should have a child that matches #{qualifier.describe}"
67
- end
68
- end
69
-
70
- ##
71
- # Custom matcher for RSpec to check if an element has the specified
72
- # descendent element.
73
- class HasDescendentMatcher < AbstractMatcher
74
- # @param [AX::Element]
75
- def matches? ancestor
76
- @ancestor = ancestor
77
- @result = ancestor.search(kind, filters, &block)
78
- !@result.blank?
79
- end
80
-
81
- # @return [String]
82
- def failure_message_for_should
83
- "Expected #@ancestor to have descendent #{qualifier.describe}"
84
- end
85
-
86
- # @return [String]
87
- def failure_message_for_should_not
88
- "Expected #@ancestor to NOT have descendent #@result"
89
- end
90
-
91
- # @return [String]
92
- def description
93
- "should have a descendent matching #{qualifier.describe}"
94
- end
95
- end
96
-
97
- ##
98
- # Custom matcher for RSpec to check if an element has the specified
99
- # child element within a grace period. Used for testing things
100
- # after an asynchronous action is performed.
101
- class HasChildShortlyMatcher < AbstractMatcher
102
- include DSL
103
-
104
- # @param [AX::Element]
105
- def matches? parent
106
- @filters[:parent] = @parent = parent
107
- @result = wait_for kind, filters, &block
108
- !@result.blank?
109
- end
110
-
111
- # @return [String]
112
- def failure_message_for_should
113
- "Expected #@parent to have child #{qualifier.describe} before a timeout occurred"
114
- end
115
-
116
- # @return [String]
117
- def failure_message_for_should_not
118
- "Expected #@parent to NOT have child #@result before a timeout occurred"
119
- end
120
-
121
- # @return [String]
122
- def description
123
- "should have a child that matches #{qualifier.describe} before a timeout occurs"
124
- end
125
- end
126
-
127
- ##
128
- # Custom matcher for RSpec to check if an element has the specified
129
- # descendent element within a grace period. Used for testing things
130
- # after an asynchronous action is performed.
131
- class HasDescendentShortlyMatcher < AbstractMatcher
132
- include DSL
133
-
134
- # @param [AX::Element]
135
- def matches? ancestor
136
- @filters[:ancestor] = @ancestor = ancestor
137
- @result = wait_for kind, filters, &block
138
- !@result.blank?
139
- end
140
-
141
- # @return [String]
142
- def failure_message_for_should
143
- "Expected #@ancestor to have descendent #{qualifier.describe} before a timeout occurred"
144
- end
145
-
146
- # @return [String]
147
- def failure_message_for_should_not
148
- "Expected #@ancestor to NOT have descendent #@result before a timeout occurred"
149
- end
150
-
151
- # @return [String]
152
- def description
153
- "should have a descendent matching #{qualifier.describe} before a timeout occurs"
154
- end
155
- end
156
- end
157
-
158
-
159
- ##
160
- # Assert that the receiving element has the specified child element. You
161
- # can use any filters you would normally use in a search, including
162
- # a block.
163
- #
164
- # @example
165
- #
166
- # window.toolbar.should have_child(:search_field)
167
- # table.should have_child(:row, static_text: { value: /42/ })
168
- #
169
- # search_field.should_not have_child(:busy_indicator)
170
- #
171
- # @param [#to_s]
172
- # @param [Hash]
173
- # @yield An optional block to be used as part of the search qualifier
174
- def have_child kind, filters = {}, &block
175
- Accessibility::HasChildMatcher.new kind, filters, &block
176
- end
177
-
178
- ##
179
- # Assert that the given element has the specified descendent. You can
180
- # pass any parameters you normally would use during a search,
181
- # including a block.
182
- #
183
- # @example
184
- #
185
- # app.main_window.should have_descendent(:button, title: 'Press Me')
186
- #
187
- # row.should_not have_descendent(:check_box)
188
- #
189
- # @param [#to_s]
190
- # @param [Hash]
191
- # @yield An optional block to be used as part of the search qualifier
192
- def have_descendent kind, filters = {}, &block
193
- Accessibility::HasDescendentMatcher.new kind, filters, &block
194
- end
195
- alias :have_descendant :have_descendent
196
-
197
- ##
198
- # Assert that the given element has the specified child soon. This
199
- # method will block until the child is found or a timeout occurs. You
200
- # can pass any parameters you normally would use during a search,
201
- # including a block.
202
- #
203
- # @example
204
- #
205
- # app.main_window.should shortly_have_child(:row, static_text: { value: 'Cake' })
206
- #
207
- # row.should_not shortly_have_child(:check_box)
208
- #
209
- # @param [#to_s]
210
- # @param [Hash]
211
- # @yield An optional block to be used as part of the search qualifier
212
- def shortly_have_child kind, filters = {}, &block
213
- Accessibility::HasChildShortlyMatcher.new(kind, filters, &block)
214
- end
215
-
216
- ##
217
- # Assert that the given element has the specified descendent soon. This
218
- # method will block until the descendent is found or a timeout occurs.
219
- # You can pass any parameters you normally would use during a search,
220
- # including a block.
221
- #
222
- # @example
223
- #
224
- # app.main_window.should shortly_have_child(:row, static_text: { value: 'Cake' })
225
- #
226
- # row.should_not shortly_have_child(:check_box)
227
- #
228
- # @param [#to_s]
229
- # @param [Hash]
230
- # @yield An optional block to be used as part of the search qualifier
231
- def shortly_have_descendent kind, filters = {}, &block
232
- Accessibility::HasDescendentShortlyMatcher.new kind, filters, &block
233
- end
234
- alias :shortly_have_descendant :shortly_have_descendent
@@ -1,18 +0,0 @@
1
- require 'test/integration/helper'
2
-
3
- class TestAccessibilityCore < MiniTest::Unit::TestCase
4
-
5
- # this assumes that radar://10040865 is not fixed
6
- # once it is fixed, this case becomes less of an
7
- # issue anyways
8
- def test_nil_children_returns_empty_array
9
- app = app_with_name 'AXElementsTester'
10
- menu = app.menu_bar_item(title: 'Help')
11
- press menu
12
-
13
- assert_empty menu.search_field.children
14
- ensure
15
- cancel menu if menu
16
- end
17
-
18
- end