AXElements 1.0.0.beta3 → 1.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/History.markdown +12 -3
- data/README.markdown +2 -8
- data/lib/accessibility/dsl.rb +149 -2
- data/lib/accessibility/version.rb +19 -2
- data/lib/ax/element.rb +7 -4
- data/test/integration/accessibility/test_dsl.rb +11 -0
- data/test/integration/ax/test_element.rb +7 -0
- data/test/sanity/accessibility/test_version.rb +15 -0
- data/test/sanity/ax/test_application.rb +4 -0
- metadata +8 -6
data/.yardopts
CHANGED
data/History.markdown
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
-
#
|
1
|
+
# 0.9.0
|
2
2
|
|
3
3
|
* AXElements can now run on MRI as well as MacRuby
|
4
4
|
|
5
|
+
* Added `DSL#pinch` to simulate pinch gestures
|
6
|
+
* Added `DSL#rotate` to simulate rotation gestures
|
7
|
+
* Added `DSL#swipe` to simulate swipe gestures
|
8
|
+
* Added `DSL#smart_magnify` to simulate smart magnification (two finger double tap)
|
9
|
+
* Added `DSL#horizontal_scroll`
|
10
|
+
* Added `DSL#contextual_menu` hack for finding contextual menus (WIP)
|
5
11
|
* Added `NSScreen.wakeup` to the `NSScreen` class to wake up sleeping displays
|
6
12
|
* Added `Accessibility::SystemInfo` for getting information about the running system
|
7
13
|
- Added a `Battery` module for querying information about the battery status
|
@@ -14,15 +20,17 @@
|
|
14
20
|
* Added `SystemWide.status_items`
|
15
21
|
* Added `SystemWide.desktop`
|
16
22
|
* Added History.markdown to track notable changes
|
23
|
+
* Added CONTRIBUTING.markdown with much less stringent guidelines
|
17
24
|
|
18
|
-
* Moved MiniTest extensions to their own repository
|
19
|
-
* Moved RSpec extensions to their own repository
|
25
|
+
* Moved MiniTest extensions to their own gem/repository [minitest-ax\_elements](https://github.com/AXElements/minitest-ax_elements)
|
26
|
+
* Moved RSpec extensions to their own gem/repository [rspec-ax\_elements](https://github.com/AXElements/rspec-ax_elements)
|
20
27
|
|
21
28
|
* Ported `mouse.rb` to C and moved code to [mouse](https://github.com/AXElements/mouse)
|
22
29
|
* Ported `core.rb` to C and moved code to [accessibility\_core](https://github.com/AXElements/accessibility_core)
|
23
30
|
* Ported `screen_recorder.rb` to C and moved code to [screen\_recorder](https://github.com/AXElements/screen_recorder)
|
24
31
|
|
25
32
|
* Changed `DSL#right_click` to accept a block; block is yielded to between click down and click up events
|
33
|
+
* Changed `AX::Element#rect` to `AX::Element#to_rect`
|
26
34
|
|
27
35
|
* Deprecate `AX::DOCK` constant, use `AX::Application.dock` instead
|
28
36
|
* Remove `Accessibility.application_with_bundle_identifier`; use `AX::Application.new` instead
|
@@ -30,3 +38,4 @@
|
|
30
38
|
* Remove `DSL#subtree_for`; use `Element#inspect_subtree` instead
|
31
39
|
|
32
40
|
* Fixed fetching parameterized attributes through `Element#method_missing`
|
41
|
+
* Fixed `Element#parameterized_attribute` automatically normalizing `Range` parameters
|
data/README.markdown
CHANGED
@@ -179,18 +179,12 @@ disabled by default. In order to enable them you need to set the
|
|
179
179
|
|
180
180
|
## Contributing to AXElements
|
181
181
|
|
182
|
-
|
183
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
184
|
-
* Fork the project
|
185
|
-
* Start a feature/bugfix branch
|
186
|
-
* Commit and push until you are happy with your contribution
|
187
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
188
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
182
|
+
See {file:CONTRIBUTING.markdown}
|
189
183
|
|
190
184
|
|
191
185
|
## Copyright
|
192
186
|
|
193
|
-
Copyright (c) 2010-
|
187
|
+
Copyright (c) 2010-2013, Marketcircle Inc.
|
194
188
|
All rights reserved.
|
195
189
|
|
196
190
|
Redistribution and use in source and binary forms, with or without
|
data/lib/accessibility/dsl.rb
CHANGED
@@ -274,7 +274,7 @@ module Accessibility::DSL
|
|
274
274
|
# @param app [AX::Application]
|
275
275
|
# @return [AX::Window]
|
276
276
|
def show_preferences_window_for app
|
277
|
-
app.show_preferences_window
|
277
|
+
app.application.show_preferences_window
|
278
278
|
end
|
279
279
|
|
280
280
|
##
|
@@ -312,6 +312,31 @@ module Accessibility::DSL
|
|
312
312
|
element.ancestor(:menu).scroll_to element
|
313
313
|
end
|
314
314
|
|
315
|
+
##
|
316
|
+
# @note This is a hack to workaround an AXAPI deficiency
|
317
|
+
# @note This method may move or be renamed in the next release, though
|
318
|
+
# it will not be removed
|
319
|
+
#
|
320
|
+
# Find a contextual menu that is open near the mouses current position
|
321
|
+
#
|
322
|
+
# This method assumes that it is being called in the block of a call to
|
323
|
+
# {#right_click}, and that the contextual menu is going to be very close
|
324
|
+
# to the mouse pointer.
|
325
|
+
#
|
326
|
+
# @return [AX::Menu,nil]
|
327
|
+
def contextual_menu
|
328
|
+
# CAST, just like high school trigonometry! :P
|
329
|
+
c, a, s, t = quads = Array.new(4) { Mouse.current_position }
|
330
|
+
c.x -= 10; c.y += 10
|
331
|
+
a.x += 10; a.y += 10
|
332
|
+
s.x += 10; s.y -= 10
|
333
|
+
t.x -= 10; t.y -= 10
|
334
|
+
elements = quads.map { |quad| element_at_point quad }
|
335
|
+
elements.uniq!
|
336
|
+
elements.map! { |el| el.kind_of?(AX::Menu) ? el : el.ancestor(:menu) }
|
337
|
+
elements.find { |element| element.present? }
|
338
|
+
end
|
339
|
+
|
315
340
|
|
316
341
|
# @!group Polling
|
317
342
|
|
@@ -480,7 +505,7 @@ module Accessibility::DSL
|
|
480
505
|
# @option opts [Number] :wait (0.2) in seconds
|
481
506
|
def move_mouse_to arg, opts = {}
|
482
507
|
duration = opts[:duration] || 0.2
|
483
|
-
if Accessibility.debug? && arg.
|
508
|
+
if Accessibility.debug? && arg.kind_of?(AX::Element)
|
484
509
|
highlight arg, timeout: duration, color: NSColor.orangeColor
|
485
510
|
end
|
486
511
|
Mouse.move_to arg.to_point, duration
|
@@ -530,6 +555,27 @@ module Accessibility::DSL
|
|
530
555
|
sleep wait
|
531
556
|
end
|
532
557
|
|
558
|
+
##
|
559
|
+
# @todo Need to expose the units option? Would allow scrolling by pixel.
|
560
|
+
#
|
561
|
+
# Horizontally scrolls an arbitrary number of lines at the mouses current
|
562
|
+
# point on the screen
|
563
|
+
#
|
564
|
+
# Use a positive number to scroll left, and a negative number to scroll
|
565
|
+
# right.
|
566
|
+
#
|
567
|
+
# If the second argument is provided then the mouse will move to that
|
568
|
+
# point first; the argument must respond to `#to_point`.
|
569
|
+
#
|
570
|
+
# @param lines [Number]
|
571
|
+
# @param obj [#to_point]
|
572
|
+
# @param wait [Number]
|
573
|
+
def horizontal_scroll lines, obj = nil, wait = 0.1
|
574
|
+
move_mouse_to obj, wait: 0 if obj
|
575
|
+
Mouse.horizontal_scroll lines
|
576
|
+
sleep wait
|
577
|
+
end
|
578
|
+
|
533
579
|
##
|
534
580
|
# Perform a regular click.
|
535
581
|
#
|
@@ -608,6 +654,97 @@ module Accessibility::DSL
|
|
608
654
|
sleep wait
|
609
655
|
end
|
610
656
|
|
657
|
+
##
|
658
|
+
# Perform a swipe gesture in the given `direction`
|
659
|
+
#
|
660
|
+
# Valid directions are:
|
661
|
+
#
|
662
|
+
# - `:up`
|
663
|
+
# - `:down`
|
664
|
+
# - `:left`
|
665
|
+
# - `:right`
|
666
|
+
#
|
667
|
+
# An optional second argument can be provided. If the argument
|
668
|
+
# is provided then the mouse pointer will move to that point first.
|
669
|
+
#
|
670
|
+
# @example
|
671
|
+
#
|
672
|
+
# swipe :left, safari.web_area
|
673
|
+
#
|
674
|
+
# @param direction [Symbol]
|
675
|
+
# @param obj [#to_point]
|
676
|
+
def swipe direction, obj = nil, wait = 0.2
|
677
|
+
move_mouse_to obj, wait: 0 if obj
|
678
|
+
Mouse.swipe direction
|
679
|
+
sleep wait
|
680
|
+
end
|
681
|
+
|
682
|
+
##
|
683
|
+
# Perform a pinch gesture in the given `direction`
|
684
|
+
#
|
685
|
+
# You can optionally specify the `magnification` factor and
|
686
|
+
# `position` for the pinch event.
|
687
|
+
#*
|
688
|
+
# Available pinch directions are:
|
689
|
+
#
|
690
|
+
# - `:zoom` or `:expand`
|
691
|
+
# - `:unzoom` or `:contract`
|
692
|
+
#
|
693
|
+
# Magnification is a relative magnification setting. A zoom value of
|
694
|
+
# `1.0` means `1.0` more than the current zoom level. `2.0` would be
|
695
|
+
# `2.0` levels higher than the current zoom.
|
696
|
+
#
|
697
|
+
# You can also optionally specify an object/point on screen for the mouse
|
698
|
+
# pointer to be moved to before the gesture begins.
|
699
|
+
#
|
700
|
+
# @param direction [Symbol]
|
701
|
+
# @param magnification [Float]
|
702
|
+
# @param obj [#to_point]
|
703
|
+
def pinch direction, magnification = 1, obj = nil, wait = 0.2
|
704
|
+
move_mouse_to obj, wait: 0 if obj
|
705
|
+
Mouse.pinch direction, magnification
|
706
|
+
sleep wait
|
707
|
+
end
|
708
|
+
|
709
|
+
##
|
710
|
+
# Perform a rotation gesture in the given `direction` the given `angle` degrees
|
711
|
+
#
|
712
|
+
# Possible directions are:
|
713
|
+
#
|
714
|
+
# - `:cw`, ':clockwise`, ':clock_wise` to rotate in the clockwise
|
715
|
+
# direction
|
716
|
+
# - `:ccw`, ':counter_clockwise`, `:counter_clock_wise` to rotate in
|
717
|
+
# the the counter clockwise direction
|
718
|
+
#
|
719
|
+
# The `angle` parameter is a number of degrees to rotate. There are 360
|
720
|
+
# degrees in a full rotation, as you would expect in Euclidian geometry.
|
721
|
+
#
|
722
|
+
# You can also optionally specify an object/point on screen for the mouse
|
723
|
+
# pointer to be moved to before the gesture begins. The movement will
|
724
|
+
# be instantaneous.
|
725
|
+
#
|
726
|
+
# @param direction [Symbol]
|
727
|
+
# @param angle [Float]
|
728
|
+
# @param obj [#to_point]
|
729
|
+
def rotate direction, angle, obj = nil, wait = 0.2
|
730
|
+
move_mouse_to obj, wait: 0 if obj
|
731
|
+
Mouse.rotate direction, angle
|
732
|
+
sleep wait
|
733
|
+
end
|
734
|
+
|
735
|
+
##
|
736
|
+
# Perform a smart magnify (double tap on trackpad)
|
737
|
+
#
|
738
|
+
# You can optionally specify an object/point on the screen where to perform
|
739
|
+
# the smart magnification. The mouse will move to this point first
|
740
|
+
#
|
741
|
+
# @param obj [#to_point]
|
742
|
+
def smart_magnify obj = nil, wait = 0.2
|
743
|
+
move_mouse_to obj, wait: 0 if obj
|
744
|
+
Mouse.smart_magnify
|
745
|
+
sleep wait
|
746
|
+
end
|
747
|
+
|
611
748
|
|
612
749
|
# @!group Debug Helpers
|
613
750
|
|
@@ -642,6 +779,7 @@ module Accessibility::DSL
|
|
642
779
|
end
|
643
780
|
|
644
781
|
##
|
782
|
+
# @note This method is currently experimental
|
645
783
|
# @note You will need to have GraphViz command line tools installed
|
646
784
|
# in order for this to work.
|
647
785
|
#
|
@@ -708,7 +846,16 @@ module Accessibility::DSL
|
|
708
846
|
# See (ScreenRecorder)[http://rdoc.info/gems/screen_recorder/frames]
|
709
847
|
# for details on the screen recording options
|
710
848
|
#
|
849
|
+
# @example
|
850
|
+
#
|
851
|
+
# file = record do
|
852
|
+
# run_tests
|
853
|
+
# end
|
854
|
+
# `open '#{file}'`
|
855
|
+
#
|
711
856
|
# @param file [String]
|
857
|
+
# @yield
|
858
|
+
# @yieldparam recorder [ScreenRecorder]
|
712
859
|
# @return [String]
|
713
860
|
def record file = nil, &block
|
714
861
|
require 'screen_recorder'
|
@@ -4,8 +4,25 @@
|
|
4
4
|
# The main AXElements namespace.
|
5
5
|
module Accessibility
|
6
6
|
# @return [String]
|
7
|
-
VERSION = '1.0.0.
|
7
|
+
VERSION = '1.0.0.beta4'
|
8
8
|
|
9
9
|
# @return [String]
|
10
|
-
CODE_NAME =
|
10
|
+
CODE_NAME = case RUBY_ENGINE
|
11
|
+
when 'macruby' then 'サンダース'
|
12
|
+
when 'ruby' then 'ブースター'
|
13
|
+
when 'rbx' then 'ブラッキー' # for when rbx has good cext support
|
14
|
+
else 'シャワーズ' # vapor(ware)eon
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# The complete version string for AXElements
|
19
|
+
#
|
20
|
+
# This differs from {Accessibility::VERSION} in that it also
|
21
|
+
# includes `RUBY_ENGINE` information.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
def self.version
|
25
|
+
"#{VERSION}-#{CODE_NAME}"
|
26
|
+
end
|
27
|
+
|
11
28
|
end
|
data/lib/ax/element.rb
CHANGED
@@ -187,7 +187,7 @@ class AX::Element
|
|
187
187
|
# @param attr [#to_sym]
|
188
188
|
# @param param [Object]
|
189
189
|
def parameterized_attribute attr, param
|
190
|
-
param = param.relative_to(@ref.value.size) if
|
190
|
+
param = param.relative_to(@ref.value.size) if param.kind_of? Range
|
191
191
|
@ref.parameterized_attribute(TRANSLATOR.cocoaify(attr), param).to_ruby
|
192
192
|
end
|
193
193
|
|
@@ -264,6 +264,8 @@ class AX::Element
|
|
264
264
|
# As the opposite of {#search}, this also takes filters, and can
|
265
265
|
# be used to find a specific ancestor for the current element.
|
266
266
|
#
|
267
|
+
# Returns `nil` if no ancestor is found.
|
268
|
+
#
|
267
269
|
# @example
|
268
270
|
#
|
269
271
|
# button.ancestor :window # => #<AX::StandardWindow>
|
@@ -272,12 +274,13 @@ class AX::Element
|
|
272
274
|
# @param kind [#to_s]
|
273
275
|
# @param filters [Hash{Symbol=>Object}]
|
274
276
|
# @yield Optional block used for search filtering
|
275
|
-
# @return [AX::Element]
|
277
|
+
# @return [AX::Element,nil]
|
276
278
|
def ancestor kind, filters = {}, &block
|
277
279
|
qualifier = Accessibility::Qualifier.new(kind, filters, &block)
|
278
|
-
element =
|
280
|
+
element = self
|
279
281
|
until qualifier.qualifies? element
|
280
282
|
element = element.attribute :parent
|
283
|
+
return nil unless element
|
281
284
|
end
|
282
285
|
element
|
283
286
|
end
|
@@ -432,7 +435,7 @@ class AX::Element
|
|
432
435
|
def bounds
|
433
436
|
CGRect.new(attribute(:position), attribute(:size))
|
434
437
|
end
|
435
|
-
alias_method :
|
438
|
+
alias_method :to_rect, :bounds
|
436
439
|
|
437
440
|
##
|
438
441
|
# Get the application object for the element.
|
@@ -331,4 +331,15 @@ class TestAccessibilityDSL < MiniTest::Unit::TestCase
|
|
331
331
|
pop_up.menu_item.perform :cancel unless pop_up.children.empty?
|
332
332
|
end
|
333
333
|
|
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
|
+
|
334
345
|
end
|
@@ -10,6 +10,13 @@ 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
|
+
|
13
20
|
def test_search_singular_returns_array
|
14
21
|
result = app.search(:window)
|
15
22
|
assert_kind_of AX::Window, result
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test/runner'
|
2
|
+
require 'accessibility/version'
|
3
|
+
|
4
|
+
class TestAccessibilityVersion < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def test_version_is_ascii_only # RubyGems :(
|
7
|
+
assert_equal Accessibility::VERSION.encode(Encoding::ASCII), Accessibility::VERSION
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_version_method
|
11
|
+
assert_match Accessibility::VERSION, Accessibility.version
|
12
|
+
assert_match Accessibility::ENGINE, Accessibility.version
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: AXElements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta4
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mouse
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 2.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 2.0.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: screen_recorder
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 3.2.
|
69
|
+
version: 3.2.11
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 3.2.
|
77
|
+
version: 3.2.11
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: yard
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- test/sanity/accessibility/test_qualifier.rb
|
177
177
|
- test/sanity/accessibility/test_string.rb
|
178
178
|
- test/sanity/accessibility/test_translator.rb
|
179
|
+
- test/sanity/accessibility/test_version.rb
|
179
180
|
- test/sanity/ax/test_application.rb
|
180
181
|
- test/sanity/ax/test_element.rb
|
181
182
|
- test/sanity/ax/test_systemwide.rb
|
@@ -227,6 +228,7 @@ test_files:
|
|
227
228
|
- test/sanity/accessibility/test_qualifier.rb
|
228
229
|
- test/sanity/accessibility/test_string.rb
|
229
230
|
- test/sanity/accessibility/test_translator.rb
|
231
|
+
- test/sanity/accessibility/test_version.rb
|
230
232
|
- test/sanity/ax/test_application.rb
|
231
233
|
- test/sanity/ax/test_element.rb
|
232
234
|
- test/sanity/ax/test_systemwide.rb
|