AXElements 0.6.0beta1 → 0.6.0beta2

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/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