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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +8 -15
- data/Guardfile +6 -0
- data/LICENSE.txt +4 -2
- data/Rakefile +2 -56
- data/keyrack.gemspec +22 -104
- data/lib/keyrack.rb +9 -1
- data/lib/keyrack/database.rb +64 -98
- data/lib/keyrack/event.rb +13 -0
- data/lib/keyrack/exceptions.rb +4 -0
- data/lib/keyrack/group.rb +225 -0
- data/lib/keyrack/migrator.rb +45 -0
- data/lib/keyrack/runner.rb +98 -44
- data/lib/keyrack/site.rb +92 -0
- data/lib/keyrack/ui/console.rb +234 -95
- data/lib/keyrack/utils.rb +0 -18
- data/lib/keyrack/version.rb +3 -0
- data/test/fixtures/database-3.dat +0 -0
- data/test/helper.rb +11 -1
- data/test/integration/test_interactive_console.rb +139 -0
- data/test/unit/store/test_filesystem.rb +21 -0
- data/test/unit/store/test_ssh.rb +32 -0
- data/test/unit/test_database.rb +201 -0
- data/test/unit/test_event.rb +41 -0
- data/test/unit/test_group.rb +703 -0
- data/test/unit/test_migrator.rb +105 -0
- data/test/unit/test_runner.rb +407 -0
- data/test/unit/test_site.rb +181 -0
- data/test/unit/test_store.rb +13 -0
- data/test/unit/test_utils.rb +8 -0
- data/test/unit/ui/test_console.rb +495 -0
- metadata +98 -94
- data/Gemfile.lock +0 -45
- data/TODO +0 -4
- data/VERSION +0 -1
- data/features/console.feature +0 -103
- data/features/step_definitions/keyrack_steps.rb +0 -61
- data/features/support/env.rb +0 -16
- data/test/fixtures/aes +0 -0
- data/test/fixtures/config.yml +0 -4
- data/test/fixtures/id_rsa +0 -54
- data/test/keyrack/store/test_filesystem.rb +0 -25
- data/test/keyrack/store/test_ssh.rb +0 -36
- data/test/keyrack/test_database.rb +0 -111
- data/test/keyrack/test_runner.rb +0 -111
- data/test/keyrack/test_store.rb +0 -15
- data/test/keyrack/test_utils.rb +0 -41
- data/test/keyrack/ui/test_console.rb +0 -308
@@ -1,308 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
module UI
|
5
|
-
class TestConsole < Test::Unit::TestCase
|
6
|
-
def setup
|
7
|
-
@database = stub('database', :sites => %w{Twitter Google}, :groups => [], :dirty? => false) do
|
8
|
-
stubs(:get).with('Twitter', {}).returns({
|
9
|
-
:username => 'username', :password => 'password'
|
10
|
-
})
|
11
|
-
stubs(:get).with('Google', {}).returns([
|
12
|
-
{ :username => 'username_1', :password => 'password' },
|
13
|
-
{ :username => 'username_2', :password => 'password' }
|
14
|
-
])
|
15
|
-
end
|
16
|
-
@highline = stub('highline')
|
17
|
-
@highline.stubs(:color).with("Keyrack Main Menu", :yellow).returns("yellowKeyrack Main Menu")
|
18
|
-
@highline.stubs(:say)
|
19
|
-
HighLine.expects(:new).returns(@highline)
|
20
|
-
@console = Console.new
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_select_entry_from_menu
|
24
|
-
seq = sequence('say')
|
25
|
-
@console.database = @database
|
26
|
-
@highline.expects(:say).with("=== yellowKeyrack Main Menu ===")
|
27
|
-
@highline.expects(:say).with(" 1. Twitter [username]")
|
28
|
-
@highline.expects(:say).with(" 2. Google [username_1]")
|
29
|
-
@highline.expects(:say).with(" 3. Google [username_2]")
|
30
|
-
@highline.expects(:say).with("Mode: copy")
|
31
|
-
@highline.expects(:say).with("Commands: [n]ew [d]elete [g]roup [m]ode [q]uit")
|
32
|
-
|
33
|
-
question = mock('question')
|
34
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g}) }).returns('1')
|
35
|
-
@console.expects(:Copier).with('password')
|
36
|
-
@highline.expects(:say).with("The password has been copied to your clipboard.")
|
37
|
-
assert_nil @console.menu
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_select_entry_from_menu_in_print_mode
|
41
|
-
seq = sequence('say')
|
42
|
-
@console.database = @database
|
43
|
-
@console.mode = :print
|
44
|
-
@highline.expects(:say).with("=== yellowKeyrack Main Menu ===")
|
45
|
-
@highline.expects(:say).with(" 1. Twitter [username]")
|
46
|
-
@highline.expects(:say).with(" 2. Google [username_1]")
|
47
|
-
@highline.expects(:say).with(" 3. Google [username_2]")
|
48
|
-
@highline.expects(:say).with("Mode: print")
|
49
|
-
@highline.expects(:say).with("Commands: [n]ew [d]elete [g]roup [m]ode [q]uit")
|
50
|
-
|
51
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g}) }).returns('1')
|
52
|
-
@highline.expects(:color).with('password', :cyan).returns('cyan[password]').in_sequence(seq)
|
53
|
-
question = mock do
|
54
|
-
expects(:echo=).with(false)
|
55
|
-
if HighLine::SystemExtensions::CHARACTER_MODE != 'stty'
|
56
|
-
expects(:character=).with(true)
|
57
|
-
expects(:overwrite=).with(true)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
@highline.expects(:ask).
|
61
|
-
with('Here you go: cyan[password]. Done? ').
|
62
|
-
yields(question).
|
63
|
-
returns('')
|
64
|
-
|
65
|
-
assert_nil @console.menu
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_select_new_from_menu
|
69
|
-
@console.database = @database
|
70
|
-
|
71
|
-
# === yellowKeyrack Main Menu ===
|
72
|
-
# 1. Twitter [username]
|
73
|
-
# n. New entry
|
74
|
-
# d. Delete entry
|
75
|
-
# g. New group
|
76
|
-
# q. Quit
|
77
|
-
|
78
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g}) }).returns('n')
|
79
|
-
assert_equal :new, @console.menu
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_select_delete_from_menu
|
83
|
-
@console.database = @database
|
84
|
-
|
85
|
-
# === yellowKeyrack Main Menu ===
|
86
|
-
# 1. Twitter [username]
|
87
|
-
# n. New entry
|
88
|
-
# d. Delete entry
|
89
|
-
# g. New group
|
90
|
-
# q. Quit
|
91
|
-
|
92
|
-
question = mock('question')
|
93
|
-
question.expects(:in=).with(%w{n q m 1 2 3 d g})
|
94
|
-
@highline.expects(:ask).yields(question).returns('d')
|
95
|
-
assert_equal :delete, @console.menu
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_select_quit_from_menu
|
99
|
-
@console.database = @database
|
100
|
-
|
101
|
-
# === yellowKeyrack Main Menu ===
|
102
|
-
# 1. Twitter [username]
|
103
|
-
# n. New entry
|
104
|
-
# d. Delete entry
|
105
|
-
# g. New group
|
106
|
-
# q. Quit
|
107
|
-
|
108
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g}) }).returns('q')
|
109
|
-
assert_equal :quit, @console.menu
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_select_quit_from_menu_when_database_is_dirty
|
113
|
-
@console.database = @database
|
114
|
-
@database.stubs(:dirty?).returns(true)
|
115
|
-
|
116
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g s}) }).returns('q')
|
117
|
-
@highline.expects(:agree).with("Really quit? You have unsaved changes! [yn] ").returns(false)
|
118
|
-
assert_equal nil, @console.menu
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_select_save_from_menu
|
122
|
-
@console.database = @database
|
123
|
-
@database.stubs(:dirty?).returns(true)
|
124
|
-
|
125
|
-
@highline.expects(:say).with { |string| string =~ /\[s\]ave/ }
|
126
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g s}) }).returns('s')
|
127
|
-
assert_equal :save, @console.menu
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_select_group_from_menu
|
131
|
-
@console.database = @database
|
132
|
-
@database.stubs(:groups).returns(["Blargh"])
|
133
|
-
|
134
|
-
@highline.expects(:color).with('Blargh', :green).returns('greenBlargh')
|
135
|
-
@highline.expects(:say).with(" 1. greenBlargh")
|
136
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 4 d g}) }).returns('1')
|
137
|
-
assert_equal({:group => 'Blargh'}, @console.menu)
|
138
|
-
end
|
139
|
-
|
140
|
-
def test_select_entry_from_group_menu
|
141
|
-
@console.database = @database
|
142
|
-
@database.expects(:sites).with(:group => "Foo").returns(["Facebook"])
|
143
|
-
@database.expects(:get).with('Facebook', :group => "Foo").returns({:username => 'username', :password => 'password'})
|
144
|
-
|
145
|
-
@highline.expects(:color).with("Foo", :green).returns("greenFoo")
|
146
|
-
@highline.expects(:say).with("===== greenFoo =====")
|
147
|
-
@highline.expects(:say).with(" 1. Facebook [username]")
|
148
|
-
@highline.expects(:say).with("Mode: copy")
|
149
|
-
@highline.expects(:say).with("Commands: [n]ew [d]elete [t]op [m]ode [q]uit")
|
150
|
-
|
151
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 d t}) }).returns('1')
|
152
|
-
@console.expects(:Copier).with('password')
|
153
|
-
@highline.expects(:say).with("The password has been copied to your clipboard.")
|
154
|
-
assert_nil @console.menu(:group => 'Foo')
|
155
|
-
end
|
156
|
-
|
157
|
-
def test_get_password
|
158
|
-
question = mock('question')
|
159
|
-
question.expects(:echo=).with(false)
|
160
|
-
@highline.expects(:ask).with("Keyrack password: ").yields(question).returns("foobar")
|
161
|
-
assert_equal "foobar", @console.get_password
|
162
|
-
end
|
163
|
-
|
164
|
-
def test_get_new_entry_with_manual_password
|
165
|
-
seq = sequence("new entry")
|
166
|
-
@highline.expects(:ask).with("Label: ").returns("Foo").in_sequence(seq)
|
167
|
-
@highline.expects(:ask).with("Username: ").returns("bar").in_sequence(seq)
|
168
|
-
@highline.expects(:agree).with("Generate password? [yn] ").returns(false).in_sequence(seq)
|
169
|
-
@highline.expects(:ask).with("Password: ").yields(mock { expects(:echo=).with(false) }).returns("baz").in_sequence(seq)
|
170
|
-
@highline.expects(:ask).with("Password (again): ").yields(mock { expects(:echo=).with(false) }).returns("bar").in_sequence(seq)
|
171
|
-
@highline.expects(:say).with("Passwords didn't match. Try again!").in_sequence(seq)
|
172
|
-
@highline.expects(:ask).with("Password: ").yields(mock { expects(:echo=).with(false) }).returns("baz").in_sequence(seq)
|
173
|
-
@highline.expects(:ask).with("Password (again): ").yields(mock { expects(:echo=).with(false) }).returns("baz").in_sequence(seq)
|
174
|
-
assert_equal({:site => "Foo", :username => "bar", :password => "baz"}, @console.get_new_entry)
|
175
|
-
end
|
176
|
-
|
177
|
-
def test_get_new_entry_generated_password
|
178
|
-
seq = sequence("new entry")
|
179
|
-
@highline.expects(:ask).with("Label: ").returns("Foo").in_sequence(seq)
|
180
|
-
@highline.expects(:ask).with("Username: ").returns("bar").in_sequence(seq)
|
181
|
-
@highline.expects(:agree).with("Generate password? [yn] ").returns(true).in_sequence(seq)
|
182
|
-
Utils.expects(:generate_password).returns('foobar').in_sequence(seq)
|
183
|
-
@highline.expects(:color).with('foobar', :cyan).returns('cyanfoobar').in_sequence(seq)
|
184
|
-
@highline.expects(:agree).with("Generated cyanfoobar. Sound good? [yn] ").returns(false).in_sequence(seq)
|
185
|
-
Utils.expects(:generate_password).returns('foobar').in_sequence(seq)
|
186
|
-
@highline.expects(:color).with('foobar', :cyan).returns('cyanfoobar').in_sequence(seq)
|
187
|
-
@highline.expects(:agree).with("Generated cyanfoobar. Sound good? [yn] ").returns(true).in_sequence(seq)
|
188
|
-
assert_equal({:site => "Foo", :username => "bar", :password => "foobar"}, @console.get_new_entry)
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_display_first_time_notice
|
192
|
-
@highline.expects(:say).with("This looks like your first time using Keyrack. I'll need to ask you a few questions first.")
|
193
|
-
@console.display_first_time_notice
|
194
|
-
end
|
195
|
-
|
196
|
-
def test_rsa_setup
|
197
|
-
seq = sequence("rsa setup")
|
198
|
-
@highline.expects(:ask).with("New passphrase: ").yields(mock{expects(:echo=).with(false)}).returns('huge').in_sequence(seq)
|
199
|
-
@highline.expects(:ask).with("Confirm passphrase: ").yields(mock{expects(:echo=).with(false)}).returns('small').in_sequence(seq)
|
200
|
-
@highline.expects(:say).with("Passphrases didn't match.").in_sequence(seq)
|
201
|
-
@highline.expects(:ask).with("New passphrase: ").yields(mock{expects(:echo=).with(false)}).returns('huge').in_sequence(seq)
|
202
|
-
@highline.expects(:ask).with("Confirm passphrase: ").yields(mock{expects(:echo=).with(false)}).returns('huge').in_sequence(seq)
|
203
|
-
expected = {'password' => 'huge', 'path' => 'rsa'}
|
204
|
-
assert_equal expected, @console.rsa_setup
|
205
|
-
end
|
206
|
-
|
207
|
-
def test_store_setup_for_filesystem
|
208
|
-
@highline.expects(:choose).yields(mock {
|
209
|
-
expects(:header=).with("Choose storage type")
|
210
|
-
expects(:choices).with("filesystem", "ssh")
|
211
|
-
}).returns("filesystem")
|
212
|
-
|
213
|
-
expected = {'type' => 'filesystem', 'path' => 'database'}
|
214
|
-
assert_equal expected, @console.store_setup
|
215
|
-
end
|
216
|
-
|
217
|
-
def test_store_setup_for_ssh
|
218
|
-
seq = sequence("store setup")
|
219
|
-
@highline.expects(:choose).yields(mock {
|
220
|
-
expects(:header=).with("Choose storage type")
|
221
|
-
expects(:choices).with("filesystem", "ssh")
|
222
|
-
}).returns("ssh").in_sequence(seq)
|
223
|
-
@highline.expects(:ask).with("Host: ").returns("example.com").in_sequence(seq)
|
224
|
-
@highline.expects(:ask).with("User: ").returns("dudeguy").in_sequence(seq)
|
225
|
-
@highline.expects(:ask).with("Remote path: ").returns(".keyrack/database").in_sequence(seq)
|
226
|
-
|
227
|
-
expected = {'type' => 'ssh', 'host' => 'example.com', 'user' => 'dudeguy', 'path' => '.keyrack/database'}
|
228
|
-
assert_equal expected, @console.store_setup
|
229
|
-
end
|
230
|
-
|
231
|
-
def test_get_new_group
|
232
|
-
@highline.expects(:ask).with("Group: ").yields(mock {
|
233
|
-
expects(:validate=).with(/^\w[\w\s]*$/)
|
234
|
-
}).returns("Foo")
|
235
|
-
assert_equal({:group => "Foo"}, @console.get_new_group)
|
236
|
-
end
|
237
|
-
|
238
|
-
def test_delete_entry
|
239
|
-
@console.database = @database
|
240
|
-
@database.stubs(:sites).returns(%w{Twitter Facebook})
|
241
|
-
@database.stubs(:get).with('Facebook', {}).returns({
|
242
|
-
:username => 'username', :password => 'password'
|
243
|
-
})
|
244
|
-
|
245
|
-
seq = sequence("deleting")
|
246
|
-
@highline.expects(:say).with("Choose entry to delete:").in_sequence(seq)
|
247
|
-
@highline.expects(:say).with(" 1. Twitter [username]").in_sequence(seq)
|
248
|
-
@highline.expects(:say).with(" 2. Facebook [username]").in_sequence(seq)
|
249
|
-
@highline.expects(:say).with(" c. Cancel").in_sequence(seq)
|
250
|
-
@highline.expects(:ask).yields(mock {
|
251
|
-
expects(:in=).with(%w{c 1 2})
|
252
|
-
}).returns('1').in_sequence(seq)
|
253
|
-
@highline.expects(:color).with("Twitter [username]", :red).returns("redTwitter").in_sequence(seq)
|
254
|
-
@highline.expects(:agree).with("You're about to delete redTwitter. Are you sure? [yn] ").returns(true).in_sequence(seq)
|
255
|
-
@database.expects(:delete).with("Twitter", 'username', {}).in_sequence(seq)
|
256
|
-
@console.delete_entry
|
257
|
-
end
|
258
|
-
|
259
|
-
def test_delete_one_entry_from_site_with_multiple_entries
|
260
|
-
@console.database = @database
|
261
|
-
|
262
|
-
seq = sequence("deleting")
|
263
|
-
@highline.expects(:say).with("Choose entry to delete:").in_sequence(seq)
|
264
|
-
@highline.expects(:say).with(" 1. Twitter [username]").in_sequence(seq)
|
265
|
-
@highline.expects(:say).with(" 2. Google [username_1]").in_sequence(seq)
|
266
|
-
@highline.expects(:say).with(" 3. Google [username_2]").in_sequence(seq)
|
267
|
-
@highline.expects(:say).with(" c. Cancel").in_sequence(seq)
|
268
|
-
@highline.expects(:ask).yields(mock {
|
269
|
-
expects(:in=).with(%w{c 1 2 3})
|
270
|
-
}).returns('3').in_sequence(seq)
|
271
|
-
@highline.expects(:color).with("Google [username_2]", :red).returns("redGoogle").in_sequence(seq)
|
272
|
-
@highline.expects(:agree).with("You're about to delete redGoogle. Are you sure? [yn] ").returns(true).in_sequence(seq)
|
273
|
-
@database.expects(:delete).with("Google", 'username_2', {}).in_sequence(seq)
|
274
|
-
@console.delete_entry
|
275
|
-
end
|
276
|
-
|
277
|
-
def test_delete_group_entry
|
278
|
-
@console.database = @database
|
279
|
-
@database.stubs(:sites).returns(%w{Quora Foursquare})
|
280
|
-
@database.stubs(:get).with(kind_of(String), {:group => 'Social'}).returns({
|
281
|
-
:username => 'username', :password => 'password'
|
282
|
-
})
|
283
|
-
|
284
|
-
seq = sequence("deleting")
|
285
|
-
@highline.expects(:say).with("Choose entry to delete:").in_sequence(seq)
|
286
|
-
@highline.expects(:say).with(" 1. Quora [username]").in_sequence(seq)
|
287
|
-
@highline.expects(:say).with(" 2. Foursquare [username]").in_sequence(seq)
|
288
|
-
@highline.expects(:say).with(" c. Cancel").in_sequence(seq)
|
289
|
-
@highline.expects(:ask).yields(mock {
|
290
|
-
expects(:in=).with(%w{c 1 2})
|
291
|
-
}).returns('2').in_sequence(seq)
|
292
|
-
@highline.expects(:color).with("Foursquare [username]", :red).returns("redFoursquare").in_sequence(seq)
|
293
|
-
@highline.expects(:agree).with("You're about to delete redFoursquare. Are you sure? [yn] ").returns(true).in_sequence(seq)
|
294
|
-
@database.expects(:delete).with("Foursquare", 'username', :group => 'Social').in_sequence(seq)
|
295
|
-
@console.delete_entry(:group => 'Social')
|
296
|
-
end
|
297
|
-
|
298
|
-
def test_switch_mode_from_menu
|
299
|
-
@console.database = @database
|
300
|
-
@console.mode = :copy
|
301
|
-
|
302
|
-
@highline.expects(:ask).yields(mock { expects(:in=).with(%w{n q m 1 2 3 d g}) }).returns('m')
|
303
|
-
assert_nil @console.menu
|
304
|
-
assert_equal :print, @console.mode
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|