win32-autogui 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.gitattributes +1 -0
  2. data/.gitignore +10 -0
  3. data/.yardopts +6 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +60 -0
  6. data/HISTORY.markdown +11 -0
  7. data/LICENSE +20 -0
  8. data/README.markdown +265 -0
  9. data/Rakefile +55 -0
  10. data/TODO.markdown +9 -0
  11. data/VERSION +1 -0
  12. data/config/cucumber.yml +7 -0
  13. data/examples/quicknote/.gitignore +8 -0
  14. data/examples/quicknote/FormAboutU.dfm +44 -0
  15. data/examples/quicknote/FormAboutU.pas +36 -0
  16. data/examples/quicknote/FormMainU.dfm +110 -0
  17. data/examples/quicknote/FormMainU.pas +268 -0
  18. data/examples/quicknote/FormSplashU.dfm +32 -0
  19. data/examples/quicknote/FormSplashU.pas +52 -0
  20. data/examples/quicknote/LICENSE +20 -0
  21. data/examples/quicknote/README.markdown +28 -0
  22. data/examples/quicknote/Rakefile +12 -0
  23. data/examples/quicknote/TODO.markdown +15 -0
  24. data/examples/quicknote/dcu/.gitignore +1 -0
  25. data/examples/quicknote/exe/.gitignore +0 -0
  26. data/examples/quicknote/exe/quicknote.exe +0 -0
  27. data/examples/quicknote/lib/quicknote.rb +140 -0
  28. data/examples/quicknote/quicknote.cfg +37 -0
  29. data/examples/quicknote/quicknote.dof +158 -0
  30. data/examples/quicknote/quicknote.dpr +16 -0
  31. data/examples/quicknote/quicknote.res +0 -0
  32. data/examples/quicknote/spec/quicknote/form_about_spec.rb +50 -0
  33. data/examples/quicknote/spec/quicknote/form_main_spec.rb +274 -0
  34. data/examples/quicknote/spec/quicknote/form_splash_spec.rb +44 -0
  35. data/examples/quicknote/spec/spec.opts +2 -0
  36. data/examples/quicknote/spec/spec_helper.rb +34 -0
  37. data/examples/quicknote/spec/watchr.rb +143 -0
  38. data/examples/skeleton/.gitignore +8 -0
  39. data/examples/skeleton/LICENSE +20 -0
  40. data/examples/skeleton/README.markdown +62 -0
  41. data/examples/skeleton/Rakefile +21 -0
  42. data/examples/skeleton/TODO.markdown +9 -0
  43. data/examples/skeleton/config/cucumber.yml +7 -0
  44. data/examples/skeleton/dcu/.gitignore +1 -0
  45. data/examples/skeleton/exe/.gitignore +1 -0
  46. data/examples/skeleton/features/basic.feature +6 -0
  47. data/examples/skeleton/features/step_definitions/.gitignore +0 -0
  48. data/examples/skeleton/features/step_definitions/application_steps.rb +43 -0
  49. data/examples/skeleton/features/support/env.rb +5 -0
  50. data/examples/skeleton/lib/myapp.rb +73 -0
  51. data/examples/skeleton/spec/myapp/form_about_spec.rb +50 -0
  52. data/examples/skeleton/spec/myapp/form_main_spec.rb +60 -0
  53. data/examples/skeleton/spec/spec.opts +2 -0
  54. data/examples/skeleton/spec/spec_helper.rb +29 -0
  55. data/examples/skeleton/spec/watchr.rb +143 -0
  56. data/features/automating_an_application.feature +11 -0
  57. data/features/step_definitions/.gitignore +0 -0
  58. data/features/step_definitions/calculator_steps.rb +37 -0
  59. data/features/support/env.rb +4 -0
  60. data/lib/win32/autogui.rb +27 -0
  61. data/lib/win32/autogui/application.rb +249 -0
  62. data/lib/win32/autogui/input.rb +238 -0
  63. data/lib/win32/autogui/window.rb +191 -0
  64. data/lib/win32/autogui/windows/window.rb +22 -0
  65. data/spec/applications/calculator.rb +34 -0
  66. data/spec/auto_gui/application_spec.rb +132 -0
  67. data/spec/basic_gem/basic_gem_spec.rb +13 -0
  68. data/spec/spec.opts +2 -0
  69. data/spec/spec_helper.rb +31 -0
  70. data/spec/watchr.rb +144 -0
  71. data/win32-autogui.gemspec +43 -0
  72. metadata +329 -0
