keyrack 0.3.0.pre → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +8 -15
  4. data/Guardfile +6 -0
  5. data/LICENSE.txt +4 -2
  6. data/Rakefile +2 -56
  7. data/keyrack.gemspec +22 -104
  8. data/lib/keyrack.rb +9 -1
  9. data/lib/keyrack/database.rb +64 -98
  10. data/lib/keyrack/event.rb +13 -0
  11. data/lib/keyrack/exceptions.rb +4 -0
  12. data/lib/keyrack/group.rb +225 -0
  13. data/lib/keyrack/migrator.rb +45 -0
  14. data/lib/keyrack/runner.rb +98 -44
  15. data/lib/keyrack/site.rb +92 -0
  16. data/lib/keyrack/ui/console.rb +234 -95
  17. data/lib/keyrack/utils.rb +0 -18
  18. data/lib/keyrack/version.rb +3 -0
  19. data/test/fixtures/database-3.dat +0 -0
  20. data/test/helper.rb +11 -1
  21. data/test/integration/test_interactive_console.rb +139 -0
  22. data/test/unit/store/test_filesystem.rb +21 -0
  23. data/test/unit/store/test_ssh.rb +32 -0
  24. data/test/unit/test_database.rb +201 -0
  25. data/test/unit/test_event.rb +41 -0
  26. data/test/unit/test_group.rb +703 -0
  27. data/test/unit/test_migrator.rb +105 -0
  28. data/test/unit/test_runner.rb +407 -0
  29. data/test/unit/test_site.rb +181 -0
  30. data/test/unit/test_store.rb +13 -0
  31. data/test/unit/test_utils.rb +8 -0
  32. data/test/unit/ui/test_console.rb +495 -0
  33. metadata +98 -94
  34. data/Gemfile.lock +0 -45
  35. data/TODO +0 -4
  36. data/VERSION +0 -1
  37. data/features/console.feature +0 -103
  38. data/features/step_definitions/keyrack_steps.rb +0 -61
  39. data/features/support/env.rb +0 -16
  40. data/test/fixtures/aes +0 -0
  41. data/test/fixtures/config.yml +0 -4
  42. data/test/fixtures/id_rsa +0 -54
  43. data/test/keyrack/store/test_filesystem.rb +0 -25
  44. data/test/keyrack/store/test_ssh.rb +0 -36
  45. data/test/keyrack/test_database.rb +0 -111
  46. data/test/keyrack/test_runner.rb +0 -111
  47. data/test/keyrack/test_store.rb +0 -15
  48. data/test/keyrack/test_utils.rb +0 -41
  49. data/test/keyrack/ui/test_console.rb +0 -308
