gnome_app_driver 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (8) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog.md +39 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +92 -0
  6. data/Rakefile +17 -0
  7. data/lib/gnome_app_driver.rb +159 -0
  8. metadata +119 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 10a3a958d03c4ebc90fe78e4159eed230a79e5fa
4
+ data.tar.gz: c8c36cb4b8b50fae9835d632851453577cfa2c35
5
+ SHA512:
6
+ metadata.gz: ff10a7761fc4455f2b6279a0c4db3f40b51c615d058f3e072061d67db7f732c74c91ee17a3ddec8d238724ce2ba60fb26e1e66af4a86a7b1306651b18ed6c123
7
+ data.tar.gz: 694fe0e0cfdd318feddfa1138d294bbed7b37545f943dabfca38d12b80447331a1a5179f4e1fb103300cd2feb207f80fcfaf4da86073327946a2af64b6cf7a54
data/Changelog.md ADDED
@@ -0,0 +1,39 @@
1
+ # Change log
2
+
3
+ ## 0.1.1 / 2017-11-05
4
+
5
+ * Release Ruby-GNOME2 version under a new name: gnome_app_driver
6
+
7
+ ## 0.1.0 / 2017-04-25
8
+
9
+ * Use Ruby-GNOME2 instead of GirFFI to provide GLib bindings
10
+
11
+ ## 0.0.7 / 2016-10-16
12
+
13
+ * Depend on GirFFI 0.11.x
14
+
15
+ ## 0.0.6 / 2016-03-23
16
+
17
+ * Depend on GirFFI 0.10.x
18
+
19
+ ## 0.0.5 / 2016-02-04
20
+
21
+ * Depend on GirFFI 0.9.x
22
+ * Fix boot failure handling
23
+
24
+ ## 0.0.4 / 2015-12-12
25
+
26
+ * Loosen dependencies
27
+
28
+ ## 0.0.3 / 2015-10-29
29
+
30
+ * Ensure frame is focused by waiting for it to be :active
31
+
32
+ ## 0.0.2 / 2015-09-20
33
+
34
+ * Print self during recursive inspect
35
+ * Update dependencies
36
+
37
+ ## 0.0.1 / 2015-05-29
38
+
39
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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
+ # Ruby-GNOME2 App Driver
2
+
3
+ Test driver for Ruby-GNOME2 applications using Atspi. 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 'gnome_app_driver'
14
+
15
+ describe 'The application' do
16
+ before do
17
+ @driver = GnomeAppDriver.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 gnome_app_driver
59
+
60
+ ## Dependencies
61
+
62
+ Ruby-GNOME2 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 Ruby-GNOME2 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-2017 [Matijs van Zuijlen](http://www.matijs.net).
92
+ See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rake/clean'
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+ Rake::TestTask.new(:end_to_end) do |t|
7
+ t.libs = ['lib']
8
+ t.test_files = FileList['test/end_to_end/*_test.rb']
9
+ t.warning = true
10
+ end
11
+
12
+ task all: [:end_to_end]
13
+ end
14
+
15
+ task test: 'test:all'
16
+
17
+ task default: 'test'
@@ -0,0 +1,159 @@
1
+ require 'gobject-introspection'
2
+
3
+ # Namespace for Atspi classes. Autoloading with GObjectIntrospection is set up
4
+ # here.
5
+ module Atspi
6
+ class << self
7
+ def const_missing(name)
8
+ init
9
+ if const_defined?(name)
10
+ const_get(name)
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def init
17
+ class << self
18
+ remove_method(:init)
19
+ remove_method(:const_missing)
20
+ end
21
+ loader = GObjectIntrospection::Loader.new(self)
22
+ loader.load('Atspi')
23
+ end
24
+ end
25
+ end
26
+
27
+ # Utility monkey-patches for the Atspi::Accessible class
28
+ module AtspiAccessiblePatches
29
+ def each_child
30
+ child_count.times do |i|
31
+ child = get_child_at_index i
32
+ yield child if child
33
+ end
34
+ end
35
+
36
+ def find_role(role, regex = //)
37
+ return self if role == self.role && name =~ regex
38
+ each_child do |child|
39
+ result = child.find_role role, regex
40
+ return result if result
41
+ end
42
+ nil
43
+ end
44
+
45
+ def inspect_recursive(level = 0, maxlevel = 5)
46
+ puts "#{' ' * level} > name: #{name}; role: #{role}"
47
+ each_child do |child|
48
+ child.inspect_recursive(level + 1) unless level >= maxlevel
49
+ end
50
+ end
51
+ end
52
+
53
+ Atspi::Accessible.include AtspiAccessiblePatches
54
+
55
+ # Test driver for the Atspi-enabled applications. Takes care of boot and
56
+ # shutdown, and provides a handle on the GUI's main UI frame.
57
+ class GnomeAppDriver
58
+ def initialize(app_name, app_file: nil, verbose: false)
59
+ @app_file = app_file || "bin/#{app_name}"
60
+ @lib_dir = 'lib'
61
+ @app_name = app_name
62
+ @pid = nil
63
+ @verbose = verbose
64
+ @frame = nil
65
+ @thread = nil
66
+ end
67
+
68
+ attr_reader :frame
69
+
70
+ def boot(test_timeout: 30, exit_timeout: 10, arguments: [])
71
+ raise 'Already booted' if @pid
72
+
73
+ spawn_process(arguments)
74
+
75
+ @cleanup = false
76
+
77
+ @frame = find_and_focus_frame
78
+
79
+ @thread = Thread.new do
80
+ wait_for('test to be done', test_timeout) { @cleanup }
81
+ wait_for('pid to go away', exit_timeout) { !@pid }
82
+ kill_process if @pid
83
+ end
84
+ end
85
+
86
+ def spawn_process(arguments)
87
+ command = "ruby -I#{@lib_dir} #{@app_file} #{arguments.join(' ')}"
88
+ log "About to spawn: `#{command}`"
89
+ @pid = Process.spawn command
90
+ end
91
+
92
+ def press_ctrl_q
93
+ Atspi.generate_keyboard_event(37, nil, :press)
94
+ Atspi.generate_keyboard_event(24, nil, :pressrelease)
95
+ Atspi.generate_keyboard_event(37, nil, :release)
96
+ end
97
+
98
+ def cleanup
99
+ status = exit_status
100
+ @pid = nil
101
+ @thread.join if @thread
102
+ status
103
+ end
104
+
105
+ private
106
+
107
+ def find_and_focus_frame
108
+ acc = wait_for('app to appear', 10) { find_app }
109
+ raise 'App not found' unless acc
110
+
111
+ frame = acc.get_child_at_index 0
112
+ role = frame.role
113
+ raise "Frame has unexpected role #{role.inspect}" unless role == :frame
114
+
115
+ wait_for('frame to be focused', 10) do
116
+ frame.state_set.contains(Atspi::StateType::ACTIVE)
117
+ end
118
+
119
+ frame
120
+ end
121
+
122
+ def kill_process
123
+ log "About to kill child process #{@pid}"
124
+ Process.kill 'KILL', @pid
125
+ end
126
+
127
+ def log(message)
128
+ warn message if @verbose
129
+ end
130
+
131
+ def find_app
132
+ desktop = Atspi.get_desktop(0)
133
+ desktop.each_child do |child|
134
+ return child if child.name == @app_name
135
+ end
136
+ nil
137
+ end
138
+
139
+ # TODO: Use timeout
140
+ def wait_for(description, _timeout)
141
+ start = Time.now
142
+ result = nil
143
+ # Try for 0.01 * 50 * (50 + 1) / 2 = 12.75 seconds
144
+ 50.times do |num|
145
+ result = yield
146
+ break if result
147
+ sleep 0.01 * (num + 1)
148
+ end
149
+ log "Waited #{Time.now - start} seconds for #{description}"
150
+ result
151
+ end
152
+
153
+ def exit_status
154
+ return unless @pid
155
+ @cleanup = true
156
+ _, status = Process.wait2 @pid
157
+ status
158
+ end
159
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gnome_app_driver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Matijs van Zuijlen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gobject-introspection
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: gtk3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '12.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '12.0'
83
+ description:
84
+ email:
85
+ - matijs@matijs.net
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - Changelog.md
91
+ - Gemfile
92
+ - LICENSE
93
+ - README.md
94
+ - Rakefile
95
+ - lib/gnome_app_driver.rb
96
+ homepage: http://www.github.com/mvz/ruby-gnome2_app_driver
97
+ licenses: []
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.6.13
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Test Ruby-GNOME2 applications using Atspi
119
+ test_files: []