AXElements 0.9.0 → 1.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.yardopts +0 -4
  2. data/README.markdown +22 -17
  3. data/Rakefile +1 -1
  4. data/ext/accessibility/key_coder/extconf.rb +1 -1
  5. data/ext/accessibility/key_coder/key_coder.c +2 -4
  6. data/lib/accessibility.rb +3 -3
  7. data/lib/accessibility/core.rb +948 -0
  8. data/lib/accessibility/dsl.rb +30 -186
  9. data/lib/accessibility/enumerators.rb +1 -0
  10. data/lib/accessibility/factory.rb +78 -134
  11. data/lib/accessibility/graph.rb +5 -9
  12. data/lib/accessibility/highlighter.rb +86 -0
  13. data/lib/accessibility/{pretty_printer.rb → pp_inspector.rb} +4 -3
  14. data/lib/accessibility/qualifier.rb +3 -5
  15. data/lib/accessibility/screen_recorder.rb +217 -0
  16. data/lib/accessibility/statistics.rb +57 -0
  17. data/lib/accessibility/translator.rb +23 -32
  18. data/lib/accessibility/version.rb +2 -22
  19. data/lib/ax/application.rb +20 -159
  20. data/lib/ax/element.rb +42 -32
  21. data/lib/ax/scroll_area.rb +5 -6
  22. data/lib/ax/systemwide.rb +1 -33
  23. data/lib/ax_elements.rb +1 -9
  24. data/lib/ax_elements/core_graphics_workaround.rb +5 -0
  25. data/lib/ax_elements/nsarray_compat.rb +17 -97
  26. data/lib/ax_elements/vendor/inflection_data.rb +66 -0
  27. data/lib/ax_elements/vendor/inflections.rb +176 -0
  28. data/lib/ax_elements/vendor/inflector.rb +306 -0
  29. data/lib/minitest/ax_elements.rb +180 -0
  30. data/lib/mouse.rb +227 -0
  31. data/lib/rspec/expectations/ax_elements.rb +234 -0
  32. data/rakelib/gem.rake +3 -12
  33. data/rakelib/test.rake +15 -0
  34. data/test/helper.rb +20 -10
  35. data/test/integration/accessibility/test_core.rb +18 -0
  36. data/test/integration/accessibility/test_dsl.rb +40 -38
  37. data/test/integration/accessibility/test_enumerators.rb +1 -0
  38. data/test/integration/accessibility/test_graph.rb +0 -1
  39. data/test/integration/accessibility/test_qualifier.rb +2 -2
  40. data/test/integration/ax/test_application.rb +2 -9
  41. data/test/integration/ax/test_element.rb +0 -40
  42. data/test/integration/minitest/test_ax_elements.rb +89 -0
  43. data/test/integration/rspec/expectations/test_ax_elements.rb +102 -0
  44. data/test/sanity/accessibility/test_factory.rb +2 -2
  45. data/test/sanity/accessibility/test_highlighter.rb +56 -0
  46. data/test/sanity/accessibility/{test_pretty_printer.rb → test_pp_inspector.rb} +9 -9
  47. data/test/sanity/accessibility/test_statistics.rb +57 -0
  48. data/test/sanity/ax/test_application.rb +1 -16
  49. data/test/sanity/ax/test_element.rb +2 -2
  50. data/test/sanity/ax_elements/test_nsobject_inspect.rb +2 -4
  51. data/test/sanity/minitest/test_ax_elements.rb +17 -0
  52. data/test/sanity/rspec/expectations/test_ax_elements.rb +15 -0
  53. data/test/sanity/test_mouse.rb +22 -0
  54. data/test/test_core.rb +454 -0
  55. metadata +44 -69
  56. data/History.markdown +0 -41
  57. data/lib/accessibility/system_info.rb +0 -230
  58. data/lib/ax_elements/active_support_selections.rb +0 -10
  59. data/lib/ax_elements/mri.rb +0 -57
  60. data/test/sanity/accessibility/test_version.rb +0 -15
data/rakelib/gem.rake CHANGED
@@ -4,24 +4,15 @@ ax_elements = Gem::Specification.load('AXElements.gemspec')
4
4
  Gem::PackageTask.new(ax_elements) { }
5
5
 
6
6
  desc 'Build and install gem (not including deps)'
7
- task :install => [:gem, :setup] do
7
+ task :install => :gem do
8
8
  require 'rubygems/installer'
