AXElements 0.7.8 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|