@@ -0,0 +1,8 @@
1
+ *.ddp
2
+ *.dsk
3
+ *.log
4
+ *.cfIndex
5
+ *.cfProject
6
+ tmp/aruba
7
+ tags
8
+ rerun.txt
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 GearheadForHire, LLC
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
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,62 @@
1
+ Skeleton README
2
+ ===============
3
+
4
+ This is a template of the file structure needed for jump-starting
5
+ GUI testing with the Win32-autogui RubyGem.
6
+
7
+
8
+ Usage Example
9
+ =============
10
+ Create a new Win32 application testing structure for the binary quicknote.exe.
11
+
12
+ NOTE: Replace 'quicknote' with the name of your application.
13
+
14
+ get the source for Win32-autogui
15
+
16
+ cd ~/workspace
17
+ git clone git://github.com/robertwahler/win32-autogui.git
18
+
19
+ copy the skeleton example to a new folder 'quicknote'
20
+
21
+ cp -r ~/workspace/win32-autogui/examples/skeleton quicknote
22
+
23
+ check it into SCM
24
+
25
+ cd quicknote
26
+ git init
27
+ git add .
28
+ git commit -m "initial commit"
29
+
30
+ rename skeleton app to 'quicknote'
31
+
32
+ git mv lib/myapp.rb lib/quicknote.rb
33
+ git mv spec/myapp spec/quicknote
34
+
35
+ # MyApp => QuickNote
36
+ find . -name *.rb -exec sed -i 's/MyApp/QuickNote/' '{}' +
37
+
38
+ # Myapp => Quicknote
39
+ find . -name *.rb -exec sed -i 's/Myapp/Quicknote/' '{}' +
40
+
41
+ # myapp => quicknote
42
+ find . -name *.rb -exec sed -i 's/myapp/quicknote/' '{}' +
43
+
44
+ customize docs
45
+
46
+ vim README.markdown LICENSE
47
+
48
+ test it
49
+
50
+ rake spec
51
+ rake features
52
+
53
+ commit it
54
+
55
+ git add .
56
+ git commit -m "renamed skelton app to MyApp"
57
+
58
+
59
+ Copyright
60
+ ---------
61
+
62
+ Copyright (c) 2010 GearheadForHire, LLC. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ require 'spec'
6
+ require 'spec/rake/spectask'
7
+ Spec::Rake::SpecTask.new(:spec) do |spec|
8
+ spec.libs << 'lib' << 'spec'
9
+ spec.spec_files = FileList['spec/**/*_spec.rb']
10
+ end
11
+
12
+ require 'cucumber'
13
+ require 'cucumber/rake/task'
14
+ Cucumber::Rake::Task.new(:features) do |task|
15
+ task.cucumber_opts = ["features"]
16
+ end
17
+
18
+ desc "Run specs and features"
19
+ task :test => [:spec, :features]
20
+
21
+ task :default => :test
@@ -0,0 +1,9 @@
1
+ MyApp TODO
2
+ ==========
3
+
4
+ general
5
+ -------
6
+
7
+ testing
8
+ -------
9
+
@@ -0,0 +1,7 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun_opts = rerun.to_s.strip.empty? ? "--format pretty features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
+ std_opts = "#{rerun_opts} --format rerun --out rerun.txt --strict --tags ~@wip"
5
+ %>
6
+ default: <%= std_opts %>
7
+ wip: --tags @wip:3 --wip features
@@ -0,0 +1 @@
1
+ *.dcu
@@ -0,0 +1 @@
1
+ *.exe
@@ -0,0 +1,6 @@
1
+ @application
2
+ Feature: BasicGem
3
+
4
+ This is a placeholder
5
+
6
+ Scenario: Replace or delete this file
@@ -0,0 +1,43 @@
1
+ require 'myapp'
2
+
3
+ include Autogui::Input
4
+
5
+ After('@application') do
6
+ if @application
7
+ @application.close(:wait_for_close => true) if @application.running?
8
+ @application.should be_running
9
+ end
10
+ end
11
+
12
+ Before('@applicaton') do
13
+ @application = Myapp.new
14
+ @application.should_not be_running
15
+
16
+ # debug
17
+ puts "application:"
18
+ puts @application.inspect
19
+ puts "application.combined_text"
20
+ puts @application.combined_text
21
+ end
22
+
23
+ When /^I type in "([^"]*)"$/ do |string|
24
+ @application.set_focus
25
+ type_in(string)
26
+ end
27
+
28
+ # "the window text should match" allows regex in the partial_output, if
29
+ # you don't need regex, use "the output should contain" instead since
30
+ # that way, you don't have to escape regex characters that
31
+ # appear naturally in the output
32
+ Then /^the edit window text should match \/([^\/]*)\/$/ do |partial_output|
33
+ @application.edit_window.text.should =~ /#{partial_output}/
34
+ end
35
+
36
+ Then /^the edit window text should contain exactly "([^"]*)"$/ do |exact_output|
37
+ @application.edit_window.text.should == unescape(exact_output)
38
+ end
39
+
40
+ Then /^the edit window text should contain exactly:$/ do |exact_output|
41
+ @application.edit_window.text.should == exact_output
42
+ end
43
+
@@ -0,0 +1,5 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+
3
+ require 'win32/autogui'
4
+ require 'aruba'
5
+ require 'spec/expectations'
@@ -0,0 +1,73 @@
1
+ require 'win32/autogui'
2
+
3
+ APPNAME="exe\\myapp.exe" # relative path to app using Windows style path
4
+
5
+ class Myapp < Autogui::Application
6
+
7
+ def initialize(name=APPNAME, options = {:title=> "MyApp"})
8
+ super name, options
9
+ end
10
+
11
+ def edit_window
12
+ main_window.children.find {|w| w.window_class == 'TMemo'}
13
+ end
14
+
15
+ def status_bar
16
+ main_window.children.find {|w| w.window_class == 'TStatusBar'}
17
+ end
18
+
19
+ def dialog_about
20
+ Autogui::EnumerateDesktopWindows.new.find do |w|
21
+ w.title.match(/About MyApp/) && (w.pid == pid)
22
+ end
23
+ end
24
+
25
+ def message_dialog_confirm
26
+ Autogui::EnumerateDesktopWindows.new.find do |w|
27
+ w.title.match(/Confirm/) && (w.pid == pid)
28
+ end
29
+ end
30
+
31
+ # Title and class are the same as dialog_overwrite_confirm
32
+ # Use child windows to differentiate
33
+ def dialog_overwrite_confirm
34
+ Autogui::EnumerateDesktopWindows.new.find do |w|
35
+ w.title.match(/^Text File Save$/) &&
36
+ (w.pid == pid) &&
37
+ (w.window_class == "#32770") &&
38
+ (w.combined_text.match(/already exists/))
39
+ end
40
+ end
41
+
42
+ # title and class are the same as dialog_overwrite_confirm
43
+ def file_save_as_dialog
44
+ Autogui::EnumerateDesktopWindows.new.find do |w|
45
+ w.title.match(/Text File Save/) &&
46
+ (w.pid == pid) &&
47
+ (w.window_class == "#32770") &&
48
+ (w.combined_text.match(/Save \&in:/))
49
+ end
50
+ end
51
+
52
+ def file_open_dialog
53
+ Autogui::EnumerateDesktopWindows.new.find do |w|
54
+ w.title.match(/Text File Open/) && (w.pid == pid)
55
+ end
56
+ end
57
+
58
+ def error_dialog
59
+ Autogui::EnumerateDesktopWindows.new.find do |w|
60
+ w.title.match(/^MyApp$/) && (w.pid == pid) && (w.window_class == "#32770")
61
+ end
62
+ end
63
+
64
+ # menu action File, Exit
65
+ def file_exit
66
+ set_focus
67
+ keystroke(VK_N) if message_dialog_confirm
68
+ keystroke(VK_ESCAPE) if file_open_dialog
69
+ keystroke(VK_MENU, VK_F, VK_X)
70
+ keystroke(VK_N) if message_dialog_confirm
71
+ end
72
+
73
+ end
@@ -0,0 +1,50 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ include Autogui::Input
4
+
5
+ describe "FormAbout" do
6
+
7
+ before(:all) do
8
+ @application = Myapp.new
9
+ end
10
+
11
+ after(:all) do
12
+ @application.close(:wait_for_close => true) if @application.running?
13
+ @application.should_not be_running
14
+ end
15
+
16
+ before(:each) do
17
+ @application.dialog_about.should be_nil
18
+ @application.set_focus
19
+ keystroke(VK_MENU, VK_H, VK_A)
20
+ @dialog_about = @application.dialog_about
21
+ @dialog_about.should_not be_nil
22
+ @dialog_about.is_window?.should == true
23
+ end
24
+
25
+ after(:each) do
26
+ @dialog_about.close if @dialog_about.is_window?
27
+ @dialog_about.is_window?.should == false
28
+ end
29
+
30
+ it "should open with the hotkey combination VK_MENU, VK_H, VK_A" do
31
+ @dialog_about.is_window?.should == true
32
+ end
33
+
34
+ it "should close by hitting return" do
35
+ @dialog_about.set_focus
36
+ keystroke(VK_RETURN)
37
+ @application.dialog_about.should be_nil
38
+ end
39
+
40
+ it "should have the title 'About MyApp'" do
41
+ @dialog_about.title.should == "About MyApp"
42
+ end
43
+
44
+ it "should have an 'Ok' button" do
45
+ button = @dialog_about.children.find {|w| w.window_class == 'TButton'}
46
+ button.should_not be_nil
47
+ button.text.should match(/Ok/)
48
+ end
49
+
50
+ end
@@ -0,0 +1,60 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ include Autogui::Input
4
+
5
+ describe "FormMain" do
6
+ before(:all) do
7
+ @debug = false
8
+ @verbose = true
9
+ @application = Myapp.new
10
+ FileUtils.rm_rf(current_dir)
11
+ puts "FormMain before(:all)" if @debug
12
+ puts "application:\n#{@application.inspect}\n" if @debug && @verbose
13
+ puts "application.combined_text:\n #{@application.combined_text}\n" if @debug && @verbose
14
+ end
15
+ before(:each) do
16
+ @application = Myapp.new unless @application.running?
17
+ @application.should be_running
18
+ @application.set_focus
19
+ puts "FormMain before(:each)" if @debug
20
+ end
21
+ after(:all) do
22
+ if @application.running?
23
+ @application.file_exit
24
+ # still running? force it to close
25
+ @application.close(:wait_for_close => true)
26
+ @application.should_not be_running
27
+ end
28
+ puts "FormMain after(:all)" if @debug
29
+ end
30
+ after(:each) do
31
+ if @application.running?
32
+ keystroke(VK_N) if @application.message_dialog_confirm || @application.dialog_overwrite_confirm
33
+ keystroke(VK_ESCAPE) if @application.error_dialog
34
+ end
35
+ puts "FormMain after(:each)" if @debug
36
+ end
37
+
38
+ describe "after startup" do
39
+ it "should have the title 'Myapp" do
40
+ @application.main_window.title.should match(/MyApp/)
41
+ end
42
+ end
43
+
44
+ describe "file exit (VK_MENU, VK_F, VK_X)" do
45
+ it "should prompt and save with modified text" do
46
+ type_in("anything")
47
+ keystroke(VK_MENU, VK_F, VK_X)
48
+ @application.message_dialog_confirm.should_not be_nil
49
+ @application.main_window.is_window?.should == true
50
+ @application.should be_running
51
+ end
52
+ it "should not prompt to save with unmodified text" do
53
+ keystroke(VK_MENU, VK_F, VK_X)
54
+ @application.message_dialog_confirm.should be_nil
55
+ @application.main_window.is_window?.should == false
56
+ @application.should_not be_running
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
@@ -0,0 +1,29 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', __FILE__) unless
2
+ $LOAD_PATH.include? File.expand_path('..', __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) unless
4
+ $LOAD_PATH.include? File.expand_path('../../lib', __FILE__)
5
+
6
+ require 'rubygems'
7
+ require 'win32/autogui'
8
+ require 'myapp'
9
+ require 'spec'
10
+ require 'spec/autorun'
11
+ require 'aruba/api'
12
+
13
+ # aruba helper, returns full path to files in the aruba tmp folder
14
+ def fullpath(filename)
15
+ path = File.expand_path(File.join(current_dir, filename))
16
+ path = `cygpath -w #{path}`.chomp if path.match(/^\/cygdrive/) # cygwin?
17
+ path
18
+ end
19
+
20
+ # return the contents of "filename" in the aruba tmp folder
21
+ def get_file_content(filename)
22
+ in_current_dir do
23
+ IO.read(filename)
24
+ end
25
+ end
26
+
27
+ Spec::Runner.configure do |config|
28
+ config.include Aruba::Api
29
+ end
@@ -0,0 +1,143 @@
1
+ # Watchr: Autotest like functionality
2
+ #
3
+ # gem install watchr
4
+ #
5
+ # Run me with:
6
+ #
7
+ # $ watchr spec/watchr.rb
8
+
9
+ require 'term/ansicolor'
10
+
11
+ $c = Term::ANSIColor
12
+
13
+ def getch
14
+ state = `stty -g`
15
+ begin
16
+ `stty raw -echo cbreak`
17
+ $stdin.getc
18
+ ensure
19
+ `stty #{state}`
20
+ end
21
+ end
22
+
23
+ # --------------------------------------------------
24
+ # Convenience Methods
25
+ # --------------------------------------------------
26
+ def all_feature_files
27
+ Dir['features/*.feature']
28
+ end
29
+
30
+ def all_spec_files
31
+ files = Dir['spec/**/*_spec\.rb']
32
+ end
33
+
34
+ def run(cmd)
35
+
36
+ pid = fork do
37
+ puts "\n"
38
+ print $c.cyan, cmd, $c.clear, "\n"
39
+ exec(cmd)
40
+ end
41
+ Signal.trap('INT') do
42
+ puts "sending KILL to pid: #{pid}"
43
+ Process.kill("KILL", pid)
44
+ end
45
+ Process.waitpid(pid)
46
+
47
+ prompt
48
+ end
49
+
50
+ def run_all
51
+ run_all_specs
52
+ run_default_cucumber
53
+ end
54
+
55
+ # allow cucumber rerun.txt smarts
56
+ def run_default_cucumber
57
+ cmd = "cucumber"
58
+ run(cmd)
59
+ end
60
+
61
+ def run_all_features
62
+ cmd = "cucumber #{all_feature_files.join(' ')}"
63
+ run(cmd)
64
+ end
65
+
66
+ def run_feature(feature)
67
+ cmd = "cucumber #{feature}"
68
+ $last_feature = feature
69
+ run(cmd)
70
+ end
71
+
72
+ def run_last_feature
73
+ run_feature($last_feature) if $last_feature
74
+ end
75
+
76
+ def run_default_spec
77
+ cmd = "spec _1.3.1_ --color --format s ./spec"
78
+ run(cmd)
79
+ end
80
+
81
+ def run_all_specs
82
+ cmd = "spec _1.3.1_ --color --format s #{all_spec_files.join(' ')}"
83
+ p cmd
84
+ run(cmd)
85
+ end
86
+
87
+ def run_spec(spec)
88
+ cmd = "spec _1.3.1_ --color --format s #{spec}"
89
+ $last_spec = spec
90
+ run(cmd)
91
+ end
92
+
93
+ def run_last_spec
94
+ run_spec($last_spec) if $last_spec
95
+ end
96
+
97
+ def prompt
98
+ puts "Ctrl-\\ for menu, Ctrl-C to quit"
99
+ end
100
+
101
+ # init
102
+ $last_feature = nil
103
+ prompt
104
+
105
+ # --------------------------------------------------
106
+ # Watchr Rules
107
+ # --------------------------------------------------
108
+ watch( '^features/(.*)\.feature' ) { run_default_cucumber }
109
+
110
+ #watch( '^bin/(.*)' ) { run_default_cucumber }
111
+ watch( '^lib/(.*)' ) { run_default_cucumber }
112
+
113
+ watch( '^features/step_definitions/(.*)\.rb' ) { run_default_cucumber }
114
+ watch( '^features/support/(.*)\.rb' ) { run_default_cucumber }
115
+
116
+ watch( '^spec/(.*)_spec\.rb' ) { |m| run_spec(m[0]) }
117
+ # specify just the lib files that have specs
118
+ # TODO: This can be determined automatically from the spec file naming convention
119
+ watch( '^lib/(.*)' ) { run_default_spec }
120
+
121
+ # --------------------------------------------------
122
+ # Signal Handling
123
+ # --------------------------------------------------
124
+
125
+ # Ctrl-\
126
+ Signal.trap('QUIT') do
127
+
128
+ puts "\n\nMENU: a = all , f = features s = specs, l = last feature (#{$last_feature ? $last_feature : 'none'}), q = quit\n\n"
129
+ c = getch
130
+ puts c.chr
131
+ if c.chr == "a"
132
+ run_all
133
+ elsif c.chr == "f"
134
+ run_default_cucumber
135
+ elsif c.chr == "s"
136
+ run_all_specs
137
+ elsif c.chr == "q"
138
+ abort("exiting\n")
139
+ elsif c.chr == "l"
140
+ run_last_feature
141
+ end
142
+
143
+ end