9
9
  Gem::Installer.new("pkg/#{ax_elements.file_name}").install
10
10
  end
11
11
 
12
- desc 'Install dependencies for running AXElements'
13
- task :setup do
14
- require 'rubygems/dependency_installer'
15
- ax_elements.runtime_dependencies.each do |dep|
16
- puts "Installing #{dep.name} (#{dep.requirement})"
17
- Gem::DependencyInstaller.new.install(dep.name, dep.requirement)
18
- end
19
- end
20
-
21
12
  desc 'Install dependencies for development'
22
- task :setup_dev => :setup do
13
+ task :setup_dev do
23
14
  require 'rubygems/dependency_installer'
24
- (ax_elements.runtime_dependencies + ax_elements.development_dependencies).each do |dep|
15
+ ax_elements.development_dependencies.each do |dep|
25
16
  puts "Installing #{dep.name} (#{dep.requirement})"
26
17
  Gem::DependencyInstaller.new.install(dep.name, dep.requirement)
27
18
  end
data/rakelib/test.rake CHANGED
@@ -23,6 +23,12 @@ task :clobber => :clobber_fixture
23
23
 
24
24
  require 'rake/testtask'
25
25
  namespace :test do
26
+ Rake::TestTask.new(:core) do |t|
27
+ t.libs << '.'
28
+ t.pattern = 'test/test_core.rb'
29
+ end
30
+ task :core => [:ext, :fixture]
31
+
26
32
  Rake::TestTask.new(:sanity) do |t|
27
33
  t.libs << '.'
28
34
  t.pattern = "test/sanity/**/test_*.rb"
@@ -41,4 +47,13 @@ namespace :test do
41
47
  t.pattern = "test/sanity/accessibility/test_string.rb"
42
48
  end
43
49
  task :string => :ext
50
+
51
+ desc 'Run tests under CRuby (where applicable)'
52
+ task :cruby do
53
+ if ENV['RUBY_VERSION'] # using rvm
54
+ puts sh 'rvm 1.9.3 do rake test:string'
55
+ else
56
+ sh 'rake test:string'
57
+ end
58
+ end
44
59
  end
data/test/helper.rb CHANGED
@@ -1,18 +1,28 @@
1
- require 'rubygems'
2
- require 'accessibility/core'
3
- framework 'Cocoa' if on_macruby?
1
+ framework 'Cocoa'
4
2
 
5
3
  # We want to launch the test app and make sure it responds to
6
4
  # accessibility queries, but that is difficult to know at what
7
5
  # point it will start to respond, so we just sleep
8
- APP_BUNDLE_PATH = File.expand_path './test/fixture/Release/AXElementsTester.app'
6
+ APP_BUNDLE_URL = NSURL.fileURLWithPath File.expand_path './test/fixture/Release/AXElementsTester.app'
9
7
  APP_BUNDLE_IDENTIFIER = 'com.marketcircle.AXElementsTester'
10
8
 
11
- `open #{APP_BUNDLE_PATH}`
12
- sleep 3
13
-
14
- at_exit do
15
- `killall AXElementsTester`
9
+ error = Pointer.new :id
10
+ TEST_APP = NSWorkspace.sharedWorkspace.launchApplicationAtURL APP_BUNDLE_URL,
11
+ options: NSWorkspaceLaunchAsync,
12
+ configuration: {},
13
+ error: error
14
+ if TEST_APP.nil?
15
+ $stderr.puts 'You need to build AND run the fixture app once before running tests'
16
+ $stderr.puts 'Run `rake run_fixture` to initalize the fixture'
17
+ exit 3
18
+ else
19
+ sleep 2 # Instead of using high level features of AXElements that we are
20
+ # testing, I think it is just safer to sleep
21
+ # Make sure the test app is closed when testing finishes
22
+ at_exit do
23
+ TEST_APP.terminate
24
+ puts STATS.to_s
25
+ end
16
26
  end
17
27
 
18
28
 
@@ -22,5 +32,5 @@ require 'test/runner'
22
32
  class MiniTest::Unit::TestCase
23
33
  # needs to be defined in the class, there is a TOPLEVEL::PID
24
34
  PID = pid_for APP_BUNDLE_IDENTIFIER
25
- REF = Accessibility::Element.application_for PID
35
+ REF = AXUIElementCreateApplication(PID)
26
36
  end
@@ -0,0 +1,18 @@
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
@@ -166,8 +166,7 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
166
166
 
