atspi_app_driver 0.0.1

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 (7) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +92 -0
  4. data/Rakefile +2 -0
  5. data/gems.rb +3 -0
  6. data/lib/atspi_app_driver.rb +132 -0
  7. metadata +90 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 509b787e88981adcc2bf586c981e47c7d2739584
4
+ data.tar.gz: 392fe1910cac1d8726bd770205a3328af8a9691b
5
+ SHA512:
6
+ metadata.gz: b283db9f341667f37781ed06e5e0a85dd080fa286adc6735d05ec333e5be4d4412c63ba44aabcd5f77c2945cddc6487a10b7364900b983e8fda1f5d00c4c3f0f
7
+ data.tar.gz: c3b2d4150d7a2fede09ead523846335454415512f38ca7416d7a2d61f39a1d1d2e2c0954344040987e0a89b25a119b8a23c035b55f516b4802d402e0181ae74c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2015 Matijs van Zuijlen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # Atspi App Driver
2
+
3
+ Test driver for the Atspi-enabled applications. Takes care of boot and
4
+ shutdown, and provides a handle on the GUI's main UI frame.
5
+
6
+ ## Usage
7
+
8
+ This driver assumes your application lives in `bin/` and uses additional ruby
9
+ code in `lib/`.
10
+
11
+ Say, your application is called `foo`. Then, in your tests, do something like this:
12
+
13
+ require 'atspi_app_driver'
14
+
15
+ describe 'The application' do
16
+ before do
17
+ @driver = AtspiAppDriver.new('foo')
18
+
19
+ # This will boot `ruby -Ilib bin/foo`, wait for its main window to appear,
20
+ # and focus it.
21
+ @driver.boot
22
+ end
23
+
24
+ it 'does stuff' do
25
+ # Fetch the main window's atspi object
26
+ frame = @driver.frame
27
+
28
+ # You can now interact with the window's objects
29
+
30
+ # Select item matching /bar/ from combo box:
31
+ box = frame.find_role :combo_box
32
+ item = box.find_role :menu_item, /bar/
33
+ box.get_action_name(0).must_equal 'press'
34
+ box.do_action 0
35
+ item.get_action_name(0).must_equal 'click'
36
+ item.do_action 0
37
+
38
+ # Fetch contents of a text box
39
+ textbox = frame.find_role :text
40
+ textbox.get_text(0, 100).must_equal 'Foo bar baz'
41
+
42
+ # Quit application
43
+ @driver.press_ctrl_q
44
+
45
+ # Check exit status
46
+ status = @driver.cleanup
47
+ status.exitstatus.must_equal 0
48
+ end
49
+
50
+ after do
51
+ # Ensure application is cleaned up
52
+ @driver.cleanup
53
+ end
54
+ end
55
+
56
+ ## Installation
57
+
58
+ gem install atspi_app_driver
59
+
60
+ ## Dependencies
61
+
62
+ Atspi App Driver needs atspi's GIR data, and needs to be able to interact with
63
+ the application via atspi and atk. The below are suggested packages to install.
64
+ Corrections are welcome, of course.
65
+
66
+ ### Debian
67
+
68
+ This should work on Debian unstable.
69
+
70
+ sudo apt-get install dbus
71
+ sudo apt-get install libgirepository1.0-dev gobject-introspection
72
+ sudo apt-get install gir1.2-atspi-2.0 libatk-adaptor
73
+
74
+ ### Ubuntu
75
+
76
+ Please try the instructions for Debian. This will probably not work on Ubuntu
77
+ 12.04. Again, corrections and additions are welcome.
78
+
79
+ ### Other OS
80
+
81
+ To be determined. Please contribute back your experience in getting Atspi App
82
+ Driver working on your favorite operation system.
83
+
84
+ ## Contributing
85
+
86
+ Contributions are welcome! Please feel free to create issues or pull requests
87
+ on GitHub.
88
+
89
+ ## License
90
+
91
+ Copyright © 2015 [Matijs van Zuijlen](http://www.matijs.net).
92
+ See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'rake/clean'
2
+ require 'bundler/gem_tasks'
data/gems.rb ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,132 @@
1
+ require 'gir_ffi'
2
+
3
+ GirFFI.setup :Atspi
4
+ Atspi.load_class :Accessible
5
+
6
+ # Utility monkey-patches for the Atspi::Accessible class
7
+ module AtspiAccessiblePatches
8
+ def each_child
9
+ child_count.times do |i|
10
+ child = get_child_at_index i
11
+ yield child if child
12
+ end
13
+ end
14
+
15
+ def find_role role, regex = //
16
+ return self if role == self.role && name =~ regex
17
+ each_child do |child|
18
+ result = child.find_role role, regex
19
+ return result if result
20
+ end
21
+ nil
22
+ end
23
+
24
+ def inspect_recursive level = 0, maxlevel = 4
25
+ each_child do |child|
26
+ puts "#{' ' * level} > name: #{child.name}; role: #{child.role}"
27
+ child.inspect_recursive(level + 1) unless level >= maxlevel
28
+ end
29
+ end
30
+ end
31
+
32
+ Atspi::Accessible.include AtspiAccessiblePatches
33
+
34
+ # Test driver for the Atspi-enabled applications. Takes care of boot and
35
+ # shutdown, and provides a handle on the GUI's main UI frame.
36
+ class AtspiAppDriver
37
+ def initialize app_name, verbose: false
38
+ @app_file = "bin/#{app_name}"
39
+ @lib_dir = 'lib'
40
+ @app_name = app_name
41
+ @pid = nil
42
+ @verbose = verbose
43
+ @frame = nil
44
+ end
45
+
46
+ attr_reader :frame
47
+
48
+ def boot test_timeout: 30, exit_timeout: 10, arguments: []
49
+ raise 'Already booted' if @pid
50
+
51
+ spawn_process(arguments)
52
+
53
+ @cleanup = false
54
+
55
+ @frame = find_and_focus_frame
56
+
57
+ @thread = Thread.new do
58
+ wait_for('test to be done', test_timeout) { @cleanup }
59
+ wait_for('pid to go away', exit_timeout) { !@pid }
60
+ kill_process if @pid
61
+ end
62
+ end
63
+
64
+ def spawn_process arguments
65
+ command = "ruby -I#{@lib_dir} #{@app_file} #{arguments.join(' ')}"
66
+ log "About to spawn: `#{command}`"
67
+ @pid = Process.spawn command
68
+ end
69
+
70
+ def press_ctrl_q
71
+ Atspi.generate_keyboard_event(37, nil, :press)
72
+ Atspi.generate_keyboard_event(24, nil, :pressrelease)
73
+ Atspi.generate_keyboard_event(37, nil, :release)
74
+ end
75
+
76
+ def cleanup
77
+ status = exit_status
78
+ @pid = nil
79
+ @thread.join if @thread
80
+ status
81
+ end
82
+
83
+ private
84
+
85
+ def find_and_focus_frame
86
+ acc = wait_for('app to appear', 10) { find_app }
87
+ raise 'App not found' unless acc
88
+
89
+ frame = acc.get_child_at_index 0
90
+ frame.role.must_equal :frame
91
+ frame.grab_focus
92
+
93
+ frame
94
+ end
95
+
96
+ def kill_process
97
+ log "About to kill child process #{@pid}"
98
+ Process.kill 'KILL', @pid
99
+ end
100
+
101
+ def log message
102
+ warn message if @verbose
103
+ end
104
+
105
+ def find_app
106
+ desktop = Atspi.get_desktop(0)
107
+ desktop.each_child do |child|
108
+ return child if child.name == @app_name
109
+ end
110
+ nil
111
+ end
112
+
113
+ # TODO: User timeout
114
+ def wait_for description, _timeout
115
+ start = Time.now
116
+ # Try for 0.01 * 50 * (50 + 1) / 2 = 12.75 seconds
117
+ value = 50.times.each do |num|
118
+ result = yield
119
+ break result if result
120
+ sleep 0.01 * (num + 1)
121
+ end
122
+ log "Waited #{Time.now - start} seconds for #{description}"
123
+ value
124
+ end
125
+
126
+ def exit_status
127
+ return unless @pid
128
+ @cleanup = true
129
+ _, status = Process.wait2 @pid
130
+ status
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: atspi_app_driver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matijs van Zuijlen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gir_ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.9
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.9
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.1'
55
+ description:
56
+ email:
57
+ - matijs@matijs.net
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - gems.rb
66
+ - lib/atspi_app_driver.rb
67
+ homepage: http://www.github.com/mvz/atspi_app_driver
68
+ licenses: []
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.4.5
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Test GNOME applications using Atspi
90
+ test_files: []