main
1module TFA
2 describe TotpCommand do
3 subject { TotpCommand.new(storage) }
4 let(:storage) { Storage.new(File.join(Dir.tmpdir, SecureRandom.uuid)) }
5
6 def code_for(secret)
7 ::ROTP::TOTP.new(secret).now
8 end
9
10 describe "#run" do
11 context "when a single key is given" do
12 let(:secret) { ::ROTP::Base32.random_base32 }
13
14 it "returns a time based one time password for the authentication secret given" do
15 storage.save("development", secret)
16 expect(subject.run("development")).to eql(code_for(secret))
17 end
18 end
19
20 context "when no arguments are given" do
21 let(:development_secret) { ::ROTP::Base32.random_base32 }
22 let(:staging_secret) { ::ROTP::Base32.random_base32 }
23
24 it "returns the one time password for all keys" do
25 storage.save("development", development_secret)
26 storage.save("staging", staging_secret)
27
28 expect(subject.run(nil)).to match_array([
29 { "development" => code_for(development_secret) },
30 { "staging" => code_for(staging_secret) }
31 ])
32 end
33 end
34
35 context "when the key is not known" do
36 it "returns with nothing" do
37 expect(subject.run(["blah"])).to be_empty
38 end
39 end
40
41 context "when the secret is invalid" do
42 let(:invalid_secret) { "hello world" }
43
44 before :each do
45 storage.save("development", invalid_secret)
46 end
47
48 it "returns an error message" do
49 expected = { "development" => "INVALID SECRET" }
50 expect(subject.run(["development"])).to match_array([expected])
51 end
52 end
53 end
54 end
55end