167
167
  def test_wait_for_invalidation_of_element
168
168
  app.main_window.button(title: 'Yes').perform(:press)
169
- Thread.new do
170
- sleep 1
169
+ Dispatch::Queue.new("herp").after(1) do
171
170
  app.main_window.button(title: 'No').perform(:press)
172
171
  end
173
172
 
@@ -176,8 +175,7 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
176
175
 
177
176
  def test_wait_for_invalidation_of_wait_for
178
177
  app.main_window.button(title: 'Yes').perform(:press)
179
- Thread.new do
180
- sleep 1
178
+ Dispatch::Queue.new("herp").after(1) do
181
179
  app.main_window.button(title: 'No').perform(:press)
182
180
  end
183
181
 
@@ -201,33 +199,48 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
201
199
  app.main_window.set :position, orig_window_position if orig_window_position
202
200
  end
203
201
 
204
- def test_right_click_with_block
205
- area = app.main_window.web_area
206
-
207
- got_called = false
208
- dsl.right_click area do
209
- got_called = true
210
- end
211
- assert got_called
212
- ensure
213
- dsl.click area
214
- end
215
-
216
- def test_triple_click
217
- dummy_text = 'Lorem ipsum dolor.' * 15
218
- text_area.set :value, dummy_text
219
- dsl.triple_click text_area
220
- assert_equal dummy_text, text_area.selected_text
221
- ensure
222
- app.main_window.text_area.set :value, ''
223
- end
224
-
225
202
  def test_highlight
226
203
  highlighter = dsl.highlight app.main_window, colour: NSColor.blueColor
227
204
  assert_kind_of Accessibility::Highlighter, highlighter
228
- assert_equal NSColor.blueColor, highlighter.color
205
+ assert_equal NSColor.blueColor, highlighter.backgroundColor
229
206
  highlighter.stop
230
- refute highlighter.visible?
207
+
208
+ def highlight_test
209
+ @got_called = true
210
+ end
211
+ highlighter = dsl.highlight app.main_window, color: NSColor.greenColor, timeout: 0.1
212
+ NSNotificationCenter.defaultCenter.addObserver self,
213
+ selector: 'highlight_test',
214
+ name: NSWindowWillCloseNotification,
215
+ object: highlighter
216
+ sleep 0.1
217
+ assert @got_called
218
+ end
219
+
220
+ def test_dump_works_for_nested_tab_groups
221
+ output = dsl.subtree_for app.window.tab_group
222
+
223
+ expected = [
224
+ ['AX::TabGroup', 0],
225
+ ['AX::RadioButton', 1], ['AX::RadioButton', 1], ['AX::TabGroup', 1],
226
+ ['AX::RadioButton', 2], ['AX::RadioButton', 2], ['AX::TabGroup', 2],
227
+ ['AX::RadioButton', 3], ['AX::RadioButton', 3], ['AX::TabGroup', 3],
228
+ ['AX::RadioButton', 4], ['AX::RadioButton', 4],
229
+ ['AX::Group', 4],
230
+ ['AX::TextField', 5], ['AX::StaticText', 6],
231
+ ['AX::TextField' , 5], ['AX::StaticText', 6]
232
+ ]
233
+
234
+ refute_empty output
235
+ output = output.split("\n")
236
+
237
+ until output.empty?
238
+ line = output.shift
239
+ klass, indents = expected.shift
240
+ assert_equal indents, line.match(/^\t*/).to_a.first.length, line
241
+ line.strip!
242
+ assert_match /^\#<#{klass}/, line
243
+ end
231
244
  end
232
245
 
233
246
  def test_screenshot
@@ -331,15 +344,4 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
331
344
  pop_up.menu_item.perform :cancel unless pop_up.children.empty?
332
345
  end
333
346
 
334
- def test_contextual_menu
335
- Mouse.move_to app.window.web_area
336
- menu = nil
337
- dsl.right_click do
338
- menu = dsl.contextual_menu
339
- end
340
- refute_nil menu, 'did not find the contextual menu'
341
- refute_nil menu.item(title: 'Reload')
342
- menu.perform :cancel
343
- end
344
-
345
347
  end
@@ -49,6 +49,7 @@ end
49
49
 
50
50
 
51
51
  class TestAccessibilityEnumeratorsDepthFirst < MiniTest::Unit::TestCase
52
+ include Accessibility::Element
52
53
 
53
54
  def app
54
55
  @@app ||= AX::Application.new REF
