AXElements 0.7.8 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -10
- data/README.markdown +7 -14
- data/ext/accessibility/key_coder/key_coder.c +7 -0
- data/lib/AXElements.rb +0 -2
- data/lib/accessibility/core.rb +180 -123
- data/lib/accessibility/dsl.rb +310 -191
- data/lib/accessibility/enumerators.rb +9 -8
- data/lib/accessibility/errors.rb +7 -8
- data/lib/accessibility/factory.rb +16 -9
- data/lib/accessibility/graph.rb +68 -22
- data/lib/accessibility/highlighter.rb +86 -0
- data/lib/accessibility/pp_inspector.rb +4 -4
- data/lib/accessibility/qualifier.rb +11 -9
- data/lib/accessibility/string.rb +12 -4
- data/lib/accessibility/translator.rb +19 -10
- data/lib/accessibility/version.rb +3 -1
- data/lib/accessibility.rb +42 -17
- data/lib/ax/application.rb +90 -30
- data/lib/ax/button.rb +5 -2
- data/lib/ax/element.rb +133 -149
- data/lib/ax/pop_up_button.rb +12 -0
- data/lib/ax/radio_button.rb +5 -2
- data/lib/ax/row.rb +2 -2
- data/lib/ax/static_text.rb +5 -2
- data/lib/ax/systemwide.rb +24 -12
- data/lib/ax_elements/awesome_print.rb +13 -0
- data/lib/ax_elements/exception_workaround.rb +5 -0
- data/lib/ax_elements/nsarray_compat.rb +1 -0
- data/lib/ax_elements.rb +2 -1
- data/lib/minitest/ax_elements.rb +60 -4
- data/lib/mouse.rb +47 -20
- data/lib/rspec/expectations/ax_elements.rb +180 -88
- data/rakelib/doc.rake +7 -0
- data/test/helper.rb +2 -1
- data/test/integration/accessibility/test_dsl.rb +126 -18
- data/test/integration/accessibility/test_errors.rb +1 -1
- data/test/integration/ax/test_element.rb +17 -0
- data/test/integration/minitest/test_ax_elements.rb +33 -38
- data/test/integration/rspec/expectations/test_ax_elements.rb +68 -19
- data/test/sanity/accessibility/test_core.rb +45 -37
- data/test/sanity/accessibility/test_highlighter.rb +56 -0
- data/test/sanity/ax/test_application.rb +8 -0
- data/test/sanity/ax/test_element.rb +7 -3
- data/test/sanity/minitest/test_ax_elements.rb +2 -0
- data/test/sanity/rspec/expectations/test_ax_elements.rb +3 -0
- data/test/sanity/test_accessibility.rb +9 -0
- data/test/sanity/test_mouse.rb +2 -2
- metadata +11 -38
- data/docs/AccessibilityTips.markdown +0 -119
- data/docs/Acting.markdown +0 -340
- data/docs/Debugging.markdown +0 -165
- data/docs/Inspecting.markdown +0 -261
- data/docs/KeyboardEvents.markdown +0 -122
- data/docs/NewBehaviour.markdown +0 -151
- data/docs/Notifications.markdown +0 -271
- data/docs/Searching.markdown +0 -250
- data/docs/TestingExtensions.markdown +0 -52
- data/docs/images/all_the_buttons.jpg +0 -0
- data/docs/images/next_version.png +0 -0
- data/docs/images/ui_hierarchy.dot +0 -34
- data/docs/images/ui_hierarchy.png +0 -0
- data/lib/accessibility/debug.rb +0 -164
- data/test/integration/accessibility/test_debug.rb +0 -44
- data/test/sanity/accessibility/test_debug.rb +0 -63
@@ -14,6 +14,7 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
|
|
14
14
|
|
15
15
|
def app; @@app ||= AX::Application.new REF end
|
16
16
|
def text_area; @@text_area ||= app.main_window.text_area end
|
17
|
+
def pop_up; @@pop_up ||= app.main_window.pop_up end
|
17
18
|
def pref_window; app.children.find { |x| x.attribute(:title) == 'Preferences' } end
|
18
19
|
def spelling_window; app.children.find { |x| x.attribute(:title).to_s.match(/^Spelling/) } end
|
19
20
|
|
@@ -144,6 +145,111 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
|
|
144
145
|
assert_equal 'AXIsNyan', result.value
|
145
146
|
end
|
146
147
|
|
148
|
+
def test_wait_for_invalid_raises_if_wait_for_without_parent_or_ancestor
|
149
|
+
assert_raises(ArgumentError) { dsl.wait_for_invalidation_of(:button) }
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_wait_for_invalid_false_if_timeout
|
153
|
+
refute dsl.wait_for_invalidation_of(:button, parent: app.main_window, timeout: 1)
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_wait_for_invalidation_of_element
|
157
|
+
app.main_window.button(title: 'Yes').perform(:press)
|
158
|
+
Dispatch::Queue.new("herp").after(1) do
|
159
|
+
app.main_window.button(title: 'No').perform(:press)
|
160
|
+
end
|
161
|
+
|
162
|
+
assert dsl.wait_for_invalid(app.main_window.button(title: 'Bye!'))
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_wait_for_invalidation_of_wait_for
|
166
|
+
app.main_window.button(title: 'Yes').perform(:press)
|
167
|
+
Dispatch::Queue.new("herp").after(1) do
|
168
|
+
app.main_window.button(title: 'No').perform(:press)
|
169
|
+
end
|
170
|
+
|
171
|
+
assert dsl.wait_for_invalid(:button, ancestor: app, title: 'Bye!')
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_drag_mouse_to
|
175
|
+
title_element = app.main_window.title_ui_element
|
176
|
+
orig_title_position = title_element.to_point
|
177
|
+
orig_window_position = app.main_window.position
|
178
|
+
|
179
|
+
dsl.drag_mouse_to [100,100], from: title_element
|
180
|
+
assert_in_delta 100, title_element.to_point.x, 1
|
181
|
+
assert_in_delta 100, title_element.to_point.y, 1
|
182
|
+
|
183
|
+
dsl.drag_mouse_to orig_title_position
|
184
|
+
assert_in_delta orig_title_position.x, title_element.to_point.x, 1
|
185
|
+
assert_in_delta orig_title_position.y, title_element.to_point.y, 1
|
186
|
+
|
187
|
+
ensure
|
188
|
+
app.main_window.set :position, orig_window_position if orig_window_position
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_highlight
|
192
|
+
highlighter = dsl.highlight app.main_window, colour: NSColor.blueColor
|
193
|
+
assert_kind_of Accessibility::Highlighter, highlighter
|
194
|
+
assert_equal NSColor.blueColor, highlighter.backgroundColor
|
195
|
+
highlighter.stop
|
196
|
+
|
197
|
+
def highlight_test
|
198
|
+
@got_called = true
|
199
|
+
end
|
200
|
+
highlighter = dsl.highlight app.main_window, color: NSColor.greenColor, timeout: 0.1
|
201
|
+
NSNotificationCenter.defaultCenter.addObserver self,
|
202
|
+
selector: 'highlight_test',
|
203
|
+
name: NSWindowWillCloseNotification,
|
204
|
+
object: highlighter
|
205
|
+
sleep 0.1
|
206
|
+
assert @got_called
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_dump_works_for_nested_tab_groups
|
210
|
+
output = dsl.subtree_for app.window.tab_group
|
211
|
+
|
212
|
+
expected = [
|
213
|
+
['AX::TabGroup', 0],
|
214
|
+
['AX::RadioButton', 1], ['AX::RadioButton', 1], ['AX::TabGroup', 1],
|
215
|
+
['AX::RadioButton', 2], ['AX::RadioButton', 2], ['AX::TabGroup', 2],
|
216
|
+
['AX::RadioButton', 3], ['AX::RadioButton', 3], ['AX::TabGroup', 3],
|
217
|
+
['AX::RadioButton', 4], ['AX::RadioButton', 4],
|
218
|
+
['AX::Group', 4],
|
219
|
+
['AX::TextField', 5], ['AX::StaticText', 6],
|
220
|
+
['AX::TextField' , 5], ['AX::StaticText', 6]
|
221
|
+
]
|
222
|
+
|
223
|
+
refute_empty output
|
224
|
+
output = output.split("\n")
|
225
|
+
|
226
|
+
until output.empty?
|
227
|
+
line = output.shift
|
228
|
+
klass, indents = expected.shift
|
229
|
+
assert_equal indents, line.match(/^\t*/).to_a.first.length, line
|
230
|
+
line.strip!
|
231
|
+
assert_match /^\#<#{klass}/, line
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_screenshot
|
236
|
+
path = dsl.screenshot
|
237
|
+
assert File.exists? path
|
238
|
+
FileUtils.rm path
|
239
|
+
|
240
|
+
path = dsl.screenshot "Thing"
|
241
|
+
assert File.exists? path
|
242
|
+
assert_match /\/Thing/, path
|
243
|
+
FileUtils.rm path
|
244
|
+
|
245
|
+
path = dsl.screenshot "Thing", "/tmp"
|
246
|
+
assert File.exists? path
|
247
|
+
assert_match %r{/tmp/Thing-}, path
|
248
|
+
FileUtils.rm path
|
249
|
+
ensure
|
250
|
+
FileUtils.rm path if File.exists? path
|
251
|
+
end
|
252
|
+
|
147
253
|
def test_system_wide
|
148
254
|
assert_instance_of AX::SystemWide, dsl.system_wide
|
149
255
|
end
|
@@ -203,26 +309,28 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
|
|
203
309
|
end
|
204
310
|
|
205
311
|
def test_scroll_menu_to
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
pop_up.perform :
|
216
|
-
|
217
|
-
dsl.scroll_menu_to item
|
218
|
-
assert_equal item, element_under_mouse
|
219
|
-
dsl.click
|
220
|
-
assert_equal 'Togusa', pop_up.value
|
312
|
+
['49', 'Togusa'].each do |title|
|
313
|
+
pop_up.perform :press
|
314
|
+
item = wait_for :menu_item, ancestor: pop_up, title: title
|
315
|
+
dsl.scroll_menu_to item
|
316
|
+
assert_equal item, element_under_mouse
|
317
|
+
dsl.click
|
318
|
+
assert_equal title, pop_up.value
|
319
|
+
end
|
320
|
+
ensure
|
321
|
+
pop_up.menu_item.perform :cancel unless pop_up.children.empty?
|
322
|
+
end
|
221
323
|
|
324
|
+
def test_scroll_menu_to_using_single_click
|
325
|
+
['40', 'Batou', '49', 'Motoko'].each do |title|
|
326
|
+
dsl.click pop_up do
|
327
|
+
item = wait_for :menu_item, title: title, ancestor: pop_up
|
328
|
+
dsl.scroll_menu_to item
|
329
|
+
end
|
330
|
+
assert_equal title, pop_up.value
|
331
|
+
end
|
222
332
|
ensure
|
223
|
-
unless pop_up.children.empty?
|
224
|
-
pop_up.menu_item.perform :cancel
|
225
|
-
end if pop_up
|
333
|
+
pop_up.menu_item.perform :cancel unless pop_up.children.empty?
|
226
334
|
end
|
227
335
|
|
228
336
|
end
|
@@ -27,7 +27,7 @@ class TestAccessibilityErrors < MiniTest::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_search_failure_includes_subtree_in_debug_mode
|
30
|
-
assert Accessibility
|
30
|
+
assert Accessibility.debug?, 'Someone turned debugging off'
|
31
31
|
l = AX::DOCK.children.first
|
32
32
|
e = Accessibility::SearchFailure.new(l, :trash_dock_item, nil)
|
33
33
|
def e.backtrace; []; end
|
@@ -6,6 +6,14 @@ class TestAXElement < MiniTest::Unit::TestCase
|
|
6
6
|
@@app ||= AX::Application.new PID
|
7
7
|
end
|
8
8
|
|
9
|
+
def test_path_returns_correct_elements_in_correct_order
|
10
|
+
list = app.window.close_button.ancestry
|
11
|
+
assert_equal 3, list.size
|
12
|
+
assert_equal app, list.third
|
13
|
+
assert_equal app.window, list.second
|
14
|
+
assert_equal app.window.close_button, list.first
|
15
|
+
end
|
16
|
+
|
9
17
|
def test_search_singular_returns_array
|
10
18
|
result = app.search(:window)
|
11
19
|
assert_kind_of AX::Window, result
|
@@ -39,4 +47,13 @@ class TestAXElement < MiniTest::Unit::TestCase
|
|
39
47
|
box.set :value, '' if box
|
40
48
|
end
|
41
49
|
|
50
|
+
def test_invalid
|
51
|
+
refute app.invalid?
|
52
|
+
|
53
|
+
app.main_window.button(title: 'Yes').perform :press
|
54
|
+
bye = app.main_window.button(title: /Bye/)
|
55
|
+
app.main_window.button(title: 'No').perform :press
|
56
|
+
assert bye.invalid?
|
57
|
+
end
|
58
|
+
|
42
59
|
end
|
@@ -13,72 +13,69 @@ class TestMiniTestAssertions < MiniTest::Unit::TestCase
|
|
13
13
|
assert_equal expected, assert_has_child(app, :window)
|
14
14
|
assert_equal expected, assert_has_child(app, :window, title: 'AXElementsTester')
|
15
15
|
|
16
|
-
|
17
|
-
@got_called = true
|
18
|
-
x.title == 'AXElementsTester'
|
19
|
-
}
|
20
|
-
assert_equal expected, result
|
16
|
+
assert_has_child(app, :window) { |_| @got_called = true }
|
21
17
|
assert @got_called
|
22
18
|
end
|
23
19
|
|
24
20
|
def test_assert_has_child_raises_in_failure_cases
|
25
|
-
e = assert_raises
|
26
|
-
assert_has_child app, :button
|
27
|
-
end
|
21
|
+
e = assert_raises(MiniTest::Assertion) { assert_has_child app, :button }
|
28
22
|
assert_match /to have Button as a child/, e.message
|
29
23
|
|
30
|
-
e = assert_raises
|
31
|
-
|
32
|
-
end
|
33
|
-
assert_match /to have Button\(title: "Press Me"\) as a child/, e.message
|
24
|
+
e = assert_raises(MiniTest::Assertion) { assert_has_child app, :button, title: "Press" }
|
25
|
+
assert_match %r{to have Button\(title: "Press"\) as a child}, e.message
|
34
26
|
end
|
35
27
|
|
36
28
|
def test_assert_has_descendent
|
37
29
|
expected = app.main_window.check_box
|
38
30
|
|
39
31
|
assert_equal expected, assert_has_descendent(app,:check_box)
|
40
|
-
assert_equal expected, assert_has_descendent(app,:check_box,title: /Box/)
|
32
|
+
assert_equal expected, assert_has_descendent(app,:check_box, title: /Box/)
|
41
33
|
|
42
|
-
|
43
|
-
@got_called = true
|
44
|
-
x.title == 'Unchecked Check Box'
|
45
|
-
end
|
46
|
-
assert_equal expected, result
|
34
|
+
assert_has_descendent(app, :check_box) { |_| @got_called = true }
|
47
35
|
assert @got_called
|
48
36
|
end
|
49
37
|
|
50
38
|
def test_assert_has_descendent_raises_in_failure_cases
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
39
|
+
e = assert_raises(MiniTest::Assertion) {
|
40
|
+
assert_has_descendent(app.main_window.slider, :window, title: /Cake/)
|
41
|
+
}
|
55
42
|
assert_match /to have Window\(title: \/Cake\/\) as a descendent/, e.message
|
56
43
|
end
|
57
44
|
|
45
|
+
def test_assert_shortly_has
|
46
|
+
assert_equal app.window, assert_shortly_has(:window, parent: app)
|
47
|
+
assert_equal app.check_box, assert_shortly_has(:check_box, ancestor: app)
|
48
|
+
|
49
|
+
assert_shortly_has(:window, parent: app) { @got_called = true }
|
50
|
+
assert @got_called
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_assert_shortly_has_raises_in_failure_cases
|
54
|
+
e = assert_raises(MiniTest::Assertion) { assert_shortly_has(:button, parent: app, timeout: 0) }
|
55
|
+
assert_match /to have child Button before a timeout occurred/, e.message
|
56
|
+
|
57
|
+
e = assert_raises(MiniTest::Assertion) { assert_shortly_has(:table, ancestor: app.menu_bar_item, timeout: 0) }
|
58
|
+
assert_match /to have descendent Table before a timeout occurred/, e.message
|
59
|
+
end
|
60
|
+
|
58
61
|
def test_refute_has_child
|
59
|
-
assert_nil refute_has_child(app
|
60
|
-
assert_nil refute_has_child(app
|
62
|
+
assert_nil refute_has_child(app, :button)
|
63
|
+
assert_nil refute_has_child(app, :window, title: 'Herp Derp')
|
61
64
|
|
62
|
-
result = refute_has_child
|
63
|
-
@got_called = true
|
64
|
-
x.title == 'Herp Derp'
|
65
|
-
end
|
65
|
+
result = refute_has_child(app, :window) { |x| x.title == 'Herp Derp' }
|
66
66
|
assert_nil result
|
67
|
-
assert @got_called
|
68
67
|
end
|
69
68
|
|
70
69
|
def test_refute_has_child_raises_in_failure_cases
|
71
|
-
e = assert_raises
|
72
|
-
|
73
|
-
end
|
74
|
-
assert_match /not to have #{Regexp.escape(app.window.inspect)} as a child/, e.message
|
70
|
+
e = assert_raises(MiniTest::Assertion) { refute_has_child app, :window }
|
71
|
+
assert_match /NOT to have #{Regexp.escape(app.window.inspect)} as a child/, e.message
|
75
72
|
end
|
76
73
|
|
77
74
|
def test_refute_has_descendent
|
78
75
|
slider = app.main_window.slider
|
79
76
|
|
80
|
-
assert_nil refute_has_descendent(slider
|
81
|
-
assert_nil refute_has_descendent(slider
|
77
|
+
assert_nil refute_has_descendent(slider, :window)
|
78
|
+
assert_nil refute_has_descendent(slider, :element, title: 'Rhubarb')
|
82
79
|
|
83
80
|
result = refute_has_descendent slider, :element do |x|
|
84
81
|
@got_called = true
|
@@ -89,9 +86,7 @@ class TestMiniTestAssertions < MiniTest::Unit::TestCase
|
|
89
86
|
end
|
90
87
|
|
91
88
|
def test_refute_has_descendent_raises_in_failure_cases
|
92
|
-
e = assert_raises
|
93
|
-
refute_has_descendent app, :window
|
94
|
-
end
|
89
|
+
e = assert_raises(MiniTest::Assertion) { refute_has_descendent app, :window }
|
95
90
|
assert_match /#{Regexp.escape(app.window.inspect)} as a descendent/, e.message
|
96
91
|
end
|
97
92
|
|
@@ -8,51 +8,100 @@ class TestRSpecMatchers < MiniTest::Unit::TestCase
|
|
8
8
|
@@app ||= AX::Application.new PID
|
9
9
|
end
|
10
10
|
|
11
|
+
|
12
|
+
|
11
13
|
def test_have_child_should_failure_message
|
12
|
-
m = Accessibility::HasChildMatcher.new(:window, {}) {}
|
13
14
|
e = app.main_window.slider
|
15
|
+
m = have_child(:window)
|
14
16
|
|
15
|
-
m.matches?
|
16
|
-
assert_equal "Expected #{e.inspect} to have child Window
|
17
|
-
m.failure_message_for_should
|
17
|
+
refute m.matches?(e)
|
18
|
+
assert_equal "Expected #{e.inspect} to have child Window", m.failure_message_for_should
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_have_child_should_not_failure_message
|
21
|
-
m = Accessibility::HasChildMatcher.new(:window, {})
|
22
22
|
e = app.window
|
23
|
+
m = have_child(:window)
|
23
24
|
|
24
|
-
m.does_not_match?
|
25
|
-
assert_equal "Expected #{app.inspect} to NOT have child #{e.inspect}",
|
26
|
-
m.failure_message_for_should_not
|
25
|
+
refute m.does_not_match?(app)
|
26
|
+
assert_equal "Expected #{app.inspect} to NOT have child #{e.inspect}", m.failure_message_for_should_not
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_have_child_description
|
30
|
-
m =
|
30
|
+
m = have_child(:window) { }
|
31
31
|
assert_equal 'should have a child that matches Window[✔]', m.description
|
32
32
|
end
|
33
33
|
|
34
|
+
|
35
|
+
|
34
36
|
def test_have_descendent_should_failure_message
|
35
|
-
m =
|
36
|
-
q = Accessibility::Qualifier.new(:Button,{}) {}
|
37
|
+
m = have_descendent(:button)
|
37
38
|
e = app.main_window.slider
|
38
39
|
|
39
|
-
m.matches?
|
40
|
-
assert_equal "Expected #{e.inspect} to have descendent Button
|
41
|
-
m.failure_message_for_should
|
40
|
+
refute m.matches?(e)
|
41
|
+
assert_equal "Expected #{e.inspect} to have descendent Button", m.failure_message_for_should
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_have_descendent_should_not_failure_message
|
45
|
-
m =
|
45
|
+
m = have_descendant(:window)
|
46
46
|
e = app.window
|
47
47
|
|
48
|
-
m.does_not_match?
|
49
|
-
assert_equal "Expected #{app.inspect} to NOT have descendent #{e.inspect}",
|
50
|
-
m.failure_message_for_should_not
|
48
|
+
refute m.does_not_match?(app)
|
49
|
+
assert_equal "Expected #{app.inspect} to NOT have descendent #{e.inspect}", m.failure_message_for_should_not
|
51
50
|
end
|
52
51
|
|
53
52
|
def test_have_descendent_description
|
54
|
-
m =
|
53
|
+
m = have_descendent(:button)
|
55
54
|
assert_equal 'should have a descendent matching Button', m.description
|
56
55
|
end
|
57
56
|
|
57
|
+
|
58
|
+
|
59
|
+
def test_shortly_have_child_should_failure_message
|
60
|
+
m = shortly_have_child(:button, timeout: 0) { }
|
61
|
+
e = app.main_window.slider
|
62
|
+
|
63
|
+
refute m.matches?(e)
|
64
|
+
assert_equal "Expected #{e.inspect} to have child Button[✔] before a timeout occurred",
|
65
|
+
m.failure_message_for_should
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_shortly_have_child_should_not_failure_message
|
69
|
+
m = shortly_have_child(:window)
|
70
|
+
e = app
|
71
|
+
|
72
|
+
refute m.does_not_match?(e)
|
73
|
+
assert_equal "Expected #{e.inspect} to NOT have child #{e.window.inspect} before a timeout occurred",
|
74
|
+
m.failure_message_for_should_not
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_shortly_have_child_description
|
78
|
+
m = shortly_have_child(:button)
|
79
|
+
assert_equal 'should have a child that matches Button before a timeout occurs', m.description
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
def test_shortly_have_descendent_should_failure_message
|
85
|
+
m = shortly_have_descendent(:button, timeout: 0)
|
86
|
+
e = app.main_window.slider
|
87
|
+
|
88
|
+
refute m.matches?(e)
|
89
|
+
assert_equal "Expected #{e.inspect} to have descendent Button before a timeout occurred",
|
90
|
+
m.failure_message_for_should
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_shortly_have_descendent_should_not_failure_message
|
94
|
+
m = shortly_have_descendent(:window)
|
95
|
+
e = app
|
96
|
+
|
97
|
+
refute m.does_not_match?(e)
|
98
|
+
assert_equal "Expected #{e.inspect} to NOT have descendent #{e.window.inspect} before a timeout occurred",
|
99
|
+
m.failure_message_for_should_not
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_shortly_have_descendent_description
|
103
|
+
m = shortly_have_descendent(:button)
|
104
|
+
assert_equal 'should have a descendent matching Button before a timeout occurs', m.description
|
105
|
+
end
|
106
|
+
|
58
107
|
end
|
@@ -65,7 +65,7 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
65
65
|
def test_attribute
|
66
66
|
assert_equal 'AXElementsTester', window.attribute(KAXTitleAttribute )
|
67
67
|
assert_equal false, window.attribute(KAXFocusedAttribute)
|
68
|
-
assert_equal
|
68
|
+
assert_equal CGSize.new(555,529), window.attribute(KAXSizeAttribute )
|
69
69
|
assert_equal REF, window.attribute(KAXParentAttribute )
|
70
70
|
assert_equal 10..19, window.attribute("AXPie" )
|
71
71
|
end
|
@@ -102,6 +102,15 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
102
102
|
assert_equal slider.attribute(KAXValueAttribute), slider.value
|
103
103
|
end
|
104
104
|
|
105
|
+
def test_pid
|
106
|
+
assert_equal PID, REF.pid
|
107
|
+
assert_equal PID, window.pid
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_pid_is_zero_for_system_wide
|
111
|
+
assert_equal 0, REF.system_wide.pid
|
112
|
+
end
|
113
|
+
|
105
114
|
def test_size_of
|
106
115
|
assert_equal REF.children.size, REF.size_of(KAXChildrenAttribute)
|
107
116
|
assert_equal 0, pop_up.size_of(KAXChildrenAttribute)
|
@@ -167,28 +176,26 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
167
176
|
assert_empty invalid_ref.parameterized_attributes
|
168
177
|
end
|
169
178
|
|
170
|
-
def
|
179
|
+
def test_parameterized_attribute
|
171
180
|
expected = 'My Li'
|
172
181
|
|
173
|
-
attr = static_text.
|
174
|
-
for_parameter: 0..4
|
182
|
+
attr = static_text.parameterized_attribute(KAXStringForRangeParameterizedAttribute, 0..4)
|
175
183
|
assert_equal expected, attr
|
176
184
|
|
177
|
-
attr = static_text.
|
178
|
-
for_parameter: 0..4
|
185
|
+
attr = static_text.parameterized_attribute(KAXAttributedStringForRangeParameterizedAttribute, 0..4)
|
179
186
|
assert_equal expected, attr.string
|
180
187
|
end
|
181
188
|
|
182
|
-
def
|
183
|
-
assert_nil invalid_ref.
|
189
|
+
def test_parameterized_attribute_handles_dead_elements_and_no_value
|
190
|
+
assert_nil invalid_ref.parameterized_attribute(KAXStringForRangeParameterizedAttribute, 0..0)
|
184
191
|
|
185
192
|
# Should add a test case to test the no value case, but it will have
|
186
193
|
# to be fabricated in the test app.
|
187
194
|
end
|
188
195
|
|
189
|
-
def
|
196
|
+
def test_parameterized_attribute_handles_errors
|
190
197
|
assert_raises(ArgumentError) {
|
191
|
-
REF.
|
198
|
+
REF.parameterized_attribute(KAXStringForRangeParameterizedAttribute, 0..1)
|
192
199
|
}
|
193
200
|
end
|
194
201
|
|
@@ -279,8 +286,8 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
279
286
|
# # more than meets the eye
|
280
287
|
def test_notification_registration_and_unregistration
|
281
288
|
obsrvr = REF.observer { |_,_,_| }
|
282
|
-
assert REF.register(obsrvr,
|
283
|
-
assert REF.unregister(obsrvr,
|
289
|
+
assert REF.register(obsrvr, KAXWindowCreatedNotification)
|
290
|
+
assert REF.unregister(obsrvr, KAXWindowCreatedNotification)
|
284
291
|
end
|
285
292
|
|
286
293
|
# integration-y
|
@@ -288,7 +295,7 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
288
295
|
obsrvr = REF.observer do |observer, element, notif|
|
289
296
|
@notif_triple = [observer, element, notif]
|
290
297
|
end
|
291
|
-
REF.register observer,
|
298
|
+
REF.register observer, 'Cheezburger'
|
292
299
|
source = REF.run_loop_source_for observer
|
293
300
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, KCFRunLoopDefaultMode)
|
294
301
|
|
@@ -304,38 +311,24 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
304
311
|
|
305
312
|
def test_register_handles_errors
|
306
313
|
assert_raises(ArgumentError) {
|
307
|
-
REF.register(nil,
|
314
|
+
REF.register(nil, KAXWindowCreatedNotification)
|
308
315
|
}
|
309
316
|
assert_raises(ArgumentError) {
|
310
317
|
obsrvr = REF.observer { |_,_,_| }
|
311
|
-
REF.register(obsrvr,
|
318
|
+
REF.register(obsrvr, nil)
|
312
319
|
}
|
313
320
|
end
|
314
321
|
|
315
322
|
def test_unregister_handles_errors
|
316
323
|
assert_raises(ArgumentError) {
|
317
|
-
REF.unregister(nil,
|
324
|
+
REF.unregister(nil, KAXWindowCreatedNotification)
|
318
325
|
}
|
319
326
|
assert_raises(ArgumentError) {
|
320
327
|
obsrvr = REF.observer { |_,_,_| }
|
321
|
-
REF.unregister(obsrvr,
|
328
|
+
REF.unregister(obsrvr, nil)
|
322
329
|
}
|
323
330
|
end
|
324
331
|
|
325
|
-
def test_enabled?
|
326
|
-
assert REF.enabled?
|
327
|
-
# @todo I guess that's good enough?
|
328
|
-
end
|
329
|
-
|
330
|
-
def test_pid
|
331
|
-
assert_equal PID, REF.pid
|
332
|
-
assert_equal PID, window.pid
|
333
|
-
end
|
334
|
-
|
335
|
-
def test_pid_is_zero_for_system_wide
|
336
|
-
assert_equal 0, REF.system_wide.pid
|
337
|
-
end
|
338
|
-
|
339
332
|
def test_system_wide
|
340
333
|
assert_equal AXUIElementCreateSystemWide(), REF.system_wide
|
341
334
|
end
|
@@ -375,7 +368,7 @@ class TestAccessibilityCore < MiniTest::Unit::TestCase
|
|
375
368
|
should_raise: ArgumentError,
|
376
369
|
with_fragments: [/can't get\/set "cake" with\/to "chocolate"/, app]
|
377
370
|
|
378
|
-
p =
|
371
|
+
p = CGPoint.new(1,3)
|
379
372
|
assert_error [KAXErrorIllegalArgument, p, nil, nil],
|
380
373
|
should_raise: ArgumentError,
|
381
374
|
with_fragments: [/The point #{p.inspect}/, app]
|
@@ -518,7 +511,7 @@ class TestToAXToRubyHooks < MiniTest::Unit::TestCase
|
|
518
511
|
|
519
512
|
def test_to_ruby
|
520
513
|
assert_equal CGPointZero, CGPointZero .to_ax.to_ruby
|
521
|
-
assert_equal
|
514
|
+
assert_equal CGSize.new(10,10), CGSize.new(10,10).to_ax.to_ruby
|
522
515
|
assert_equal Range.new(1,10), CFRange.new(1,10).to_ax.to_ruby
|
523
516
|
end
|
524
517
|
|
@@ -533,21 +526,36 @@ end
|
|
533
526
|
class TestMiscCoreExtensions < MiniTest::Unit::TestCase
|
534
527
|
|
535
528
|
def test_to_point
|
536
|
-
p =
|
529
|
+
p = CGPoint.new(2,3)
|
537
530
|
assert_equal p, p.to_point
|
538
531
|
|
539
|
-
p =
|
532
|
+
p = CGPoint.new(1,3)
|
540
533
|
assert_equal p, p.to_a.to_point
|
541
534
|
end
|
542
535
|
|
543
536
|
def test_to_size
|
544
|
-
s =
|
537
|
+
s = CGSize.new(2,4)
|
545
538
|
assert_equal s, s.to_a.to_size
|
546
539
|
end
|
547
540
|
|
548
541
|
def test_to_rect
|
549
|
-
r = CGRectMake(6,7,8,9)
|
542
|
+
r = CGRectMake(6, 7, 8, 9)
|
550
543
|
assert_equal r, r.to_a.map(&:to_a).flatten.to_rect
|
551
544
|
end
|
552
545
|
|
546
|
+
def test_to_url
|
547
|
+
site = 'http://marketcircle.com/'
|
548
|
+
url = site.to_url
|
549
|
+
refute_nil url
|
550
|
+
assert_equal NSURL.URLWithString(site), url
|
551
|
+
|
552
|
+
file = 'file://localhost/Applications/Calculator.app/'
|
553
|
+
url = file.to_url
|
554
|
+
refute_nil url
|
555
|
+
assert_equal NSURL.fileURLWithPath('/Applications/Calculator.app/'), url
|
556
|
+
|
557
|
+
void = "not a url at all"
|
558
|
+
assert_nil void.to_url
|
559
|
+
end
|
560
|
+
|
553
561
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'test/runner'
|
2
|
+
require 'accessibility/highlighter'
|
3
|
+
|
4
|
+
class TestHighlighter < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def bounds
|
7
|
+
CGRectMake(100, 100, 100, 100)
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_highlight_returns_created_window
|
11
|
+
w = Accessibility::Highlighter.new bounds
|
12
|
+
assert_kind_of NSWindow, w
|
13
|
+
assert_respond_to w, :stop
|
14
|
+
ensure
|
15
|
+
w.close if w
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_highlight_can_take_a_timeout
|
19
|
+
w = Accessibility::Highlighter.new bounds, timeout: 0.1
|
20
|
+
assert w.visible?
|
21
|
+
sleep 0.15
|
22
|
+
refute w.visible? # Not exactly the assertion I want, but close enough
|
23
|
+
ensure
|
24
|
+
w.close if w
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_highlight_can_have_custom_colour
|
28
|
+
w = Accessibility::Highlighter.new bounds, color: NSColor.cyanColor
|
29
|
+
assert w.backgroundColor == NSColor.cyanColor
|
30
|
+
w.close
|
31
|
+
|
32
|
+
# test both spellings of colour
|
33
|
+
w = Accessibility::Highlighter.new bounds, colour: NSColor.purpleColor
|
34
|
+
assert w.backgroundColor == NSColor.purpleColor
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_highlight_highlights_correct_rect
|
38
|
+
w = Accessibility::Highlighter.new bounds
|
39
|
+
assert_equal w.frame, bounds.flip!
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class TestCGRectExtensions < MiniTest::Unit::TestCase
|
45
|
+
|
46
|
+
def test_flipping
|
47
|
+
size = NSScreen.mainScreen.frame.size
|
48
|
+
assert_equal CGRectMake(0, size.height, 0, 0), CGRectZero.dup.flip!
|
49
|
+
assert_equal CGRectMake(100, size.height-200, 100, 100), CGRectMake(100,100,100,100).flip!
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_flipping_twice_returns_to_original
|
53
|
+
assert_equal CGRectZero.dup, CGRectZero.dup.flip!.flip!
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|