@@ -0,0 +1,105 @@
1
+ require 'helper'
2
+
3
+ class TestMigrator < Test::Unit::TestCase
4
+ test "migrating version 3 to version 4" do
5
+ database = {
6
+ 'groups' => {
7
+ 'top' => {
8
+ 'name' => 'top',
9
+ 'sites' => {},
10
+ 'groups' => {
11
+ 'Starfleet' => {
12
+ 'name' => 'Starfleet',
13
+ 'sites' => {
14
+ 'Enterprise' => {
15
+ 'name' => 'Enterprise',
16
+ 'logins' => {
17
+ 'picard' => 'livingston',
18
+ 'riker' => 'trombone'
19
+ }
20
+ },
21
+ },
22
+ 'groups' => {}
23
+ },
24
+ 'Klingon Empire' => {
25
+ 'name' => 'Klingon Empire',
26
+ 'sites' => {
27
+ "Bortas" => {
28
+ 'name' => "Bortas",
29
+ 'logins' => {"gowron" => "bat'leth"}
30
+ }
31
+ },
32
+ 'groups' => {}
33
+ }
34
+ }
35
+ }
36
+ },
37
+ 'version' => 3
38
+ }
39
+ expected = {
40
+ 'groups' => {
41
+ 'top' => {
42
+ 'name' => 'top',
43
+ 'sites' => [],
44
+ 'groups' => {
45
+ 'Starfleet' => {
46
+ 'name' => 'Starfleet',
47
+ 'sites' => [
48
+ {'name' => 'Enterprise', 'username' => 'picard',
49
+ 'password' => 'livingston'},
50
+ {'name' => 'Enterprise', 'username' => 'riker',
51
+ 'password' => 'trombone'},
52
+ ],
53
+ 'groups' => {}
54
+ },
55
+ 'Klingon Empire' => {
56
+ 'name' => 'Klingon Empire',
57
+ 'sites' => [
58
+ {'name' => "Bortas", 'username' => "gowron",
59
+ 'password' => "bat'leth"}
60
+ ],
61
+ 'groups' => {}
62
+ }
63
+ }
64
+ }
65
+ },
66
+ 'version' => 4
67
+ }
68
+ actual = Keyrack::Migrator.run(database)
69
+ assert_equal expected, actual
70
+ assert_not_same database, actual
71
+ end
72
+
73
+ test "migrating version 4 returns the database unchanged" do
74
+ database = {
75
+ 'groups' => {
76
+ 'top' => {
77
+ 'name' => 'top',
78
+ 'sites' => [],
79
+ 'groups' => {
80
+ 'Starfleet' => {
81
+ 'name' => 'Starfleet',
82
+ 'sites' => [
83
+ {'name' => 'Enterprise', 'username' => 'picard',
84
+ 'password' => 'livingston'},
85
+ {'name' => 'Enterprise', 'username' => 'riker',
86
+ 'password' => 'trombone'},
87
+ ],
88
+ 'groups' => {}
89
+ },
90
+ 'Klingon Empire' => {
91
+ 'name' => 'Klingon Empire',
92
+ 'sites' => [
93
+ {'name' => "Bortas", 'username' => "gowron",
94
+ 'password' => "bat'leth"}
95
+ ],
96
+ 'groups' => {}
97
+ }
98
+ }
99
+ }
100
+ },
101
+ 'version' => 4
102
+ }
103
+ assert_equal database.clone, Keyrack::Migrator.run(database)
104
+ end
105
+ end
@@ -0,0 +1,407 @@
1
+ require 'helper'
2
+
3
+ class TestRunner < Test::Unit::TestCase
4
+ def setup
5
+ @console = stub('console', {
6
+ :get_password => 'secret',
7
+ :get_new_entry => {:site => "Foo", :username => "bar", :password => "baz"}
8
+ })
9
+ Keyrack::UI::Console.stubs(:new).returns(@console)
10
+ @top_group = stub('top group', :sites => [], :group_names => [])
11
+ @database = stub('database', :top_group => @top_group)
12
+ Keyrack::Database.stubs(:new).returns(@database)
13
+
14
+ @store = stub('filesystem store')
15
+ Keyrack::Store::Filesystem.stubs(:new).with(instance_of(Hash)).returns(@store)
16
+ Keyrack::Database.stubs(:new).with('secret', @store).returns(@database)
17
+
18
+ @keyrack_dir = get_tmpname
19
+ Dir.mkdir(@keyrack_dir)
20
+
21
+ @menu_options = {
22
+ :group => @top_group, :at_top => true,
23
+ :enable_up => false, :dirty => false
24
+ }
25
+ end
26
+
27
+ DEFAULT_CONFIG = {
28
+ 'store' => {
29
+ 'type' => 'filesystem',
30
+ 'path' => 'foo.db'
31
+ }
32
+ }
33
+
34
+ def setup_config(config = {})
35
+ config = DEFAULT_CONFIG.merge(config)
36
+ File.open(File.join(@keyrack_dir, 'config.yml'), 'w') { |f| f.print(config.to_yaml) }
37
+ end
38
+
39
+ test "console startup for existing database" do
40
+ setup_config
41
+
42
+ store = mock('filesystem store')
43
+ Keyrack::UI::Console.expects(:new).returns(@console)
44
+
45
+ seq = SequenceHelper.new('ui sequence')
46
+ seq << @console.expects(:get_password).returns('secret')
47
+ seq << Keyrack::Store::Filesystem.expects(:new).with('path' => File.join(@keyrack_dir, 'foo.db')).returns(store)
48
+ seq << Keyrack::Database.expects(:new).with('secret', store).returns(@database)
49
+ seq << @database.expects(:dirty?).returns(false)
50
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
51
+
52
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
53
+ end
54
+
55
+ test "add site" do
56
+ setup_config
57
+
58
+ seq = SequenceHelper.new('ui sequence')
59
+ seq << @database.expects(:dirty?).returns(false)
60
+ seq << @console.expects(:menu).with(@menu_options).returns(:new)
61
+ seq << @console.expects(:get_new_entry).returns({:site => "Foo", :username => "bar", :password => "baz"})
62
+
63
+ new_site = stub('site')
64
+ seq << Keyrack::Site.expects(:new).with('Foo', 'bar', 'baz').returns(new_site)
65
+ seq << @top_group.expects(:add_site).with(new_site)
66
+ seq << @database.expects(:dirty?).returns(true)
67
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:quit)
68
+
69
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
70
+ end
71
+
72
+ test "add existing site" do
73
+ setup_config
74
+
75
+ seq = SequenceHelper.new('ui sequence')
76
+ foo_site = stub('Foo site', {
77
+ :name => 'Foo',
78
+ :username => 'bar',
79
+ :password => 'baz'
80
+ })
81
+ new_site = stub('new Foo site', {
82
+ :name => 'Foo',
83
+ :username => 'bar',
84
+ :password => 'junk'
85
+ })
86
+ foo_site.stubs(:==).with(new_site).returns(true)
87
+
88
+ seq << @database.expects(:dirty?).returns(true)
89
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:new)
90
+ seq << @console.expects(:get_new_entry).returns({:site => "Foo", :username => "bar", :password => "junk"})
91
+ seq << Keyrack::Site.expects(:new).with('Foo', 'bar', 'junk').returns(new_site)
92
+ seq << @top_group.expects(:sites).returns([foo_site])
93
+ seq << @console.expects(:confirm_overwrite_entry).with(foo_site).returns(true)
94
+ seq << foo_site.expects(:password=).with('junk')
95
+
96
+ seq << @database.expects(:dirty?).returns(true)
97
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:quit)
98
+
99
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
100
+ end
101
+
102
+ test "cancel adding entry" do
103
+ setup_config
104
+
105
+ seq = SequenceHelper.new('ui sequence')
106
+ seq << @database.expects(:dirty?).returns(false)
107
+ seq << @console.expects(:menu).with(@menu_options).returns(:new)
108
+ seq << @console.expects(:get_new_entry).returns(nil)
109
+
110
+ seq << @database.expects(:dirty?).returns(false)
111
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
112
+
113
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
114
+ end
115
+
116
+ test "canceling edit selection" do
117
+ setup_config
118
+
119
+ seq = SequenceHelper.new('ui sequence')
120
+ seq << @database.expects(:dirty?).returns(false)
121
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
122
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns(nil)
123
+
124
+ seq << @database.expects(:dirty?).returns(false)
125
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
126
+
127
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
128
+ end
129
+
130
+ test "changing username" do
131
+ setup_config
132
+
133
+ foo_site = stub('Foo site', :username => 'bar')
134
+ seq = SequenceHelper.new('ui sequence')
135
+ seq << @database.expects(:dirty?).returns(false)
136
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
137
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns({:site => foo_site})
138
+ seq << @console.expects(:edit_entry).with(foo_site).returns(:change_username)
139
+ seq << @console.expects(:change_username).with('bar').returns('junk')
140
+ seq << foo_site.expects(:username=).with('junk')
141
+ seq << @console.expects(:edit_entry).with(foo_site).returns(nil)
142
+
143
+ seq << @database.expects(:dirty?).returns(true)
144
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:quit)
145
+
146
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
147
+ end
148
+
149
+ test "cancel changing username" do
150
+ setup_config
151
+
152
+ foo_site = stub('Foo site', :username => 'bar')
153
+
154
+ seq = SequenceHelper.new('ui sequence')
155
+ seq << @database.expects(:dirty?).returns(false)
156
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
157
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns({:site => foo_site})
158
+ seq << @console.expects(:edit_entry).with(foo_site).returns(:change_username)
159
+ seq << @console.expects(:change_username).with('bar').returns(nil)
160
+ seq << @console.expects(:edit_entry).with(foo_site).returns(nil)
161
+
162
+ seq << @database.expects(:dirty?).returns(false)
163
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
164
+
165
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
166
+ end
167
+
168
+ test "changing password" do
169
+ setup_config
170
+
171
+ foo_site = stub('Foo site')
172
+
173
+ seq = SequenceHelper.new('ui sequence')
174
+ seq << @database.expects(:dirty?).returns(false)
175
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
176
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns({:site => foo_site})
177
+ seq << @console.expects(:edit_entry).with(foo_site).returns(:change_password)
178
+ seq << @console.expects(:get_new_password).returns('secret')
179
+ seq << foo_site.expects(:password=).with('secret')
180
+ seq << @console.expects(:edit_entry).with(foo_site).returns(nil)
181
+
182
+ seq << @database.expects(:dirty?).returns(true)
183
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:quit)
184
+
185
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
186
+ end
187
+
188
+ test "cancel changing password" do
189
+ setup_config
190
+
191
+ foo_site = stub('Foo site')
192
+
193
+ seq = SequenceHelper.new('ui sequence')
194
+ seq << @database.expects(:dirty?).returns(false)
195
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
196
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns({:site => foo_site})
197
+ seq << @console.expects(:edit_entry).with(foo_site).returns(:change_password)
198
+ seq << @console.expects(:get_new_password).returns(nil)
199
+ seq << @console.expects(:edit_entry).with(foo_site).returns(nil)
200
+
201
+ seq << @database.expects(:dirty?).returns(false)
202
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
203
+
204
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
205
+ end
206
+
207
+ test "delete entry" do
208
+ setup_config
209
+
210
+ foo_site = stub('Foo site', :name => 'Foo', :username => 'bar')
211
+
212
+ seq = SequenceHelper.new('ui sequence')
213
+ seq << @database.expects(:dirty?).returns(false)
214
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
215
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns({:site => foo_site})
216
+ seq << @console.expects(:edit_entry).with(foo_site).returns(:delete)
217
+ seq << @console.expects(:confirm_delete_entry).with(foo_site).returns(true)
218
+ seq << @top_group.expects(:remove_site).with(foo_site)
219
+
220
+ seq << @database.expects(:dirty?).returns(true)
221
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:quit)
222
+
223
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
224
+ end
225
+
226
+ test "cancel delete entry" do
227
+ setup_config
228
+
229
+ foo_site = stub('Foo site')
230
+
231
+ seq = SequenceHelper.new('ui sequence')
232
+ seq << @database.expects(:dirty?).returns(false)
233
+ seq << @console.expects(:menu).with(@menu_options).returns(:edit)
234
+ seq << @console.expects(:choose_entry_to_edit).with(@top_group).returns({:site => foo_site})
235
+ seq << @console.expects(:edit_entry).with(foo_site).returns(:delete)
236
+ seq << @console.expects(:confirm_delete_entry).with(foo_site).returns(false)
237
+ seq << @console.expects(:edit_entry).with(foo_site).returns(nil)
238
+
239
+ seq << @database.expects(:dirty?).returns(false)
240
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
241
+
242
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
243
+ end
244
+
245
+ test "creating new group" do
246
+ setup_config
247
+
248
+ seq = SequenceHelper.new("ui sequence")
249
+ seq << @database.expects(:dirty?).returns(false)
250
+ seq << @console.expects(:menu).with(@menu_options).returns(:new_group)
251
+ seq << @console.expects(:get_new_group).returns('Foo')
252
+
253
+ new_group = stub('Foo group', :site_names => [], :group_names => [])
254
+ seq << Keyrack::Group.expects(:new).with('Foo').returns(new_group)
255
+ seq << @top_group.expects(:add_group).with(new_group)
256
+
257
+ seq << @database.expects(:dirty?).returns(true)
258
+ seq << @console.expects(:menu).
259
+ with(@menu_options.merge(:group => new_group, :at_top => false, :dirty => true)).
260
+ returns(:quit)
261
+
262
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
263
+ end
264
+
265
+ test "creating new subgroup" do
266
+ setup_config
267
+
268
+ seq = SequenceHelper.new("ui sequence")
269
+ seq << @database.expects(:dirty?).returns(false)
270
+ seq << @console.expects(:menu).with(@menu_options).returns(:new_group)
271
+ seq << @console.expects(:get_new_group).returns('Foo')
272
+
273
+ foo_group = stub('Foo group', :site_names => [], :group_names => [])
274
+ seq << Keyrack::Group.expects(:new).with('Foo').returns(foo_group)
275
+ seq << @top_group.expects(:add_group).with(foo_group)
276
+
277
+ seq << @database.expects(:dirty?).returns(true)
278
+ seq << @console.expects(:menu).
279
+ with(@menu_options.merge(:group => foo_group, :at_top => false, :dirty => true)).
280
+ returns(:new_group)
281
+ seq << @console.expects(:get_new_group).returns('Bar')
282
+
283
+ bar_group = stub('Bar group', :site_names => [], :group_names => [])
284
+ seq << Keyrack::Group.expects(:new).with('Bar').returns(bar_group)
285
+ seq << foo_group.expects(:add_group).with(bar_group)
286
+
287
+ seq << @database.expects(:dirty?).returns(true)
288
+ seq << @console.expects(:menu).
289
+ with(@menu_options.merge(:group => bar_group, :at_top => false, :dirty => true, :enable_up => true)).
290
+ returns(:quit)
291
+
292
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
293
+ end
294
+
295
+ test "save" do
296
+ setup_config
297
+
298
+ seq = SequenceHelper.new("ui sequence")
299
+ seq << @database.expects(:dirty?).returns(true)
300
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:save)
301
+ seq << @console.expects(:get_password).returns('secret')
302
+ seq << @database.expects(:save).with('secret').returns(true)
303
+
304
+ seq << @database.expects(:dirty?).returns(false)
305
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
306
+
307
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
308
+ end
309
+
310
+ test "save with invalid password" do
311
+ setup_config
312
+
313
+ seq = SequenceHelper.new("ui sequence")
314
+ seq << @database.expects(:dirty?).returns(true)
315
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:save)
316
+ seq << @console.expects(:get_password).returns('secret')
317
+ seq << @database.expects(:save).with('secret').returns(false)
318
+ seq << @console.expects(:display_invalid_password_notice)
319
+ seq << @database.expects(:dirty?).returns(true)
320
+ seq << @console.expects(:menu).with(@menu_options.merge(:dirty => true)).returns(:quit)
321
+
322
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
323
+ end
324
+
325
+ test "selecting group" do
326
+ setup_config
327
+
328
+ seq = SequenceHelper.new("ui sequence")
329
+ seq << @database.expects(:dirty?).returns(false)
330
+ foo_group = stub('Foo group')
331
+ seq << @console.expects(:menu).with(@menu_options).returns(:group => foo_group)
332
+
333
+ seq << @database.expects(:dirty?).returns(false)
334
+ seq << @console.expects(:menu).with(@menu_options.merge(:group => foo_group, :at_top => false)).returns(:quit)
335
+
336
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
337
+ end
338
+
339
+ test "selecting subgroup of group" do
340
+ setup_config
341
+
342
+ seq = SequenceHelper.new("ui sequence")
343
+ seq << @database.expects(:dirty?).returns(false)
344
+ foo_group = stub('Foo group')
345
+ seq << @console.expects(:menu).with(@menu_options).returns(:group => foo_group)
346
+
347
+ bar_group = stub('Bar group')
348
+ seq << @database.expects(:dirty?).returns(false)
349
+ seq << @console.expects(:menu).
350
+ with(@menu_options.merge(:group => foo_group, :at_top => false)).
351
+ returns(:group => bar_group)
352
+
353
+ seq << @database.expects(:dirty?).returns(false)
354
+ seq << @console.expects(:menu).
355
+ with(@menu_options.merge(:group => bar_group, :at_top => false, :enable_up => true)).
356
+ returns(:quit)
357
+
358
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
359
+ end
360
+
361
+ test "navigating to top" do
362
+ setup_config
363
+
364
+ seq = SequenceHelper.new("ui sequence")
365
+ seq << @database.expects(:dirty?).returns(false)
366
+ foo_group = stub('Foo group')
367
+ seq << @console.expects(:menu).with(@menu_options).returns(:group => foo_group)
368
+
369
+ seq << @database.expects(:dirty?).returns(false)
370
+ seq << @console.expects(:menu).
371
+ with(@menu_options.merge(:group => foo_group, :at_top => false)).
372
+ returns(:top)
373
+
374
+ seq << @database.expects(:dirty?).returns(false)
375
+ seq << @console.expects(:menu).with(@menu_options).returns(:quit)
376
+
377
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
378
+ end
379
+
380
+ test "navigating up" do
381
+ setup_config
382
+
383
+ foo_group = stub('Foo group')
384
+ bar_group = stub('Bar group')
385
+
386
+ seq = SequenceHelper.new("ui sequence")
387
+ seq << @database.expects(:dirty?).returns(false)
388
+ seq << @console.expects(:menu).with(@menu_options).returns(:group => foo_group)
389
+
390
+ seq << @database.expects(:dirty?).returns(false)
391
+ seq << @console.expects(:menu).
392
+ with(@menu_options.merge(:group => foo_group, :at_top => false)).
393
+ returns(:group => bar_group)
394
+
395
+ seq << @database.expects(:dirty?).returns(false)
396
+ seq << @console.expects(:menu).
397
+ with(@menu_options.merge(:group => bar_group, :at_top => false, :enable_up => true)).
398
+ returns(:up)
399
+
400
+ seq << @database.expects(:dirty?).returns(false)
401
+ seq << @console.expects(:menu).
402
+ with(@menu_options.merge(:group => foo_group, :at_top => false)).
403
+ returns(:quit)
404
+
405
+ runner = Keyrack::Runner.new(["-d", @keyrack_dir])
406
+ end
407
+ end