@@ -4,7 +4,6 @@ require 'accessibility/graph'
4
4
  class TestAccessibilityGraph < MiniTest::Unit::TestCase
5
5
 
6
6
  def test_generate
7
- skip 'graphs are broken right now'
8
7
  p = Accessibility::Graph.new(app.main_window).generate_png!
9
8
  assert File.exists? p
10
9
  assert_match /^PNG image/, `file --brief #{p}`
@@ -72,14 +72,14 @@ class TestAccessibilityQualifier < MiniTest::Unit::TestCase
72
72
 
73
73
  def test_qualifies_based_on_param_attribute_value
74
74
  e = app.attribute(:main_window).attribute(:title_ui_element)
75
- q = qualifier(:StaticText, [:string_for_range, 0..1] => 'AX' )
75
+ q = qualifier(:StaticText, [:string_for_range, CFRange.new(0,2)] => 'AX' )
76
76
  assert q.qualifies? e
77
77
  refute q.qualifies? list
78
78
  end
79
79
 
80
80
  def test_qualifies_based_on_param_attribute_regexp_match
81
81
  e = app.attribute(:main_window).attribute(:title_ui_element)
82
- q = qualifier(:StaticText, [:string_for_range, 0..1] => /AX/ )
82
+ q = qualifier(:StaticText, [:string_for_range, CFRange.new(0,2)] => /AX/ )
83
83
  assert q.qualifies? e
84
84
  refute q.qualifies? items.sample
85
85
  end
@@ -13,13 +13,6 @@ class TestAXApplication < MiniTest::Unit::TestCase
13
13
  assert_equal app, AX::Application.new(running_app)
14
14
  end
15
15
 
16
- def test_initialize_causing_app_to_launch
17
- app = AX::Application.new('com.apple.Grab')
18
- assert_kind_of AX::Application, app
19
- ensure
20
- app.terminate if app
21
- end
22
-
23
16
  def test_can_set_focus_and_blur_app # lol, blur
24
17
  assert app.set :focused, false
25
18
  refute app.active?
@@ -32,7 +25,7 @@ class TestAXApplication < MiniTest::Unit::TestCase
32
25
  assert app.attribute :focused?
33
26
 
34
27
  ensure
35
- running_app.activateWithOptions NSRunningApplication::NSApplicationActivateIgnoringOtherApps
28
+ running_app.activateWithOptions NSApplicationActivateIgnoringOtherApps
36
29
  end
37
30
 
38
31
  def test_can_hide_and_unhide_app
@@ -49,7 +42,7 @@ class TestAXApplication < MiniTest::Unit::TestCase
49
42
  refute app.hidden?
50
43
 
51
44
  ensure
52
- running_app.activateWithOptions NSRunningApplication::NSApplicationActivateIgnoringOtherApps
45
+ running_app.activateWithOptions NSApplicationActivateIgnoringOtherApps
53
46
  end
54
47
 
55
48
  def test_set_calls_super
@@ -10,13 +10,6 @@ class TestAXElement < MiniTest::Unit::TestCase
10
10
  assert_equal app.window.close_button, list.first
11
11
  end
12
12
 
13
- def test_parameterized_attribute_normalizes_ranges
14
- text = app.main_window.static_text
15
- expected = text.value
16
- actual = text.parameterized_attribute :string_for_range, 0..-1
17
- assert_equal expected, actual
18
- end
19
-
20
13
  def test_search_singular_returns_array
21
14
  result = app.search(:window)
22
15
  assert_kind_of AX::Window, result
@@ -50,13 +43,6 @@ class TestAXElement < MiniTest::Unit::TestCase
50
43
  box.set :value, '' if box
51
44
  end
52
45
 
53
- def test_parameterized_attribute_through_method_missing
54
- field = app.window.static_text
55
- expected = field.parameterized_attribute :string_for_range, 0..2
56
- actual = field.string_for_range 0..2
57
- assert_equal expected, actual
58
- end
59
-
60
46
  def test_invalid
61
47
  refute app.invalid?
62
48
 
@@ -66,30 +52,4 @@ class TestAXElement < MiniTest::Unit::TestCase
66
52
  assert bye.invalid?
67
53
  end
68
54
 
