sesame-cli 0.2.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e9e49b899f85759b86942eb6a051205e3db2f5adef20d6026ca31862b2724af
4
- data.tar.gz: 84ae67770bb80de8854a1044b35f4b19364715383b18065507ba5cc5c8e9e183
3
+ metadata.gz: 5f22b05a9ccfb4ed20090fe15a4688435773a2fc75dc45c6360f184806a1e0b7
4
+ data.tar.gz: 02ff7c0924ce62da164a8b2243292d6fa2db0c5c729d0eb48840956de7854467
5
5
  SHA512:
6
- metadata.gz: '07078b42b50a933caeb46187d494fb0981439a963d48e3445e0b3b6c6ef3e8328460ea39baa994152dd28c319d44aebf9f7a46b6b486f245de16b62b3e113834'
7
- data.tar.gz: 14607f8208e44a33833ca234ebf5c441a0e2bdca8e3eb02336a70cd14ec63260979f06a83ef7e85d76f2da25332598238a3a7ddd0d4f08589a60c330fe91e3ac
6
+ metadata.gz: 710f4c9022e30461b894edb497d956a0be95e0235756b3e27ffb0921efc7e744fb2edc607987b5b887d25bbf39152eec6a064b6b420a0fdb3b28c9fdcc5ef327
7
+ data.tar.gz: cd10c77c1879a964ab3998b22e705efd63663127629d93505d713fe86f89a37670950b99f7908bfbf05fcbd28e1fee7c490a067cfb38b5705ff111f90374c27e
data/README.md CHANGED
@@ -42,7 +42,7 @@ mammal glue wage paper store detail weave date
42
42
 
43
43
  > exit
44
44
  🧞 - "I have secured your treasure with this key..."
