gnome_app_driver 0.1.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 (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: []