69
- def test_dump_works_for_nested_tab_groups
70
- output = app.window.tab_group.inspect_subtree
71
-
72
- expected = [
73
- ['AX::TabGroup', 0],
74
- ['AX::RadioButton', 1], ['AX::RadioButton', 1], ['AX::TabGroup', 1],
75
- ['AX::RadioButton', 2], ['AX::RadioButton', 2], ['AX::TabGroup', 2],
76
- ['AX::RadioButton', 3], ['AX::RadioButton', 3], ['AX::TabGroup', 3],
77
- ['AX::RadioButton', 4], ['AX::RadioButton', 4],
78
- ['AX::Group', 4],
79
- ['AX::TextField', 5], ['AX::StaticText', 6],
80
- ['AX::TextField' , 5], ['AX::StaticText', 6]
81
- ]
82
-
83
- refute_empty output
84
- output = output.split("\n")
85
-
86
- until output.empty?
87
- line = output.shift
88
- klass, indents = expected.shift
89
- assert_equal indents, line.match(/^\t*/).to_a.first.length, line
90
- line.strip!
91
- assert_match /^\#<#{klass}/, line
92
- end
93
- end
94
-
95
55
  end
@@ -0,0 +1,89 @@
1
+ require 'test/integration/helper'
2
+ require 'minitest/ax_elements'
3
+
4
+ class TestMiniTestAssertions < MiniTest::Unit::TestCase
5
+
6
+ def test_assert_has_child
7
+ expected = app.window
8
+
9
+ assert_equal expected, assert_has_child(app, :window)
10
+ assert_equal expected, assert_has_child(app, :window, title: 'AXElementsTester')
11
+
12
+ assert_has_child(app, :window) { |_| @got_called = true }
13
+ assert @got_called
14
+ end
15
+
16
+ def test_assert_has_child_raises_in_failure_cases
17
+ e = assert_raises(MiniTest::Assertion) { assert_has_child app, :button }
18
+ assert_match /to have Button as a child/, e.message
19
+
20
+ e = assert_raises(MiniTest::Assertion) { assert_has_child app, :button, title: "Press" }
21
+ assert_match %r{to have Button\(title: "Press"\) as a child}, e.message
22
+ end
23
+
24
+ def test_assert_has_descendent
25
+ expected = app.main_window.check_box
26
+
27
+ assert_equal expected, assert_has_descendent(app,:check_box)
28
+ assert_equal expected, assert_has_descendent(app,:check_box, title: /Box/)
29
+
30
+ assert_has_descendent(app, :check_box) { |_| @got_called = true }
31
+ assert @got_called
32
+ end
33
+
34
+ def test_assert_has_descendent_raises_in_failure_cases
35
+ e = assert_raises(MiniTest::Assertion) {
36
+ assert_has_descendent(app.main_window.slider, :window, title: /Cake/)
37
+ }
38
+ assert_match /to have Window\(title: \/Cake\/\) as a descendent/, e.message
39
+ end
40
+
41
+ def test_assert_shortly_has
42
+ assert_equal app.window, assert_shortly_has(:window, parent: app)
43
+ assert_equal app.check_box, assert_shortly_has(:check_box, ancestor: app)
44
+
45
+ assert_shortly_has(:window, parent: app) { @got_called = true }
46
+ assert @got_called
47
+ end
48
+
49
+ def test_assert_shortly_has_raises_in_failure_cases
50
+ e = assert_raises(MiniTest::Assertion) { assert_shortly_has(:button, parent: app, timeout: 0) }
51
+ assert_match /to have child Button before a timeout occurred/, e.message
52
+
53
+ e = assert_raises(MiniTest::Assertion) { assert_shortly_has(:table, ancestor: app.menu_bar_item, timeout: 0) }
54
+ assert_match /to have descendent Table before a timeout occurred/, e.message
55
+ end
56
+
57
+ def test_refute_has_child
58
+ assert_nil refute_has_child(app, :button)
59
+ assert_nil refute_has_child(app, :window, title: 'Herp Derp')
60
+
61
+ result = refute_has_child(app, :window) { |x| x.title == 'Herp Derp' }
62
+ assert_nil result
63
+ end
64
+
65
+ def test_refute_has_child_raises_in_failure_cases
66
+ e = assert_raises(MiniTest::Assertion) { refute_has_child app, :window }
67
+ assert_match /NOT to have #{Regexp.escape(app.window.inspect)} as a child/, e.message
68
+ end
69
+
70
+ def test_refute_has_descendent
71
+ slider = app.main_window.slider
72
+
73
+ assert_nil refute_has_descendent(slider, :window)
74
+ assert_nil refute_has_descendent(slider, :element, title: 'Rhubarb')
75
+
76
+ result = refute_has_descendent slider, :element do |x|
77
+ @got_called = true
78
+ x.attributes.include?(:title) && x.title == 'Rhubarb'
79
+ end
80
+ assert_nil result
81
+ assert @got_called
82
+ end
83
+
84
+ def test_refute_has_descendent_raises_in_failure_cases
85
+ e = assert_raises(MiniTest::Assertion) { refute_has_descendent app, :window }
86
+ assert_match /#{Regexp.escape(app.window.inspect)} as a descendent/, e.message
87
+ end
88
+
89
+ end
@@ -0,0 +1,102 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test/integration/helper'
3
+ require 'rspec/expectations/ax_elements'
4
+
5
+ class TestRSpecMatchers < MiniTest::Unit::TestCase
6
+
7
+
8
+ def test_have_child_should_failure_message
9
+ e = app.main_window.slider
10
+ m = have_child(:window)
11
+
12
+ refute m.matches?(e)
13
+ assert_equal "Expected #{e.inspect} to have child Window", m.failure_message_for_should
14
+ end
15
+
16
+ def test_have_child_should_not_failure_message
17
+ e = app.window
18
+ m = have_child(:window)
19
+
20
+ refute m.does_not_match?(app)
21
+ assert_equal "Expected #{app.inspect} to NOT have child #{e.inspect}", m.failure_message_for_should_not
22
+ end
23
+
24
+ def test_have_child_description
25
+ m = have_child(:window) { }
26
+ assert_equal 'should have a child that matches Window[✔]', m.description
27
+ end
28
+
29
+
30
+
31
+ def test_have_descendent_should_failure_message
32
+ m = have_descendent(:button)
33
+ e = app.main_window.slider
34
+
35
+ refute m.matches?(e)
36
+ assert_equal "Expected #{e.inspect} to have descendent Button", m.failure_message_for_should
37
+ end
38
+
39
+ def test_have_descendent_should_not_failure_message
40
+ m = have_descendant(:window)
41
+ e = app.window
42
+
43
+ refute m.does_not_match?(app)
44
+ assert_equal "Expected #{app.inspect} to NOT have descendent #{e.inspect}", m.failure_message_for_should_not
45
+ end
46
+
47
+ def test_have_descendent_description
48
+ m = have_descendent(:button)
49
+ assert_equal 'should have a descendent matching Button', m.description
50
+ end
51
+
52
+
53
+
54
+ def test_shortly_have_child_should_failure_message
55
+ m = shortly_have_child(:button, timeout: 0) { }
56
+ e = app.main_window.slider
57
+
58
+ refute m.matches?(e)
59
+ assert_equal "Expected #{e.inspect} to have child Button[✔] before a timeout occurred",
60
+ m.failure_message_for_should
61
+ end
62
+
63
+ def test_shortly_have_child_should_not_failure_message
64
+ m = shortly_have_child(:window)
65
+ e = app
66
+
67
+ refute m.does_not_match?(e)
68
+ assert_equal "Expected #{e.inspect} to NOT have child #{e.window.inspect} before a timeout occurred",
69
+ m.failure_message_for_should_not
70
+ end
71
+
72
+ def test_shortly_have_child_description
73
+ m = shortly_have_child(:button)
74
+ assert_equal 'should have a child that matches Button before a timeout occurs', m.description
75
+ end
76
+
77
+
78
+
79
+ def test_shortly_have_descendent_should_failure_message
80
+ m = shortly_have_descendent(:button, timeout: 0)
81
+ e = app.main_window.slider
82
+
83
+ refute m.matches?(e)
84
+ assert_equal "Expected #{e.inspect} to have descendent Button before a timeout occurred",
85
+ m.failure_message_for_should
86
+ end
87
+
88
+ def test_shortly_have_descendent_should_not_failure_message
89
+ m = shortly_have_descendent(:window)
90
+ e = app
91
+
92
+ refute m.does_not_match?(e)
93
+ assert_equal "Expected #{e.inspect} to NOT have descendent #{e.window.inspect} before a timeout occurred",
94
+ m.failure_message_for_should_not
95
+ end
96
+
97
+ def test_shortly_have_descendent_description
98
+ m = shortly_have_descendent(:button)
99
+ assert_equal 'should have a descendent matching Button before a timeout occurs', m.description
100
+ end
101
+
102
+ end