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