45
- sky tea ant ice
45
+ tea old ant ice
46
46
  ```
47
47
 
48
48
  You will notice that Sesame enters interactive mode when the `--interactive`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 1.0.0
data/lib/sesame/cave.rb CHANGED
@@ -121,6 +121,7 @@ module Sesame
121
121
  @item = nil
122
122
  @store = nil
123
123
  @secret = nil
124
+ @dirty = false
124
125
  end
125
126
 
126
127
  # Lock the cave by encrypting and saving the secret to a lock file, and then
@@ -212,11 +213,11 @@ module Sesame
212
213
  # True if a particular service has exactly one username.
213
214
  def unique?(service)
214
215
  raise Fail, 'Cannot test service uniqueness; store not open' unless open?
215
- return if @store[service].nil?
216
+ raise Fail, 'No such service' if @store[service].nil?
216
217
  @store[service].count < 2
217
218
  end
218
219
 
219
- # Generate and return the passpgrase for a service and username.
220
+ # Generate and return the passphrase for a service and username.
220
221
  def get(service, user = nil, index = nil)
221
222
  raise Fail, 'Cannot get service details; store not open' unless open?
222
223
  raise Fail, 'Cannot get the sesame service' if service.casecmp('sesame').zero?
@@ -233,8 +234,7 @@ module Sesame
233
234
  end
234
235
  raise Fail, 'Service cannot be empty' if service.strip.length.zero?
235
236
  raise Fail, 'User cannot be empty' if user.nil? || user.strip.length.zero?
236
- item = _find(service, user)
237
- raise Fail, 'Service and/or user already exists' unless item.nil?
237
+ raise Fail, 'User already exists for that service' unless @store[service].nil? || @store[service][user].nil?
238
238
  @store[service] ||= {}
239
239
  @store[service][user] = index || 0
240
240
  @dirty = true
@@ -248,7 +248,6 @@ module Sesame
248
248
  def update(service, user = nil, index = nil)
249
249
  raise Fail, 'Cannot update service details; store not open' unless open?
250
250
  item = _find(service, user)
251
- raise Fail, 'Unable to find that service and/or user' if item.nil?
252
251
  index = item[:index] + 1 if index.nil?
253
252
  index = 0 if index.negative?
254
253
  user = item[:user]
@@ -263,7 +262,6 @@ module Sesame
263
262
  raise Fail, 'Cannot delete service details; store not open' unless open?
264
263
  raise Fail, 'Cannot delete the sesame service' if service.casecmp('sesame').zero?
265
264
  item = _find(service, user)
266
- raise Fail, 'Unable to find that service and/or user' if item.nil?
267
265
  user = item[:user]
268
266
  @store[service].delete(user)
269
267
  @store.delete(service) if @store[service].count.zero?
@@ -284,9 +282,10 @@ module Sesame
284
282
  end
285
283
 
286
284
  def _find(service, user)
287
- return nil if service.nil? || @store[service].nil?
285
+ raise Fail, 'No such service' if service.nil? || @store[service].nil?
288
286
  @item =
289
287
  if user.nil?
288
+ raise Fail, 'No unique user for service' unless unique?(service)
290
289
  item = @store[service].first
291
290
  {
292
291
  service: service,
@@ -294,7 +293,7 @@ module Sesame
294
293
  index: item.last
295
294
  }
296
295
  elsif @store[service][user].nil?
297
- nil
296
+ raise Fail, 'No such service or user'
298
297
  else
299
298
  index = @store[service][user]
300
299
  {
data/lib/sesame/jinn.rb CHANGED
@@ -7,39 +7,40 @@ require 'clipboard'
7
7
  module Sesame
8
8
  # The Jinn class is wholly responsible for interacting with the terminal.
9
9
  class Jinn
10
- # Pass in parsed command-line options as a Slop instance.
11
- def initialize(opts)
10
+ # Pass in parsed command-line options as a Slop instance. The optional pow
11
+ # parameter should only be used to speed up tests.
12
+ def initialize(opts, pow = 30)
12
13
  I18n.load_path = Dir[File.join(File.dirname(__FILE__), 'lang', '*yml')]
13
14
  @opts = opts
14
15
  _config
15
16
  _parse
16
17
  _welcome
17
- @sesame = Cave.new(@opts[:path])
18
+ @cave = Cave.new(@opts[:path], pow)
18
19
  rescue Fail => e
19
20
  _error(e.message)
20
21
  end
21
22
 
22
23
  # Process the users request, possibly starting an interactive session.
23
24
  def process!
24
- return if @sesame.nil?
25
+ return if @cave.nil?
25
26
  @was_locked = false
26
27
  raise Fail, 'Cannot lock and expunge simultaneously' if @opts.lock? && @opts.expunge?
27
- if @sesame.exists?
28
+ if @cave.exists?
28
29
  raise Fail, 'Please remove the cave before attempting to reconstruct' if @opts.reconstruct?
29
- raise Fail, 'Cannot expunge lock; it doesn\'t exist' if @opts.expunge? && !@sesame.locked?
30
+ raise Fail, 'Cannot expunge lock; it doesn\'t exist' if @opts.expunge? && !@cave.locked?
30
31
  raise Fail, 'Please specify a command (or use interactive mode)' if !@opts.interactive? && @opts[:command].nil? && !@opts.lock? && !@opts.expunge?
31
- if @sesame.locked? && @opts.expunge?
32
- @sesame.forget
32
+ if @cave.locked? && @opts.expunge?
33
+ @cave.forget
33
34
  _warn('Lock expunged')
34
35
  end
35
- if @sesame.locked?
36
+ if @cave.locked?
36
37
  _unlock
37
38
  @was_locked = true
38
39
  else
39
40
  _open
40
41
  end
41
42
  else
42
- @sesame.forget if @sesame.locked?
43
+ @cave.forget if @cave.locked?
43
44
  _new
44
45
  end
45
46
  _process(@opts[:command])
@@ -49,12 +50,12 @@ module Sesame
49
50
  break if _prompt
50
51
  end
51
52
  if @opts.expunge?
52
- @sesame.close
53
+ @cave.close
53
54
  else
54
55
  _lock
55
56
  end
56
57
  elsif @opts.expunge? || (!@was_locked && !@opts.lock?)
57
- @sesame.close
58
+ @cave.close
58
59
  else
59
60
  _lock
60
61
  end
@@ -203,7 +204,7 @@ module Sesame
203
204
  _info('reconstruct')
204
205
  words = ask('🔑 ') { |q| q.echo = '*' }
205
206
  end
206
- phrase = @sesame.create!(words)
207
+ phrase = @cave.create!(words)
207
208
  if words.nil?
208
209
  _info('new')
209
210
  _show(phrase)
@@ -215,26 +216,26 @@ module Sesame
215
216
  def _open
216
217
  _info('open')
217
218
  words = ask('🔑 ') { |q| q.echo = '*' }
218
- @sesame.open(words)
219
- _info('path', path: @sesame.path)
219
+ @cave.open(words)
220
+ _info('path', path: @cave.path)
220
221
  end
221
222
 
222
223
  def _unlock
223
224
  _info('unlock')
224
225
  key = ask('🔑 ') { |q| q.echo = '*' }
225
- @sesame.unlock(key)
226
- _info('path', path: @sesame.path)
226
+ @cave.unlock(key)
227
+ _info('path', path: @cave.path)
227
228
  end
228
229
 
229
230
  def _forget
230
231
  _info('forgot')
231
- @sesame.forget
232
+ @cave.forget
232
233
  end
233
234
 
234
235
  def _list
235
236
  _info('list')
236
237
  if @opts[:service].nil? || @opts[:service].length.zero?
237
- @sesame.index.each do |service, users|
238
+ @cave.index.each do |service, users|
238
239
  next if service == 'sesame'
239
240
  if users.count > 1
240
241
  say("#{service} (#{users.count})")
@@ -243,7 +244,7 @@ module Sesame
243
244
  end
244
245
  end
245
246
  else
246
- users = @sesame.index[@opts[:service]]
247
+ users = @cave.index[@opts[:service]]
247
248
  raise Fail, 'No such service found, you must be thinking of some other cave' if users.nil? || @opts[:service] == 'sesame'
248
249
  users.sort.each do |user, _|
249
250
  say(user)
@@ -252,37 +253,37 @@ module Sesame
252
253
  end
253
254
 
254
255
  def _get
255
- phrase = @sesame.get(*_question, @opts[:offset])
256
- _info('get', @sesame.item)
256
+ phrase = @cave.get(*_question, @opts[:offset])
257
+ _info('get', @cave.item)
257
258
  _show(phrase)
258
259
  end
259
260
 
260
261
  def _add
261
- phrase = @sesame.insert(*_question(true), @opts[:offset])
262
- _info('add', @sesame.item)
262
+ phrase = @cave.insert(*_question(true), @opts[:offset])
263
+ _info('add', @cave.item)
263
264
  _show(phrase)
264
265
  end
265
266
 
266
267
  def _next
267
- phrase = @sesame.update(*_question, @opts[:offset])
268
+ phrase = @cave.update(*_question, @opts[:offset])
268
269
  if phrase.nil?
269
270
  _info('next_key')
270
271
  @was_locked = false
271
272
  _set_opt(:lock, true)
272
273
  else
273
- _info('next', @sesame.item)
274
+ _info('next', @cave.item)
274
275
  _show(phrase)
275
276
  end
276
277
  end
277
278
 
278
279
  def _delete
279
- phrase = @sesame.delete(*_question)
280
+ phrase = @cave.delete(*_question)
280
281
  _info('delete')
281
282
  _show(phrase)
282
283
  end
283
284
 
284
285
  def _lock
285
- key = @sesame.lock
286
+ key = @cave.lock
286
287
  return if @was_locked
287
288
  _info('lock')
288
289
  _show(key)
@@ -348,7 +349,7 @@ module Sesame
348
349
  _info('service')
349
350
  service = ask('🏷 ')
350
351
  end
351
- if user.nil? && (user_required || !@sesame.unique?(service))
352
+ if user.nil? && (user_required || !@cave.unique?(service))
352
353
  _info('user')
353
354
  user = ask('👤 ')
354
355
  end
data/sesame-cli.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: sesame-cli 0.2.0 ruby lib
5
+ # stub: sesame-cli 1.0.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "sesame-cli".freeze
9
- s.version = "0.2.0"
9
+ s.version = "1.0.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jason Hutchens".freeze, "Jack Casey".freeze]
14
- s.date = "2018-04-24"
14
+ s.date = "2018-04-25"
15
15
  s.description = "\u{1F9DE} - \"Sesame is a simple password manager for the command-line!\"".freeze
16
16
  s.email = "jasonhutchens@gmail.com".freeze
17
17
  s.executables = ["sesame".freeze]
data/spec/cave_spec.rb CHANGED
@@ -4,11 +4,15 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
 
5
5
  describe Sesame::Cave do
6
6
  let(:cave) { Sesame::Cave.new(Dir.tmpdir, 20) }
7
+ let(:deep_cave) { Sesame::Cave.new(Dir.tmpdir) }
7
8
 
8
9
  after do
9
10
  cave.close if cave.open?
10
11
  cave.forget if cave.locked?
11
12
  File.delete(cave.path) if cave.exists?
13
+ deep_cave.close if deep_cave.open?
14
+ deep_cave.forget if deep_cave.locked?
15
+ File.delete(deep_cave.path) if deep_cave.exists?
12
16
  end
13
17
 
14
18
  describe '#path' do
@@ -145,44 +149,349 @@ describe Sesame::Cave do
145
149
  end
146
150
 
147
151
  describe '#open?' do
152
+ context 'by default' do
153
+ it 'returns false' do
154
+ expect(cave.open?).to be false
155
+ end
156
+ end
157
+
158
+ context 'after #create!' do
159
+ before do
160
+ cave.create!
161
+ end
162
+ it 'returns true' do
163
+ expect(cave.open?).to be true
164
+ end
165
+ end
166
+
167
+ context 'after #create! and #close' do
168
+ before do
169
+ cave.create!
170
+ cave.close
171
+ end
172
+ it 'returns false' do
173
+ expect(cave.open?).to be false
174
+ end
175
+ end
176
+
177
+ context 'after #create! and #lock' do
178
+ before do
179
+ cave.create!
180
+ cave.lock
181
+ end
182
+ it 'returns false' do
183
+ expect(cave.open?).to be false
184
+ end
185
+ end
186
+
187
+ context 'after @create! and #close and #open' do
188
+ before do
189
+ phrase = cave.create!
190
+ cave.insert('foo', 'bar')
191
+ cave.close
192
+ cave.open(phrase)
193
+ end
194
+ it 'returns true' do
195
+ expect(cave.open?).to be true
196
+ end
197
+ end
148
198
  end
149
199
 
150
200
  describe '#dirty?' do
201
+ context 'by default' do
202
+ it 'returns false' do
203
+ expect(cave.dirty?).to be false
204
+ end
205
+ end
206
+
207
+ context 'after #create!' do
208
+ before do
209
+ cave.create!
210
+ end
211
+ it 'returns true' do
212
+ expect(cave.dirty?).to be true
213
+ end
214
+ end
215
+
216
+ context 'after #create! and #close' do
217
+ before do
218
+ cave.create!
219
+ cave.close
220
+ end
221
+ it 'returns false' do
222
+ expect(cave.dirty?).to be false
223
+ end
224
+ end
225
+
226
+ context 'after #create! and #lock' do
227
+ before do
228
+ cave.create!
229
+ cave.lock
230
+ end
231
+ it 'returns false' do
232
+ expect(cave.dirty?).to be false
233
+ end
234
+ end
235
+
236
+ context 'after @create! and #close and #open' do
237
+ before do
238
+ phrase = cave.create!
239
+ cave.insert('foo', 'bar')
240
+ cave.close
241
+ cave.open(phrase)
242
+ end
243
+ it 'returns false' do
244
+ expect(cave.dirty?).to be false
245
+ end
246
+ end
247
+
248
+ context 'after #open and #insert' do
249
+ before do
250
+ phrase = cave.create!
251
+ cave.insert('foo', 'bar')
252
+ cave.close
253
+ cave.open(phrase)
254
+ cave.insert('bar', 'foo')
255
+ end
256
+ it 'returns true' do
257
+ expect(cave.dirty?).to be true
258
+ end
259
+ end
260
+
261
+ context 'after #open and #update' do
262
+ before do
263
+ phrase = cave.create!
264
+ cave.insert('foo', 'bar')
265
+ cave.close
266
+ cave.open(phrase)
267
+ cave.update('foo', 'bar')
268
+ end
269
+ it 'returns true' do
270
+ expect(cave.dirty?).to be true
271
+ end
272
+ end
273
+
274
+ context 'after #open and #delete' do
275
+ before do
276
+ phrase = cave.create!
277
+ cave.insert('foo', 'bar')
278
+ cave.close
279
+ cave.open(phrase)
280
+ cave.delete('foo', 'bar')
281
+ end
282
+ it 'returns true' do
283
+ expect(cave.dirty?).to be true
284
+ end
285
+ end
151
286
  end
152
287
 
153
288
  describe '#create!' do
289
+ context 'by default' do
290
+ before do
291
+ cave.create!
292
+ end
293
+
294
+ it 'creates a new cave' do
295
+ expect(cave.exists?).to be false
296
+ expect(cave.locked?).to be false
297
+ expect(cave.open?).to be true
298
+ end
299
+ end
300
+
301
+ context 'with a pass phrase' do
302
+ before do
303
+ deep_cave.create!('mammal glue wage paper store detail weave date')
304
+ deep_cave.insert('twitter', 'kranzky')
305
+ end
306
+
307
+ it 'reconstructs an old cave' do
308
+ expect(deep_cave.exists?).to be false
309
+ expect(deep_cave.locked?).to be false
310
+ expect(deep_cave.open?).to be true
311
+ expect(deep_cave.get('twitter')).to eq('nylon sand slice party')
312
+ end
313
+ end
154
314
  end
155
315
 
156
316
  describe '#open' do
317
+ before do
318
+ phrase = cave.create!
319
+ cave.insert('foo', 'bar')
320
+ cave.close
321
+ cave.open(phrase)
322
+ cave.get('foo')
323
+ end
324
+ it 'opens an existing cave' do
325
+ expect(cave.exists?).to be true
326
+ expect(cave.locked?).to be false
327
+ expect(cave.open?).to be true
328
+ expect(cave.item[:user]).to eq('bar')
329
+ end
157
330
  end
158
331
 
159
332
  describe '#close' do
333
+ before do
334
+ cave.create!
335
+ cave.insert('foo', 'bar')
336
+ cave.close
337
+ end
338
+ it 'closes a cave' do
339
+ expect(cave.exists?).to be true
340
+ expect(cave.locked?).to be false
341
+ expect(cave.open?).to be false
342
+ end
160
343
  end
161
344
 
162
345
  describe '#lock' do
346
+ before do
347
+ cave.create!
348
+ cave.insert('foo', 'bar')
349
+ cave.lock
350
+ end
351
+ it 'locks a cave' do
352
+ expect(cave.exists?).to be true
353
+ expect(cave.locked?).to be true
354
+ expect(cave.open?).to be false
355
+ end
163
356
  end
164
357
 
165
358
  describe '#unlock' do
359
+ context 'with a word phrase' do
360
+ before do
361
+ cave.create!
362
+ cave.insert('foo', 'bar')
363
+ phrase = cave.lock
364
+ cave.unlock(phrase)
365
+ cave.get('foo')
366
+ end
367
+ it 'unlocks a cave' do
368
+ expect(cave.exists?).to be true
369
+ expect(cave.locked?).to be false
370
+ expect(cave.open?).to be true
371
+ expect(cave.item[:user]).to eq('bar')
372
+ end
373
+ end
374
+
375
+ context 'with a character code' do
376
+ before do
377
+ cave.create!
378
+ cave.insert('foo', 'bar')
379
+ code = cave.lock.split(' ').map { |w| w[0] }.join
380
+ cave.unlock(code)
381
+ cave.get('foo')
382
+ end
383
+ it 'unlocks a cave' do
384
+ expect(cave.exists?).to be true
385
+ expect(cave.locked?).to be false
386
+ expect(cave.open?).to be true
387
+ expect(cave.item[:user]).to eq('bar')
388
+ end
389
+ end
166
390
  end
167
391
 
168
392
  describe '#forget' do
393
+ before do
394
+ cave.create!
395
+ cave.insert('foo', 'bar')
396
+ cave.lock
397
+ cave.forget
398
+ end
399
+ it 'removes the lock file' do
400
+ expect(cave.exists?).to be true
401
+ expect(cave.locked?).to be false
402
+ expect(cave.open?).to be false
403
+ end
169
404
  end
170
405
 
171
406
  describe '#index' do
407
+ before do
408
+ cave.create!
409
+ cave.insert('foo', 'bar')
410
+ cave.insert('foo', 'xxx')
411
+ cave.insert('bar', 'foo')
412
+ end
413
+ let(:index) { cave.index }
414
+ it 'returns the contents of the cave' do
415
+ expect(index.count).to eq(3)
416
+ expect(index.keys[0]).to eq('bar')
417
+ expect(index.keys[2]).to eq('sesame')
418
+ expect(index['foo'].count).to eq(2)
419
+ expect(index['foo']['xxx']).to eq(0)
420
+ end
172
421
  end
173
422
 
174
423
  describe '#unique?' do
424
+ before do
425
+ cave.create!
426
+ cave.insert('foo', 'bar')
427
+ cave.insert('foo', 'xxx')
428
+ cave.insert('bar', 'foo')
429
+ end
430
+ it 'returns true for services that contain exactly one user' do
431
+ expect(cave.unique?('foo')).to be false
432
+ expect(cave.unique?('bar')).to be true
433
+ expect { cave.unique?('xxx') }.to raise_error(Sesame::Fail)
434
+ end
175
435
  end
176
436
 
177
437
  describe '#get' do
438
+ before do
439
+ cave.create!
440
+ cave.insert('foo', 'bar')
441
+ cave.insert('foo', 'xxx')
442
+ end
443
+ let!(:phrase) { cave.insert('bar', 'foo') }
444
+ it 'returns the phrase' do
445
+ expect(cave.item[:index]).to eq(0)
446
+ expect(cave.get('bar')).to eq(phrase)
447
+ expect(cave.get('bar', 'foo')).to eq(phrase)
448
+ expect { cave.get('foo') }.to raise_error(Sesame::Fail)
449
+ expect { cave.get('xxx') }.to raise_error(Sesame::Fail)
450
+ expect(cave.get('foo', 'xxx').split(' ').count).to eq(4)
451
+ end
178
452
  end
179
453
 
180
454
  describe '#insert' do
455
+ before do
456
+ cave.create!
457
+ cave.insert('foo', 'bar')
458
+ end
459
+ it 'inserts the item' do
460
+ expect(cave.item[:service]).to eq('foo')
461
+ expect(cave.item[:user]).to eq('bar')
462
+ expect(cave.item[:index]).to eq(0)
463
+ expect { cave.insert('foo', 'bar') }.to raise_error(Sesame::Fail)
464
+ expect(cave.insert('foo', 'xxx').split(' ').count).to eq(4)
465
+ expect(cave.item[:user]).to eq('xxx')
466
+ end
181
467
  end
182
468
 
183
469
  describe '#update' do
470
+ before do
471
+ cave.create!
472
+ end
473
+ let!(:phrase) { cave.insert('foo', 'bar') }
474
+ it 'updates the item' do
475
+ expect(cave.item[:index]).to eq(0)
476
+ expect(cave.get('foo')).to eq(phrase)
477
+ expect(cave.update('foo')).not_to eq(phrase)
478
+ expect(cave.item[:index]).to eq(1)
479
+ expect(cave.get('foo')).not_to eq(phrase)
480
+ end
184
481
  end
185
482
 
186
483
  describe '#delete' do
484
+ before do
485
+ cave.create!
486
+ cave.insert('foo', 'bar')
487
+ end
488
+ let!(:phrase) { cave.insert('bar', 'foo') }
489
+ it 'deletes the item' do
490
+ expect(cave.get('bar')).to eq(phrase)
491
+ expect(cave.delete('bar')).to eq(phrase)
492
+ expect { cave.get('bar') }.to raise_error(Sesame::Fail)
493
+ expect(cave.item[:service]).to eq('bar')
494
+ expect { cave.get('xxx') }.to raise_error(Sesame::Fail)
495
+ end
187
496
  end
188
497
  end
data/spec/jinn_spec.rb CHANGED
@@ -3,5 +3,39 @@
3
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
 
5
5
  describe Sesame::Jinn do
6
- let(:jinn) { Sesame::Jinn.new(opts) }
6
+ let(:opts) { double('opts') }
7
+ let(:jinn) { Sesame::Jinn.new(opts, 20) }
8
+
9
+ before do
10
+ option = double('option')
11
+ allow(opts).to receive(:echo?) { true }
12
+ allow(opts).to receive(:interactive?) { false }
13
+ allow(opts).to receive(:quiet?) { true }
14
+ allow(opts).to receive(:list?) { false }
15
+ allow(opts).to receive(:add?) { false }
16
+ allow(opts).to receive(:get?) { false }
17
+ allow(opts).to receive(:next?) { false }
18
+ allow(opts).to receive(:delete?) { false }
19
+ allow(opts).to receive(:lock?) { false }
20
+ allow(opts).to receive(:expunge?) { false }
21
+ allow(opts).to receive(:reconstruct?) { false }
22
+ allow(opts).to receive(:[]) { '/tmp' }
23
+ allow(opts).to receive(:option) { option }
24
+ allow(option).to receive(:ensure_call)
25
+ end
26
+
27
+ after do
28
+ cave = jinn.instance_variable_get(:@cave)
29
+ cave.close if cave.open?
30
+ cave.forget if cave.locked?
31
+ File.delete(cave.path) if cave.exists?
32
+ end
33
+
34
+ describe '#process!' do
35
+ context 'no arguments supplied' do
36
+ it 'exits with an error message' do
37
+ jinn.process!
38
+ end
39
+ end
40
+ end
7
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sesame-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Hutchens
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-04-24 00:00:00.000000000 Z
12
+ date: 2018-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bases