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,16 @@
1
+ program quicknote;
2
+
3
+ uses
4
+ Forms,
5
+ FormMainU in 'FormMainU.pas' {FormMain},
6
+ FormAboutU in 'FormAboutU.pas' {FormAbout},
7
+ FormSplashU in 'FormSplashU.pas' {FormSplash};
8
+
9
+ {$R *.res}
10
+
11
+ begin
12
+ Application.Initialize;
13
+ Application.Title := 'QuickNote';
14
+ Application.CreateForm(TFormMain, FormMain);
15
+ Application.Run;
16
+ 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 = Quicknote.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 QuickNote'" do
41
+ @dialog_about.title.should == "About QuickNote"
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,274 @@
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 = Quicknote.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 = Quicknote.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 'QuickNote - untitled.txt'" do
40
+ @application.main_window.title.should == "QuickNote - untitled.txt"
41
+ end
42
+ it "should have no text" do
43
+ @application.edit_window.text.should == ''
44
+ end
45
+ end
46
+
47
+ describe "editing text" do
48
+ after(:each) do
49
+ @application.file_new(:save => false)
50
+ end
51
+
52
+ it "should add the '+' modified flag to the title" do
53
+ @application.main_window.title.should == "QuickNote - untitled.txt"
54
+ type_in("hello")
55
+ @application.main_window.title.should == "QuickNote - +untitled.txt"
56
+ end
57
+ it "should change the text" do
58
+ @application.edit_window.text.should == ''
59
+ type_in("hello")
60
+ @application.edit_window.text.should == 'hello'
61
+ end
62
+ end
63
+
64
+ describe "file open (VK_MENU, VK_F, VK_O)" do
65
+ before(:each) do
66
+ @filename = "input_file.txt"
67
+ @file_contents = create_file(@filename, "the quick brown fox")
68
+ @application.file_new(:save => false)
69
+ end
70
+ after(:each) do
71
+ keystroke(VK_N) if @application.message_dialog_confirm
72
+ keystroke(VK_ESCAPE) if @application.file_open_dialog
73
+ end
74
+
75
+ it "should prompt to save with modified text" do
76
+ type_in("foobar")
77
+ @application.main_window.title.should match(/\+/)
78
+ keystroke(VK_MENU, VK_F, VK_O)
79
+ @application.message_dialog_confirm.should_not be_nil
80
+ end
81
+ it "should not prompt to save with unmodified text" do
82
+ @application.main_window.title.should_not match(/\+/)
83
+ keystroke(VK_MENU, VK_F, VK_O)
84
+ @application.message_dialog_confirm.should be_nil
85
+ end
86
+
87
+ describe "succeeding" do
88
+ it "should add the filename to the title" do
89
+ @application.main_window.title.should == "QuickNote - untitled.txt"
90
+ @application.file_open(fullpath(@filename), :save => false)
91
+ @application.main_window.title.should == "QuickNote - #{fullpath(@filename)}"
92
+ end
93
+ it "should load the text" do
94
+ @application.file_open(fullpath(@filename), :save => false)
95
+ @application.edit_window.text.should == 'the quick brown fox'
96
+ end
97
+ end
98
+
99
+ describe "failing" do
100
+ it "should show an error dialog with message 'Cannot open file'" do
101
+ type_in("foobar")
102
+ @application.file_open(fullpath("a_bogus_filename.txt"), :save => false)
103
+ @application.error_dialog.should_not be_nil
104
+ @application.error_dialog.combined_text.should match(/Cannot open file/)
105
+ end
106
+ it "should keep existing text" do
107
+ type_in("foobar")
108
+ @application.file_open(fullpath("a_bogus_filename.txt"), :save => false)
109
+ @application.error_dialog.should_not be_nil
110
+ @application.edit_window.text.should == 'foobar'
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "file new (VK_MENU, VK_F, VK_N)" do
116
+ it "should prompt to save modified text" do
117
+ type_in("hello")
118
+ @application.main_window.title.should match(/\+/)
119
+ keystroke(VK_MENU, VK_F, VK_N)
120
+ @application.message_dialog_confirm.should_not be_nil
121
+ end
122
+ it "should not prompt to save with unmodified text" do
123
+ @application.file_new(:save => false)
124
+ @application.main_window.title.should_not match(/\+/)
125
+ keystroke(VK_MENU, VK_F, VK_N)
126
+ @application.message_dialog_confirm.should be_nil
127
+ end
128
+ it "should add the filename 'untitled.txt' to the title" do
129
+ filename = "input_file.txt"
130
+ file_contents = create_file(filename, "the quick brown fox")
131
+ @application.file_open(filename, :save => false)
132
+ @application.main_window.title.downcase.should == "QuickNote - #{fullpath(filename)}".downcase
133
+ @application.file_new(:save => false)
134
+ @application.main_window.title.should == "QuickNote - untitled.txt"
135
+ end
136
+ it "should remove the '+' modified flag from the title" do
137
+ type_in("hello")
138
+ @application.main_window.title.should match(/\+/)
139
+ @application.file_new(:save => false)
140
+ @application.main_window.title.should_not match(/\+/)
141
+ end
142
+ it "should clear the existing text" do
143
+ type_in("hello")
144
+ @application.edit_window.text.should match(/hello/)
145
+ @application.file_new(:save => false)
146
+ @application.edit_window.text.should == ''
147
+ end
148
+ end
149
+
150
+ describe "file save (VK_MENU, VK_F, VK_S)" do
151
+ before(:each) do
152
+ @filename = "input_file.txt"
153
+ @file_contents = create_file(@filename, "original content")
154
+ @application.file_open(fullpath(@filename), :save => false)
155
+ @application.main_window.title.downcase.should == "QuickNote - #{fullpath(@filename)}".downcase
156
+ @application.edit_window.text.should == "original content"
157
+ @application.set_focus
158
+ end
159
+
160
+ it "should do nothing unless modified text" do
161
+ append_to_file(@filename, "sneak in extra content that shouldn't be here")
162
+ contents = get_file_content(@filename)
163
+ contents.should match(/extra content/)
164
+ @application.file_save
165
+ contents.should match(/extra content/)
166
+ @application.edit_window.text.should_not match(/extra content/)
167
+ end
168
+
169
+ describe "succeeding" do
170
+ it "should remove the '+' modified flag from the title" do
171
+ type_in("anything")
172
+ @application.main_window.title.should == "QuickNote - +#{fullpath(@filename)}"
173
+ @application.file_save
174
+ @application.main_window.title.should == "QuickNote - #{fullpath(@filename)}"
175
+ end
176
+ it "should save the text" do
177
+ type_in("foobar")
178
+ @application.edit_window.text.should == "foobar" + "original content"
179
+ @application.file_save
180
+ get_file_content(@filename).should == "foobar" + "original content"
181
+ end
182
+ end
183
+
184
+ describe "failing" do
185
+ before(:each) do
186
+ # set read-only to cause save failure
187
+ in_current_dir do
188
+ `attrib +R #{@filename}`
189
+ end
190
+ end
191
+ after(:each) do
192
+ # cleanup read-only file
193
+ FileUtils.rm_rf(current_dir)
194
+ end
195
+
196
+ it "should show an error dialog with message 'Cannot create file'" do
197
+ type_in("anything")
198
+ @application.file_save
199
+ @application.error_dialog.should_not be_nil
200
+ @application.error_dialog.combined_text.should match(/Cannot create file/)
201
+ end
202
+ it "should keep the '+' modified flag on the title" do
203
+ type_in("anything")
204
+ @application.file_save
205
+ @application.main_window.title.should == "QuickNote - +#{fullpath(@filename)}"
206
+ end
207
+ it "should keep existing text" do
208
+ type_in("anything")
209
+ @application.file_save
210
+ @application.edit_window.text.should == "anything" + "original content"
211
+ end
212
+ end
213
+ end
214
+
215
+ describe "file save as (VK_MENU, VK_F, VK_A)" do
216
+ before(:each) do
217
+ @filename = "original.txt"
218
+ @file_contents = create_file(@filename, "original content")
219
+ @saveas_filename = "newfile.txt"
220
+ create_file(@saveas_filename, "")
221
+ @application.file_open(fullpath(@filename), :save => false)
222
+ end
223
+ after(:each) do
224
+ keystroke(VK_N) if @application.dialog_overwrite_confirm
225
+ keystroke(VK_ESCAPE) if @application.file_save_as_dialog
226
+ end
227
+
228
+ it "should prompt for filename" do
229
+ keystroke(VK_MENU, VK_F, VK_A)
230
+ @application.file_save_as_dialog.should_not be_nil
231
+ end
232
+ it "should confirm file overwrites" do
233
+ type_in("anything")
234
+ keystroke(VK_MENU, VK_F, VK_A)
235
+ @application.clipboard.text = fullpath(@saveas_filename)
236
+ keystroke(VK_CONTROL, VK_V)
237
+ keystroke(VK_RETURN)
238
+ File.exists?(fullpath(@saveas_filename)).should be_true
239
+ @application.dialog_overwrite_confirm.should_not be_nil
240
+ end
241
+ it "should remove the '+' modified flag from the title" do
242
+ type_in("anything")
243
+ @application.main_window.title.should match(/\+/)
244
+ @application.file_save_as(fullpath(@saveas_filename), :overwrite => true)
245
+ @application.main_window.title.should_not match(/\+/)
246
+ end
247
+ it "should add the filename to the title" do
248
+ @application.file_save_as(fullpath(@saveas_filename), :overwrite => true)
249
+ @application.main_window.title.downcase.should == "QuickNote - #{fullpath(@saveas_filename)}".downcase
250
+ end
251
+ it "should save the text" do
252
+ get_file_content(@saveas_filename).should == ''
253
+ @application.file_save_as(fullpath(@saveas_filename), :overwrite => true)
254
+ get_file_content(@saveas_filename).should match(/original content/)
255
+ end
256
+ end
257
+
258
+ describe "file exit (VK_MENU, VK_F, VK_X)" do
259
+ it "should prompt and save with modified text" do
260
+ type_in("anything")
261
+ keystroke(VK_MENU, VK_F, VK_X)
262
+ @application.message_dialog_confirm.should_not be_nil
263
+ @application.main_window.is_window?.should == true
264
+ @application.should be_running
265
+ end
266
+ it "should not prompt to save with unmodified text" do
267
+ keystroke(VK_MENU, VK_F, VK_X)
268
+ @application.message_dialog_confirm.should be_nil
269
+ @application.main_window.is_window?.should == false
270
+ @application.should_not be_running
271
+ end
272
+ end
273
+
274
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ include Autogui::Input
4
+
5
+ describe "FormSplash" do
6
+ after(:all) do
7
+ if @application.running?
8
+ @application.splash.wait_for_close if @application.splash
9
+ @application.file_exit
10
+ # still running? force it to close
11
+ @application.close(:wait_for_close => true)
12
+ @application.should_not be_running
13
+ end
14
+ end
15
+
16
+ describe "startup with no command line parameters" do
17
+ before(:all) do
18
+ # --nosplash is the default, turn it back on
19
+ @application = Quicknote.new :parameters => ''
20
+ @application.should be_running
21
+ end
22
+
23
+ it "should show" do
24
+ @application.splash.should_not be_nil
25
+ end
26
+ it "should close within 5 seconds" do
27
+ @application.splash.should_not be_nil
28
+ seconds = 5
29
+ timeout(seconds) do
30
+ @application.splash.wait_for_close
31
+ end
32
+ @application.splash.should be_nil
33
+ end
34
+ end
35
+
36
+ describe "startup with '--nosplash' command line parameter" do
37
+ it "should not show" do
38
+ @application = Quicknote.new :parameters => '--nosplash'
39
+ @application.should be_running
40
+ @application.splash.should be_nil
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
@@ -0,0 +1,34 @@
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
+ # use development version of win32/autogui
7
+ # remove these lines in production code
8
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) unless
9
+ $LOAD_PATH.include? File.expand_path('../../../../lib', __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'win32/autogui'
13
+ require 'quicknote'
14
+ require 'spec'
15
+ require 'spec/autorun'
16
+ require 'aruba/api'
17
+
18
+ # aruba helper, returns full path to files in the aruba tmp folder
19
+ def fullpath(filename)
20
+ path = File.expand_path(File.join(current_dir, filename))
21
+ path = `cygpath -w #{path}`.chomp if path.match(/^\/cygdrive/) # cygwin?
22
+ path
23
+ end
24
+
25
+ # return the contents of "filename" in the aruba tmp folder
26
+ def get_file_content(filename)
27
+ in_current_dir do
28
+ IO.read(filename)
29
+ end
30
+ end
31
+
32
+ Spec::Runner.configure do |config|
33
+ config.include Aruba::Api
34
+ 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