spec/unit/configuration/account_spec.rb in imap-backup-1.0.5 vs spec/unit/configuration/account_spec.rb in imap-backup-1.0.6

- old
+ new

@@ -1,216 +1,287 @@ # encoding: utf-8 require 'spec_helper' describe Imap::Backup::Configuration::Account do - include HighLineTestHelpers - include InputOutputTestHelpers + class MockHighlineMenu + attr_reader :choices + attr_accessor :header - def choose_menu_item(item) - @state = :initial - @input.should_receive(:gets) do - case @state - when :initial - @state = :done - "#{item}\n" - when :done - "quit\n" - end + def initialize + @choices = {} end + + def choice(name, &block) + choices[name] = block + end + + def hidden(name, &block) + choices[name] = block + end end context '#run' do - before :each do - @account1_path = '/backup/path' - @account1 = { - :username => 'user@example.com', - :password => 'secret', - :local_path => @account1_path, - :folders => [ { :name => 'my_folder' }, { :name => 'another_folder' } ] + let(:highline) { double('Highline') } + let(:menu) { MockHighlineMenu.new } + let(:store) { double('Imap::Backup::Configuration::Store', :data => data) } + let(:data) { {:accounts => [account, account1]} } + let(:account) do + { + :username => existing_email, + :server => existing_server, + :local_path => '/backup/path', + :folders => [{:name => 'my_folder'}], + :password => existing_password, } - @other_account_path = '/existing/path' - @other_account = { - :username => 'existing@example.com', - :password => 'secret', - :local_path => @other_account_path, - :folders => [] + end + let(:account1) do + { + :username => other_email, + :local_path => other_existing_path, } - @data = {:accounts => [@account1, @other_account]} - @store = stub('Imap::Backup::Configuration::Store') - @store.stub!(:data => @data) - @input, @output = prepare_highline - subject.stub(:system => nil) end + let(:existing_email) { 'user@example.com' } + let(:new_email) { 'foo@example.com' } + let(:existing_server) { 'imap.example.com' } + let(:existing_password) { 'password' } + let(:other_email) { 'other@example.com' } + let(:other_existing_path) { '/other/existing/path' } - subject { Imap::Backup::Configuration::Account.new(@store, @account1) } + before do + allow(subject).to receive(:system).and_return(nil) + allow(subject).to receive(:puts).and_return(nil) + allow(highline).to receive(:choose) do |&block| + block.call(menu) + throw :done + end + end - context 'menu' do + subject { described_class.new(store, account, highline) } + + context 'preparation' do + before { subject.run } + it 'clears the screen' do - subject.should_receive(:system).with('clear') + expect(subject).to have_received(:system).with('clear') + end - subject.run + context 'menu' do + it 'shows the menu' do + expect(highline).to have_received(:choose) + end end + end - it 'should show a menu' do - subject.run + context 'menu' do + [ + 'modify email', + 'modify password', + 'modify server', + 'modify backup path', + 'choose backup folders', + 'test connection', + 'delete', + 'return to main menu', + 'quit', # TODO: quit is hidden + ].each do |item| + before { subject.run } - @output.string.should =~ /modify email/ - @output.string.should =~ /modify password/ - @output.string.should =~ /modify backup path/ - @output.string.should =~ /choose backup folders/ - @output.string.should =~ /test authentication/ - @output.string.should =~ /delete/ - @output.string.should =~ /return to main/ + it "has a '#{item}' item" do + expect(menu.choices).to include(item) + end end + end - it 'should show account details in the menu' do - subject.run + context 'account details' do + [ + ['email', /email:\s+user@example.com/], + ['server', /server:\s+imap.example.com/], + ['password', /password:\s+x+/], + ['path', %r(path:\s+/backup/path)], + ['folders', /folders:\s+my_folder/], + ].each do |attribute, value| + before { subject.run } - @output.string.should =~ /email:\s+user@example.com/ - @output.string.should =~ /password:\s+x+/ - @output.string.should =~ %r{path:\s+/backup/path} - @output.string.should =~ /folders:\s+my_folder, another_folder/ + it "shows the #{attribute}" do + expect(menu.header).to match(value) + end end - it 'should indicate that a password is not set' do - @account1[:password] = '' + context 'with no password' do + let(:existing_password) { '' } - subject.run + before { subject.run } - @output.string.should =~ /password:\s+\(unset\)/ + it 'indicates that a password is not set' do + expect(menu.header).to include('password: (unset)') + end end - end context 'email' do - it 'should modify the email address' do - Imap::Backup::Configuration::Asker.should_receive(:email).once.and_return('new@example.com') + before do + allow(Imap::Backup::Configuration::Asker).to receive(:email).and_return(new_email) + subject.run + menu.choices['modify email'].call + end - choose_menu_item 'modify email' + context 'if the server is blank' do + [ + ['GMail', 'foo@gmail.com', 'imap.gmail.com'], + ['Fastmail', 'bar@fastmail.fm', 'mail.messagingengine.com'], + ].each do |service, email, expected| + context service do + let(:new_email) { email } - subject.run + context 'with nil' do + let(:existing_server) { nil } - @output.string.should =~ /email:\s+new@example.com/ - @account1[:username].should == 'new@example.com' + it 'sets a default server' do + expect(account[:server]).to eq(expected) + end + end + + context 'with an empty string' do + let(:existing_server) { '' } + + it 'sets a default server' do + expect(account[:server]).to eq(expected) + end + end + end + end end - it 'should do nothing if it creates a duplicate' do - Imap::Backup::Configuration::Asker.should_receive(:email).once.and_return('existing@example.com') + it 'modifies the email address' do + expect(account[:username]).to eq(new_email) + end - choose_menu_item 'modify email' + context 'the email already exists' do + let(:new_email) { other_email } - capturing_output do - subject.run - end.should =~ /there is already an account set up with that email address/i + it 'indicates the error' do + expect(subject).to have_received(:puts).with('There is already an account set up with that email address') + end + + it "doesn't set the email" do + expect(account[:username]).to eq(existing_email) + end end end context 'password' do - it 'should update the password' do - Imap::Backup::Configuration::Asker.should_receive(:password).once.and_return('new_pwd') + let(:new_password) { 'new_password' } - choose_menu_item 'modify password' - + before do + allow(Imap::Backup::Configuration::Asker).to receive(:password).and_return(new_password) subject.run + menu.choices['modify password'].call + end - @account1[:password].should == 'new_pwd' + it 'updates the password' do + expect(account[:password]).to eq(new_password) end - it 'should do nothing if the user cancels' do - Imap::Backup::Configuration::Asker.should_receive(:password).once.and_return(nil) + context 'if the user cancels' do + let(:new_password) { nil } - choose_menu_item 'modify password' + it 'does nothing' do + expect(account[:password]).to eq(existing_password) + end + end + end + context 'server' do + let(:server) { 'server' } + + before do + allow(highline).to receive(:ask).with('server: ').and_return(server) + end + + before do subject.run + menu.choices['modify server'].call + end - @account1[:password].should == 'secret' + it 'updates the server' do + expect(account[:server]).to eq(server) end end context 'backup_path' do - it 'should update the path' do - Imap::Backup::Configuration::Asker.should_receive(:backup_path).once do |default, validator| - validator.call('new/path') - '/new/path' - end + let(:new_backup_path) { '/new/path' } - choose_menu_item 'modify backup path' - + before do + @validator = nil + allow(Imap::Backup::Configuration::Asker).to receive(:backup_path) do |path, validator| + @validator = validator + new_backup_path + end subject.run + menu.choices['modify backup path'].call + end - @account1[:local_path].should == '/new/path' + it 'updates the path' do + expect(account[:local_path]).to eq(new_backup_path) end - it 'should validate that the path is not used by other backups' do - Imap::Backup::Configuration::Asker.should_receive(:backup_path) do |default, validator| - validator.call(@other_account_path) - '/path' - end - - choose_menu_item 'modify backup path' - - capturing_output do - subject.run - end.should =~ %r{The path '/existing/path' is used to backup the account 'existing@example.com'} + it 'validates that the path is not used by other backups' do + expect(@validator.call(other_existing_path)).to be_false end end - it 'should add/remove folders' do - @chooser = stub('Imap::Backup::Configuration::FolderChooser') - Imap::Backup::Configuration::FolderChooser.should_receive(:new).with(@account1).and_return(@chooser) - @chooser.should_receive(:run).with().once + context 'folders' do + let(:chooser) { double(:run => nil) } - choose_menu_item 'choose backup folders' + before do + allow(Imap::Backup::Configuration::FolderChooser).to receive(:new).and_return(chooser) + subject.run + menu.choices['choose backup folders'].call + end - subject.run + it 'edits folders' do + expect(chooser).to have_received(:run) + end end - it 'should allow testing the connection' do - Imap::Backup::Configuration::ConnectionTester.should_receive(:test).with(@account1).and_return('All fine') - - choose_menu_item 'test authentication' - - capturing_output do + context 'connection test' do + before do + allow(Imap::Backup::Configuration::ConnectionTester).to receive(:test).and_return('All fine') + allow(highline).to receive(:ask) subject.run - end.should == "All fine\n" + menu.choices['test connection'].call + end + + it 'tests the connection' do + expect(Imap::Backup::Configuration::ConnectionTester).to have_received(:test).with(account) + end end context 'deletion' do - it 'should confirm deletion' do - Imap::Backup::Configuration::Setup.highline.should_receive(:agree).with("Are you sure? (y/n) ").and_return(true) + let(:confirmed) { true } - choose_menu_item 'delete' - + before do + allow(highline).to receive(:agree).and_return(confirmed) subject.run + catch :done do + menu.choices['delete'].call + end end - it 'should delete the account' do - Imap::Backup::Configuration::Setup.highline.stub!(:agree).with("Are you sure? (y/n) ").and_return(true) - - choose_menu_item 'delete' - - subject.run - - @data[:accounts].should_not include(@account1) + it 'asks for confirmation' do + expect(highline).to have_received(:agree) end - it 'should not delete if confirmation is not given' do - Imap::Backup::Configuration::Setup.highline.stub!(:agree).with("Are you sure? (y/n) ").and_return(false) - - choose_menu_item 'delete' - - subject.run - - @data[:accounts].should include(@account1) + it 'deletes the account' do + expect(data[:accounts].find{|a| a[:username] == existing_email}).to be_nil end - end - context 'return to main menu' do - it 'should return' do - @input.stub!(:gets).with().and_return("return\n") + context 'without confirmation' do + let(:confirmed) { false } - subject.run.should be_nil + it 'does nothing' do + expect(data[:accounts].find{|a| a[:username] == existing_email}).to eq(account) + end end end end end -