AXElements 0.6.0beta1 → 0.6.0beta2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -70,7 +70,7 @@ task :fixture do
70
70
  end
71
71
 
72
72
  require 'rake/testtask'
73
- Rake::TestTask.new(:test) do |t|
73
+ Rake::TestTask.new do |t|
74
74
  t.libs << 'test' << 'ext/key_coder'
75
75
  t.pattern = 'test/**/test_*.rb'
76
76
  t.ruby_opts = ['-rhelper']
@@ -4,6 +4,27 @@ This document includes instructions on using AXElements' built in
4
4
  tools to help you debug issues with your scripts, or in cases where
5
5
  you might find a bug in AXElements itself or MacRuby.
6
6
 
7
+ ## Visibility
8
+
9
+ Sometimes an object that should be visible to accessibility does not
10
+ show up. Sometimes it will be invisible to the Accessibility Inspector
11
+ and sometimes it will be invisible to AXElements. This is because the
12
+ inspector uses hit testing to find objects and AXElements uses the
13
+ `children` and `parent` attributes (usually). Depending on which part
14
+ of the accessibility protocol is not being implemented correctly, one
15
+ or both tools might fail to work.
16
+
17
+ Fortunately, failures in the accessibility API are few and far
18
+ between. The one big,
19
+ [known issue](http://openradar.appspot.com/6832098) is with menu bar
20
+ items; you cannot work around this issue without hacking into private
21
+ Apple APIs. Specifically, you would need to override built in
22
+ accessibility methods in the class that implement the user interface
23
+ for NSStatusItem, which is a private class; or you could build your
24
+ status bar item as an NSMenuExtra, which is another private class. You
25
+ can find more tips on augmenting accessibility for apps in the
26
+ {file:docs/AccessibilityTips.markdown Accessibility Tips} document.
27
+
7
28
  ## Trees
8
29
 
9
30
  Sometimes you need to see the big picture, the whole UI tree at
@@ -41,8 +62,6 @@ but the text tree dump method uses {Accessibility::DFEnumerator}.
41
62
 
42
63
  ### Dot Graph
43
64
 
44
- __NOTE__: This feature isn't actually done yet. Coming soon, I promise.
45
-
46
65
  For super fancy text trees, AXElements can generate dot graphs for
47
66
  consumption by [Graphviz](http://www.graphviz.org/). In this case, you
48
67
  want to call {Accessibility.graph} and pass the root of the tree you
@@ -62,8 +81,8 @@ AXElements was that you could not search through the menu bar causing
62
81
  a text dump to fail in a very difficult to trace manner.
63
82
 
64
83
  In these cases you will need to use your deductive reasoning to figure
65
- out where the problem is coming from. Fortunately, I have provided
66
- some tools to help you along the way.
84
+ out where the problem is coming from. Fortunately, AXElements has some
85
+ tools to help you along the way.
67
86
 
68
87
  ## All The Way Up
69
88
 
data/lib/AXElements.rb ADDED
@@ -0,0 +1 @@
1
+ require 'ax_elements'
@@ -31,7 +31,9 @@ class << Accessibility
31
31
  #
32
32
  # @return [String]
33
33
  def graph root
34
- raise NotImplementedError, 'Please implement me, :('
34
+ dot = Graph.new(root)
35
+ dot.build!
36
+ dot.to_s
35
37
  end
36
38
 
37
39
  ##
@@ -0,0 +1,118 @@
1
+ ##
2
+ # They see me graphing, they hatin, patrollin they can't catch me graphin' dirty.
3
+ class Accessibility::Graph
4
+
5
+ ##
6
+ # Exploit the ordering of a breadth-first enumeration to simplify the
7
+ # creation of edges for the graph. This only works because the UI
8
+ # hiearchy is a simple tree.
9
+ #
10
+ # @return [Array<Accessibility::Graph::Node>]
11
+ attr_reader :edge_queue
12
+
13
+ ##
14
+ # List of nodes in the UI hierarchy.
15
+ #
16
+ # @return [Array<Accessibility::Graph::Node>]
17
+ attr_reader :nodes
18
+
19
+ ##
20
+ # A node in the UI hierarchy. Used by {Accessibility::Graph} in order
21
+ # to build Graphviz dot graphs.
22
+ class Node
23
+
24
+ # @return [AX::Element]
25
+ attr_reader :ref
26
+
27
+ ##
28
+ # Unique identifier for the node.
29
+ #
30
+ # @return [String]
31
+ attr_reader :id
32
+
33
+ ##
34
+ # Label to use for displaying the node.
35
+ #
36
+ # @return [String]
37
+ attr_reader :label
38
+
39
+ ##
40
+ # Shape to draw the node as.
41
+ #
42
+ # @return [String]
43
+ attr_reader :shape
44
+
45
+ ##
46
+ # Colour to fill the node with.
47
+ #
48
+ # @return [String]
49
+ attr_reader :colour
50
+
51
+ # @param [AX::Element]
52
+ def initialize element
53
+ @ref = element
54
+ @id = "element_#{element.object_id}"
55
+ @label = element.class.to_s
56
+ @shape = 3 # based on size?
57
+ @colour = 3 # rotate a la minitest?
58
+ end
59
+ end
60
+
61
+ ##
62
+ # List of edges in the graph.
63
+ #
64
+ # @return [Hash{Accessibility::Graph::Node=>Accessibility::Graph::Node}]
65
+ attr_reader :edges
66
+
67
+ # @param [AX::Element]
68
+ def initialize root
69
+ @nodes = []
70
+ @edges = {}
71
+ @edge_queue = [:root] # hack
72
+ add_node root
73
+ end
74
+
75
+ ##
76
+ # Construct the list of nodes and edges for the graph...
77
+ def build!
78
+ Accessibility::BFEnumerator.new(nodes.first.ref).each do |element|
79
+ add_node element
80
+ end
81
+ end
82
+
83
+ ##
84
+ #
85
+ #
86
+ # @return [String]
87
+ def to_s
88
+ graph = "digraph {\n"
89
+ graph << nodes_list
90
+ graph << edges_list
91
+ graph << "}\n"
92
+ end
93
+
94
+ def nodes_list
95
+ nodes.reduce('') do |string, node|
96
+ string << "#{node.name} [label=\"#{node.label}\"]\n"
97
+ end
98
+ end
99
+
100
+ def edges_list
101
+ edges.delete_if { |_,v| v == :root } # remove hack
102
+ edges.reduce('') do |string, pair|
103
+ string << "#{pair.second.name} -> #{pair.first.name}\n"
104
+ end
105
+ end
106
+
107
+ def add_node element
108
+ node = Node.new(element)
109
+ nodes << node
110
+ edges[node] = edge_queue.shift
111
+ if element.respond_to? :children
112
+ element.size_of(:children).times do
113
+ edge_queue << node
114
+ end
115
+ end
116
+ end
117
+
118
+ end
@@ -37,7 +37,8 @@ module Accessibility::PPInspector
37
37
  if val.kind_of? NSString
38
38
  return " #{val.inspect}" unless val.empty?
39
39
  else
40
- return " value=#{val.inspect}"
40
+ # we assume that nil is not a legitimate value
41
+ return " value=#{val.inspect}" unless val.nil?
41
42
  end
42
43
  end
43
44
 
@@ -71,7 +72,11 @@ module Accessibility::PPInspector
71
72
  # @return [String]
72
73
  def pp_position
73
74
  position = attribute :position
74
- " (#{position.x}, #{position.y})"
75
+ if position
76
+ " (#{position.x}, #{position.y})"
77
+ else
78
+ ::EMPTY_STRING
79
+ end
75
80
  end
76
81
 
77
82
  ##
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Accessibility
4
4
  # @return [String]
5
- VERSION = '0.6.0beta1'
5
+ VERSION = '0.6.0beta2'
6
6
 
7
7
  # @return [String]
8
8
  CODE_NAME = 'Luxray'
@@ -24,7 +24,10 @@ class TestPPInspector < MiniTest::Unit::TestCase
24
24
  assert_match /value=3.14/, pp_identifier
25
25
 
26
26
  @attribute = ''
27
- assert_match NSString.string, pp_identifier
27
+ assert_match ::EMPTY_STRING, pp_identifier
28
+
29
+ @attribute = nil
30
+ assert_match ::EMPTY_STRING, pp_identifier
28
31
  end
29
32
 
30
33
  def test_identifier_using_title
@@ -73,6 +76,12 @@ class TestPPInspector < MiniTest::Unit::TestCase
73
76
  assert_match /\(3\.14, -5\.0\)/, pp_position
74
77
  end
75
78
 
79
+ # this sometimes happens, even though it shouldn't
80
+ def test_position_is_nil
81
+ @attribute = nil
82
+ assert_equal ::EMPTY_STRING, pp_position
83
+ end
84
+
76
85
  def test_children_pluralizes_properly
77
86
  @size_of = 2
78
87
  assert_match /2 children/, pp_children
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: AXElements
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 5
5
- version: 0.6.0beta1
5
+ version: 0.6.0beta2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mark Rada
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-29 00:00:00 -04:00
12
+ date: 2011-10-02 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -123,6 +123,7 @@ extra_rdoc_files:
123
123
  - README.markdown
124
124
  files:
125
125
  - lib/ax_elements/accessibility/enumerators.rb
126
+ - lib/ax_elements/accessibility/graph.rb
126
127
  - lib/ax_elements/accessibility/language.rb
127
128
  - lib/ax_elements/accessibility/qualifier.rb
128
129
  - lib/ax_elements/accessibility.rb
@@ -139,6 +140,7 @@ files:
139
140
  - lib/ax_elements/notification.rb
140
141
  - lib/ax_elements/version.rb
141
142
  - lib/ax_elements.rb
143
+ - lib/AXElements.rb
142
144
  - lib/minitest/ax_elements.rb
143
145
  - lib/mouse.rb
144
146
  - lib/rspec/expectations/ax_elements.rb