AXElements 1.0.0.alpha7 → 1.0.0.alpha8

Sign up to get free protection for your applications and to get access to all the features.
data/History.markdown CHANGED
@@ -1,5 +1,9 @@
1
1
  # 1.0.0
2
2
 
3
+ * Added History.markdown to track notable changes
4
+
5
+ * Ported `mouse.rb` to C and moved code to [MRMouse](https://github.com/ferrous26/MRMouse)
6
+
3
7
  * Remove `Accessibility.application_with_bundle_identifier`; use `AX::Application.new` instead
4
8
  * Remove `Accessibility.application_with_name; use `AX::Application.new` instead
5
9
  * Remove `DSL#subtree_for`; use `Element#inspect_subtree` instead
@@ -47,7 +47,7 @@ class Accessibility::Graph
47
47
 
48
48
  def identifier
49
49
  klass = @element.class.to_s.split(NAMESPACE).last
50
- ident = @element.pp_identifier.dup
50
+ ident = @element.pp_identifier.to_s.dup
51
51
  if ident.length > 12
52
52
  ident = "#{ident[0...12]}..."
53
53
  end
@@ -58,9 +58,13 @@ class Accessibility::Graph
58
58
  end
59
59
 
60
60
  def shape
61
- (@element.attribute(:focused) && OCTAGON) ||
62
- (@element.actions.empty? && OVAL) ||
63
- BOX
61
+ if @element.attributes.include?(:focused) && @element.attribute(:focused)
62
+ OCTAGON
63
+ elsif @element.actions.empty?
64
+ OVAL
65
+ else
66
+ BOX
67
+ end
64
68
  end
65
69
 
66
70
  def style
@@ -69,7 +73,7 @@ class Accessibility::Graph
69
73
  return FILLED unless @element.attribute(:enabled)
70
74
  end
71
75
  # bold if focused and no children
72
- if @element.attribute(:focused)
76
+ if @element.attributes.include?(:focused) && @element.attribute(:focused)
73
77
  return BOLD if @element.size_of(:children).zero?
74
78
  end
75
79
  SOLID
@@ -16,7 +16,7 @@ module Accessibility::PrettyPrinter
16
16
  # Create an identifier for the receiver by using various attributes
17
17
  # that should make it very easy to identify the element.
18
18
  #
19
- # @return [String]
19
+ # @return [String,#to_s]
20
20
  def pp_identifier
21
21
  # @note use, or lack of use, of #inspect is intentional for visual effect
22
22
 
@@ -49,8 +49,7 @@ module Accessibility::PrettyPrinter
49
49
  return " id=#{attribute(:identifier)}"
50
50
  end
51
51
 
52
- # @todo should we have other fallbacks?
53
- return EMPTY_STRING
52
+ rescue NoMethodError
54
53
  end
55
54
 
56
55
  ##
@@ -4,7 +4,7 @@
4
4
  # The main AXElements namespace.
5
5
  module Accessibility
6
6
  # @return [String]
7
- VERSION = '1.0.0.alpha7'
7
+ VERSION = '1.0.0.alpha8'
8
8
 
9
9
  # @return [String]
10
10
  CODE_NAME = 'ルナトーン'
data/lib/ax/element.rb CHANGED
@@ -360,7 +360,7 @@ class AX::Element
360
360
  #
361
361
  # @return [String]
362
362
  def inspect
363
- msg = "#<#{self.class}" << pp_identifier
363
+ msg = "#<#{self.class}" << pp_identifier.to_s
364
364
  msg << pp_position if attributes.include? :position
365
365
  msg << pp_children if attributes.include? :children
366
366
  msg << pp_checkbox(:enabled) if attributes.include? :enabled
@@ -226,32 +226,6 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
226
226
  assert @got_called
227
227
  end
228
228
 
229
- def test_dump_works_for_nested_tab_groups
230
- output = dsl.subtree_for app.window.tab_group
231
-
232
- expected = [
233
- ['AX::TabGroup', 0],
234
- ['AX::RadioButton', 1], ['AX::RadioButton', 1], ['AX::TabGroup', 1],
235
- ['AX::RadioButton', 2], ['AX::RadioButton', 2], ['AX::TabGroup', 2],
236
- ['AX::RadioButton', 3], ['AX::RadioButton', 3], ['AX::TabGroup', 3],
237
- ['AX::RadioButton', 4], ['AX::RadioButton', 4],
238
- ['AX::Group', 4],
239
- ['AX::TextField', 5], ['AX::StaticText', 6],
240
- ['AX::TextField' , 5], ['AX::StaticText', 6]
241
- ]
242
-
243
- refute_empty output
244
- output = output.split("\n")
245
-
246
- until output.empty?
247
- line = output.shift
248
- klass, indents = expected.shift
249
- assert_equal indents, line.match(/^\t*/).to_a.first.length, line
250
- line.strip!
251
- assert_match /^\#<#{klass}/, line
252
- end
253
- end
254
-
255
229
  def test_screenshot
256
230
  path = dsl.screenshot
257
231
  assert File.exists? path
@@ -52,4 +52,30 @@ class TestAXElement < MiniTest::Unit::TestCase
52
52
  assert bye.invalid?
53
53
  end
54
54
 
55
+ def test_dump_works_for_nested_tab_groups
56
+ output = app.window.tab_group.inspect_subtree
57
+
58
+ expected = [
59
+ ['AX::TabGroup', 0],
60
+ ['AX::RadioButton', 1], ['AX::RadioButton', 1], ['AX::TabGroup', 1],
61
+ ['AX::RadioButton', 2], ['AX::RadioButton', 2], ['AX::TabGroup', 2],
62
+ ['AX::RadioButton', 3], ['AX::RadioButton', 3], ['AX::TabGroup', 3],
63
+ ['AX::RadioButton', 4], ['AX::RadioButton', 4],
64
+ ['AX::Group', 4],
65
+ ['AX::TextField', 5], ['AX::StaticText', 6],
66
+ ['AX::TextField' , 5], ['AX::StaticText', 6]
67
+ ]
68
+
69
+ refute_empty output
70
+ output = output.split("\n")
71
+
72
+ until output.empty?
73
+ line = output.shift
74
+ klass, indents = expected.shift
75
+ assert_equal indents, line.match(/^\t*/).to_a.first.length, line
76
+ line.strip!
77
+ assert_match /^\#<#{klass}/, line
78
+ end
79
+ end
80
+
55
81
  end
@@ -18,10 +18,10 @@ class TestAccessibilityPrettyPrinter < MiniTest::Unit::TestCase
18
18
  assert_match /value=3.14/, pp_identifier
19
19
 
20
20
  @attribute = ''
21
- assert_match EMPTY_STRING, pp_identifier
21
+ assert_match EMPTY_STRING, pp_identifier.to_s
22
22
 
23
23
  @attribute = nil
24
- assert_match EMPTY_STRING, pp_identifier
24
+ assert_match EMPTY_STRING, pp_identifier.to_s
25
25
  end
26
26
 
27
27
  def test_identifier_using_title
@@ -44,7 +44,7 @@ class TestAccessibilityPrettyPrinter < MiniTest::Unit::TestCase
44
44
  assert_match /roflcopter/, pp_identifier
45
45
 
46
46
  @attribute = NSString.string
47
- assert_equal EMPTY_STRING, pp_identifier
47
+ assert_equal EMPTY_STRING, pp_identifier.to_s
48
48
 
49
49
  @attribute = 26
50
50
  assert_match /26/, pp_identifier
@@ -62,7 +62,7 @@ class TestAccessibilityPrettyPrinter < MiniTest::Unit::TestCase
62
62
 
63
63
  def test_identifier_empty_string_as_final_fallback
64
64
  @attributes = NSArray.array
65
- assert_equal EMPTY_STRING, pp_identifier
65
+ assert_equal EMPTY_STRING, pp_identifier.to_s
66
66
  end
67
67
 
68
68
  def test_position
metadata CHANGED
@@ -2,31 +2,31 @@
2
2
  name: AXElements
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 1.0.0.alpha7
5
+ version: 1.0.0.alpha8
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mark Rada
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-05 00:00:00 Z
12
+ date: 2012-12-08 00:00:00 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: minitest
15
+ name: mouse
16
16
  prerelease: false
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: 4.3.1
23
- type: :development
22
+ version: 1.0.1
23
+ type: :runtime
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 4.3.1
29
+ version: 1.0.1
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: yard
32
32
  prerelease: false
@@ -107,7 +107,6 @@ files:
107
107
  - lib/ax_elements.rb
108
108
  - lib/AXElements.rb
109
109
  - lib/minitest/ax_elements.rb
110
- - lib/mouse.rb
111
110
  - lib/rspec/expectations/ax_elements.rb
112
111
  - ext/accessibility/key_coder/extconf.rb
113
112
  - ext/accessibility/core/core.c
@@ -151,7 +150,6 @@ files:
151
150
  - test/sanity/rspec/expectations/test_ax_elements.rb
152
151
  - test/sanity/test_accessibility.rb
153
152
  - test/sanity/test_ax_elements.rb
154
- - test/sanity/test_mouse.rb
155
153
  - test/test_core.rb
156
154
  - test/helper.rb
157
155
  homepage: http://github.com/Marketcircle/AXElements
@@ -211,6 +209,5 @@ test_files:
211
209
  - test/sanity/rspec/expectations/test_ax_elements.rb
212
210
  - test/sanity/test_accessibility.rb
213
211
  - test/sanity/test_ax_elements.rb
214
- - test/sanity/test_mouse.rb
215
212
  - test/test_core.rb
216
213
  - test/helper.rb
data/lib/mouse.rb DELETED
@@ -1,273 +0,0 @@
1
- framework 'ApplicationServices'
2
- require 'ax_elements/core_graphics_workaround'
3
-
4
-
5
- ##
6
- # This is a first attempt at writing a wrapper around the CoreGraphics event
7
- # taps API provided by OS X. The module provides a simple Ruby interface to
8
- # performing mouse interactions such as moving and clicking.
9
- #
10
- # [Reference](http://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html).
11
- #
12
- # A rewrite is in the works, but in the mean time this code base still works
13
- # despite its warts.
14
- module Mouse
15
- extend self
16
-
17
- ##
18
- # Number of animation steps per second
19
- #
20
- # @return [Number]
21
- FPS = 120
22
-
23
- ##
24
- # @note We keep the number as a rational to try and avoid rounding
25
- # error introduced by the floats, especially MacRuby floats.
26
- #
27
- # Smallest unit of time allowed for an animation step
28
- #
29
- # @return [Number]
30
- QUANTUM = Rational(1, FPS)
31
-
32
- ##
33
- # Available constants for the type of units to use when scrolling
34
- #
35
- # @return [Hash{Symbol=>Fixnum}]
36
- UNIT = {
37
- line: KCGScrollEventUnitLine,
38
- pixel: KCGScrollEventUnitPixel
39
- }
40
-
41
- ##
42
- # The coordinates of the mouse using the flipped coordinate system
43
- #
44
- # Flipped coordinates have the origin in top left corner of the
45
- # primary screen.
46
- #
47
- # @return [CGPoint]
48
- def current_position
49
- CGEventGetLocation(CGEventCreate(nil))
50
- end
51
-
52
- ##
53
- # Move the mouse from the current position to the given point
54
- #
55
- # @param point [CGPoint]
56
- # @param duration [Float] animation duration, in seconds
57
- def move_to point, duration = 0.2
58
- animate KCGEventMouseMoved, KCGMouseButtonLeft, current_position, point, duration
59
- end
60
-
61
- ##
62
- # Click and drag from the current position to the given point
63
- #
64
- # @param point [CGPoint]
65
- # @param duration [Float] animation duration, in seconds
66
- def drag_to point, duration = 0.2
67
- post new_event(KCGEventLeftMouseDown, current_position, KCGMouseButtonLeft)
68
-
69
- animate KCGEventLeftMouseDragged, KCGMouseButtonLeft, current_position, point, duration
70
-
71
- post new_event(KCGEventLeftMouseUp, current_position, KCGMouseButtonLeft)
72
- end
73
-
74
- ##
75
- # @todo Need to double check to see if I introduce any inaccuracies.
76
- #
77
- # Scroll at the current position the given amount of units
78
- #
79
- # Scrolling too much or too little in a period of time will cause the
80
- # animation to look weird, possibly causing the app to mess things up.
81
- #
82
- # A positive `amonut` to scroll will scroll up and a negative `amount`
83
- # will scroll down.
84
- #
85
- # @param amount [Fixnum] number of units to scroll
86
- # @param duration [Float] in seconds
87
- # @param units [Symbol] must be either `:line` or `:pixel`
88
- def scroll amount, duration = 0.2, units = :line
89
- units = UNIT[units] || raise(ArgumentError, "#{units} is not a valid unit")
90
- steps = (FPS * duration).round
91
- current = 0.0
92
- steps.times do |step|
93
- done = (step+1).to_f / steps
94
- scroll = ((done - current)*amount).round
95
- post new_scroll_event(units, 1, scroll)
96
- sleep QUANTUM
97
- current += scroll.to_f / amount
98
- end
99
- end
100
-
101
- ##
102
- # @api semipublic
103
- #
104
- # Perform a down click
105
- #
106
- # You should follow this up with a call to {#click_up} to finish the click.
107
- #
108
- # @param point [CGPoint]
109
- # @param duration [Number]
110
- def click_down point = current_position, duration = 12
111
- event = new_event KCGEventLeftMouseDown, point, KCGMouseButtonLeft
112
- post event
113
- sleep QUANTUM*duration
114
- end
115
-
116
- ##
117
- # @api semipublic
118
- #
119
- # Perform an up click
120
- #
121
- # This should only be called after a call to {#click_down} to finish
122
- # the click event.
123
- #
124
- # @param point [CGPoint]
125
- def click_up point = current_position
126
- event = new_event KCGEventLeftMouseUp, point, KCGMouseButtonLeft
127
- post event
128
- end
129
-
130
- ##
131
- # Standard secondary click, sometimes called a "right click"
132
- #
133
- # Default position is the current position.
134
- #
135
- # @param point [CGPoint]
136
- # @param duration [Number] in seconds
137
- def secondary_click point = current_position, duration = 12
138
- event = new_event KCGEventRightMouseDown, point, KCGMouseButtonRight
139
- post event
140
- sleep QUANTUM*duration
141
- set_type event, KCGEventRightMouseUp
142
- post event
143
- end
144
- alias_method :right_click, :secondary_click
145
-
146
- ##
147
- # @api semipublic
148
- #
149
- # Generate a multi click event at the given position
150
- #
151
- # `num_clicks` is the number of clicks for the event, where a value of `2'
152
- # corresponds to a double click, `3` corresponds to a triple click, etc.
153
- #
154
- # However, I've only tested with a double and triple click, for which you
155
- # can just call {#double_click} and {#triple_click} instead.
156
- #
157
- # @param num_clicks [Fixnum]
158
- # @param point [CGPoint]
159
- def multi_click num_clicks, point = current_position
160
- event = new_event KCGEventLeftMouseDown, point, KCGMouseButtonLeft
161
- CGEventSetIntegerValueField(event, KCGMouseEventClickState, num_clicks)
162
- set_type event, KCGEventLeftMouseDown
163
- post event
164
- set_type event, KCGEventLeftMouseUp
165
- post event
166
- end
167
-
168
- ##
169
- # A standard double click
170
- #
171
- # Defaults to clicking at the current position.
172
- #
173
- # @param point [CGPoint]
174
- def double_click point = current_position
175
- # some apps still expect to receive the single click event first
176
- # and then the double click event
177
- multi_click 1, point
178
- multi_click 2, point
179
- end
180
-
181
- ##
182
- # A standard triple click
183
- #
184
- # Defaults to clicking at the current position.
185
- #
186
- # @param point [CGPoint]
187
- def triple_click point = current_position
188
- # some apps still expect to receive the single click event first
189
- # and then the double and triple click events
190
- double_click
191
- multi_click 3, point
192
- end
193
-
194
- ##
195
- # Click with an arbitrary mouse button
196
- #
197
- # Numbers are used to map the mouse buttons. At the time of writing,
198
- # the documented values are:
199
- #
200
- # - KCGMouseButtonLeft = 0
201
- # - KCGMouseButtonRight = 1
202
- # - KCGMouseButtonCenter = 2
203
- #
204
- # And the rest are not documented! Though they should be easy enough
205
- # to figure out. See the `CGMouseButton` enum in the reference
206
- # documentation for the most up to date list.
207
- #
208
- # @param point [CGPoint]
209
- # @param button [Number]
210
- # @param duration [Number]
211
- def arbitrary_click point = current_position, button = KCGMouseButtonCenter, duration = 12
212
- event = new_event KCGEventOtherMouseDown, point, button
213
- post event
214
- sleep QUANTUM*duration
215
- set_type event, KCGEventOtherMouseUp
216
- post event
217
- end
218
- alias_method :other_click, :arbitrary_click
219
-
220
-
221
- private
222
-
223
- ##
224
- # Executes a mouse movement animation. It can be a simple cursor
225
- # move or a drag depending on what is passed to `type`.
226
- def animate type, button, from, to, duration
227
- current = from
228
- xstep = (to.x - current.x) / (FPS * duration)
229
- ystep = (to.y - current.y) / (FPS * duration)
230
- start = NSDate.date
231
-
232
- until close_enough?(current, to)
233
- remaining = to.x - current.x
234
- current.x += xstep.abs > remaining.abs ? remaining : xstep
235
-
236
- remaining = to.y - current.y
237
- current.y += ystep.abs > remaining.abs ? remaining : ystep
238
-
239
- post new_event(type, current, button)
240
-
241
- sleep QUANTUM
242
- break if NSDate.date.timeIntervalSinceDate(start) > 5.0
243
- current = current_position
244
- end
245
- end
246
-
247
- def close_enough? current, target
248
- x = current.x - target.x
249
- y = current.y - target.y
250
- ((x**2)+(y**2)) <= 1
251
- end
252
-
253
- def new_event event, position, button
254
- CGEventCreateMouseEvent(nil, event, position, button)
255
- end
256
-
257
- # @param [Fixnum] wheel which scroll wheel to use (value between 1-3)
258
- def new_scroll_event units, wheel, amount
259
- CGEventCreateScrollWheelEvent(nil, units, wheel, amount)
260
- end
261
-
262
- def post event
263
- CGEventPost(KCGHIDEventTap, event)
264
- end
265
-
266
- ##
267
- # Change the event type for an instance of an event. This is how you would
268
- # reuse a specific event. In most cases, reusing events is a necessity.
269
- def set_type event, state
270
- CGEventSetType(event, state)
271
- end
272
-
273
- end
@@ -1,22 +0,0 @@
1
- require 'test/runner'
2
- require 'mouse'
3
-
4
- class TestMouseModule < MiniTest::Unit::TestCase
5
-
6
- def distance point1, point2
7
- x = point1.x - point2.x
8
- y = point1.y - point2.y
9
- Math.sqrt((x**2) + (y**2))
10
- end
11
-
12
- def test_move_to
13
- point = CGPoint.new(100, 100)
14
- Mouse.move_to point
15
- assert_in_delta 0, distance(point,Mouse.current_position), 1.0
16
-
17
- point = CGPoint.new(rand(700)+150, rand(500)+100)
18
- Mouse.move_to point
19
- assert_in_delta 0, distance(point,Mouse.current_position), 1.0
20
- end
21
-
22
- end