AXElements 0.9.0 → 1.0.0.alpha

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