imap-backup 0.0.3 → 0.0.4

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.
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+ load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
3
+
4
+ describe Imap::Backup::Configuration::ConnectionTester do
5
+
6
+ context '.test' do
7
+
8
+ it 'should try to connect' do
9
+ Imap::Backup::Account::Connection.should_receive(:new).with('foo')
10
+
11
+ Imap::Backup::Configuration::ConnectionTester.test('foo')
12
+ end
13
+
14
+ it 'should return success if the connection works' do
15
+ Imap::Backup::Account::Connection.stub!(:new).
16
+ with('foo')
17
+
18
+ result = Imap::Backup::Configuration::ConnectionTester.test('foo')
19
+
20
+ result.should =~ /successful/
21
+ end
22
+
23
+ it 'should handle no response' do
24
+ e = Net::IMAP::NoResponseError.new(stub('o', :data => stub('foo', :text => 'bar')))
25
+ Imap::Backup::Account::Connection.stub!(:new).
26
+ with('foo').
27
+ and_raise(e)
28
+
29
+ result = Imap::Backup::Configuration::ConnectionTester.test('foo')
30
+
31
+ result.should =~ /no response/i
32
+ end
33
+
34
+ it 'should handle other errors' do
35
+ Imap::Backup::Account::Connection.stub!(:new).
36
+ with('foo').
37
+ and_raise('error')
38
+
39
+ result = Imap::Backup::Configuration::ConnectionTester.test('foo')
40
+
41
+ result.should =~ /unexpected error/i
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
@@ -0,0 +1,131 @@
1
+ # encoding: utf-8
2
+ load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
3
+
4
+ describe Imap::Backup::Configuration::FolderChooser do
5
+
6
+ include HighLineTestHelpers
7
+ include InputOutputTestHelpers
8
+
9
+ context '#run' do
10
+
11
+ before :each do
12
+ empty_account = {
13
+ :folders => []
14
+ }
15
+ @connection = setup_account(empty_account, [])
16
+ @input, @output = prepare_highline
17
+ end
18
+
19
+ def setup_account(account, remote_folders)
20
+ @account = account
21
+ connection = stub('Imap::Backup::Account::Connection')
22
+ connection.stub!(:folders).and_return(remote_folders)
23
+ Imap::Backup::Account::Connection.stub!(:new).with(account).and_return(connection)
24
+ connection
25
+ end
26
+
27
+ subject { Imap::Backup::Configuration::FolderChooser.new(@account) }
28
+
29
+ it 'should connect to the account' do
30
+ Imap::Backup::Account::Connection.should_receive(:new).with(@account).and_return(@connection)
31
+
32
+ subject.run
33
+ end
34
+
35
+ it 'should handle connection errors' do
36
+ Imap::Backup::Account::Connection.should_receive(:new).with(@account).and_raise('error')
37
+ Imap::Backup::Configuration::Setup.highline.should_receive(:ask).with('Press a key ')
38
+
39
+ capturing_output do
40
+ subject.run
41
+ end.should =~ /connection failed/i
42
+ end
43
+
44
+ it 'should get a list of account folders' do
45
+ @connection.should_receive(:folders).and_return([])
46
+
47
+ subject.run
48
+ end
49
+
50
+ it 'should show the menu' do
51
+ subject.run
52
+
53
+ @output.string.should =~ %r{Add/remove folders}
54
+ end
55
+
56
+ it 'should return to the account menu' do
57
+ @input.should_receive(:gets).and_return("return\n")
58
+
59
+ subject.run
60
+
61
+ @output.string.should =~ %r{return to the account menu}
62
+ end
63
+
64
+ context 'folder listing' do
65
+
66
+ before :each do
67
+ account = {
68
+ :folders => [{:name => 'my_folder'}]
69
+ }
70
+ folder1 = stub('folder', :name => 'my_folder') # this one is already backed up
71
+ folder2 = stub('folder', :name => 'another_folder')
72
+ remote_folders = [folder1, folder2]
73
+ @connection = setup_account(account, remote_folders)
74
+ end
75
+
76
+ it 'should list folders' do
77
+ subject.run
78
+
79
+ @output.string.should =~ /my_folder/
80
+ end
81
+
82
+ it 'should show which folders are already being backed up' do
83
+ subject.run
84
+
85
+ @output.string.should =~ /\d+\. \+ my_folder/
86
+ @output.string.should =~ /\d+\. \- another_folder/
87
+ end
88
+
89
+ it 'should add folders' do
90
+ state = :initial
91
+ @input.stub(:gets) do
92
+ case state
93
+ when :initial
94
+ state = :added
95
+ "2\n" # choose 'another_folder'
96
+ else
97
+ "q\n"
98
+ end
99
+ end
100
+
101
+ subject.run
102
+
103
+ @output.string.should =~ /\d+\. \+ another_folder/
104
+ @account[:folders].should include( { :name => 'another_folder' } )
105
+ end
106
+
107
+ it 'should remove folders' do
108
+ state = :initial
109
+ @input.stub(:gets) do
110
+ case state
111
+ when :initial
112
+ state = :added
113
+ "1\n"
114
+ else
115
+ "q\n"
116
+ end
117
+ end
118
+
119
+ subject.run
120
+
121
+ @output.string.should =~ /\d+\. \- my_folder/
122
+ @account[:folders].should_not include( { :name => 'my_folder' } )
123
+ end
124
+
125
+
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+ load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
3
+
4
+ describe Imap::Backup::Configuration::List do
5
+ before :each do
6
+ @configuration_data = {
7
+ :accounts => [
8
+ {
9
+ :username => 'a1@example.com'
10
+ },
11
+ {
12
+ :username => 'a2@example.com',
13
+ },
14
+ ]
15
+ }
16
+ @store = stub('Imap::Backup::Configuration::Store', :data => @configuration_data)
17
+ Imap::Backup::Configuration::Store.stub!(:new => @store)
18
+ end
19
+
20
+ context '#initialize' do
21
+
22
+ context 'with account parameter' do
23
+ it 'should only create requested accounts' do
24
+ configuration = Imap::Backup::Configuration::List.new(['a2@example.com'])
25
+
26
+ configuration.accounts.should == @configuration_data[:accounts][1..1]
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ context 'instance methods' do
33
+
34
+ before :each do
35
+ @connection = stub('Imap::Backup::Account::Connection', :disconnect => nil)
36
+ end
37
+
38
+ subject { Imap::Backup::Configuration::List.new }
39
+
40
+ context '#each_connection' do
41
+
42
+ it 'should instantiate connections' do
43
+ Imap::Backup::Account::Connection.should_receive(:new).with(@configuration_data[:accounts][0]).and_return(@connection)
44
+ Imap::Backup::Account::Connection.should_receive(:new).with(@configuration_data[:accounts][1]).and_return(@connection)
45
+
46
+ subject.each_connection{}
47
+ end
48
+
49
+ it 'should call the block' do
50
+ Imap::Backup::Account::Connection.stub!(:new).and_return(@connection)
51
+ calls = 0
52
+
53
+ subject.each_connection do |a|
54
+ calls += 1
55
+ a.should == @connection
56
+ end
57
+ calls.should == 2
58
+ end
59
+
60
+ it 'should disconnect connections' do
61
+ Imap::Backup::Account::Connection.stub!(:new).and_return(@connection)
62
+
63
+ @connection.should_receive(:disconnect)
64
+
65
+ subject.each_connection {}
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+ load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
3
+
4
+ describe Imap::Backup::Configuration::Setup do
5
+
6
+ include HighLineTestHelpers
7
+
8
+ context '#initialize' do
9
+
10
+ it 'should not require the config file to exist' do
11
+ Imap::Backup::Configuration::Store.should_receive(:new).with(false)
12
+
13
+ Imap::Backup::Configuration::Setup.new
14
+ end
15
+
16
+ end
17
+
18
+ context '#run' do
19
+
20
+ before :each do
21
+ prepare_store
22
+ @input, @output = prepare_highline
23
+ end
24
+
25
+ def prepare_store
26
+ accounts = [
27
+ { :username => 'account@example.com' }
28
+ ]
29
+ @data = {:accounts => accounts}
30
+ @store = stub('Imap::Backup::Configuration::Store', :data => @data, :path => '/base/path')
31
+ Imap::Backup::Configuration::Store.stub!(:new).with(false).and_return(@store)
32
+ end
33
+
34
+ subject { Imap::Backup::Configuration::Setup.new }
35
+
36
+ it 'should present a main menu' do
37
+ @input.should_receive(:eof?).and_return(false)
38
+ @input.should_receive(:gets).and_return("q\n")
39
+
40
+ subject.run
41
+
42
+ @output.string.should =~ /Choose an action:/
43
+ @output.string.should =~ /add account/
44
+ @output.string.should =~ /save and exit/
45
+ @output.string.should =~ /quit/
46
+ end
47
+
48
+ it 'should list accounts' do
49
+ subject.run
50
+
51
+ @output.string.should =~ /account@example.com/
52
+ end
53
+
54
+ it 'should edit accounts' do
55
+ state = :initial
56
+ @input.stub(:gets) do
57
+ case state
58
+ when :initial
59
+ state = :editing
60
+ "account@example.com\n"
61
+ else
62
+ "q\n"
63
+ end
64
+ end
65
+
66
+ @account = stub('Imap::Backup::Configuration::Account')
67
+ Imap::Backup::Configuration::Account.should_receive(:new).with(@store, 'account@example.com').and_return(@account)
68
+ @account.should_receive(:run).with()
69
+
70
+ subject.run
71
+ end
72
+
73
+ it 'should add accounts' do
74
+ state = :initial
75
+ @input.stub(:gets) do
76
+ case state
77
+ when :initial
78
+ state = :editing
79
+ "add\n"
80
+ else
81
+ "q\n"
82
+ end
83
+ end
84
+
85
+ Imap::Backup::Configuration::Asker.should_receive(:email).with().and_return('new@example.com')
86
+ Imap::Backup::Configuration::Account.should_receive(:new).with(@store, 'new@example.com')
87
+
88
+ subject.run
89
+
90
+ @data[:accounts].size.should == 2
91
+ @data[:accounts][1].should == {
92
+ :username => "new@example.com",
93
+ :password => "",
94
+ :local_path => "/base/path/new_example.com",
95
+ :folders => []
96
+ }
97
+ end
98
+
99
+ it 'should save the configuration' do
100
+ @input.should_receive(:gets).with().and_return("save\n")
101
+ @store.should_receive(:save).with()
102
+
103
+ subject.run
104
+ end
105
+
106
+ it 'should exit' do
107
+ @input.should_receive(:gets).with().and_return("quit\n")
108
+
109
+ subject.run
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
@@ -0,0 +1,173 @@
1
+ # encoding: utf-8
2
+ load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
3
+
4
+ describe Imap::Backup::Configuration::Store do
5
+
6
+ before :all do
7
+ @configuration_directory = Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY
8
+ Imap::Backup::Configuration::Store.instance_eval { remove_const :'CONFIGURATION_DIRECTORY' }
9
+ Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY = '/base/path'
10
+ end
11
+
12
+ after :all do
13
+ Imap::Backup::Configuration::Store.instance_eval { remove_const :'CONFIGURATION_DIRECTORY' }
14
+ Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY = @configuration_directory
15
+ end
16
+
17
+ context '#initialize' do
18
+
19
+ before :each do
20
+ Imap::Backup::Utils.stub!(:check_permissions => nil)
21
+ end
22
+
23
+ it 'by default, should fail if the config file is missing' do
24
+ File.should_receive(:directory?).with('/base/path').and_return(true)
25
+ File.should_receive(:exist?).with('/base/path/config.json').and_return(false)
26
+
27
+ expect do
28
+ Imap::Backup::Configuration::Store.new
29
+ end.to raise_error(Imap::Backup::ConfigurationNotFound, /not found/)
30
+ end
31
+
32
+ it 'should not fail if fail_if_missing is false' do
33
+ File.should_receive(:directory?).with('/base/path').and_return(true)
34
+ File.should_receive(:exist?).with('/base/path/config.json').and_return(false)
35
+
36
+ expect do
37
+ Imap::Backup::Configuration::Store.new(false)
38
+ end.to_not raise_error
39
+ end
40
+
41
+ it 'should fail if the config file permissions are too lax' do
42
+ File.stub!(:exist?).with('/base/path/config.json').and_return(true)
43
+
44
+ Imap::Backup::Utils.should_receive(:check_permissions).with('/base/path/config.json', 0600).and_raise('Error')
45
+
46
+ expect do
47
+ Imap::Backup::Configuration::Store.new
48
+ end.to raise_error(RuntimeError, 'Error')
49
+ end
50
+
51
+ it 'should load the config file' do
52
+ File.stub!(:exist?).with('/base/path/config.json').and_return(true)
53
+
54
+ configuration = 'JSON string'
55
+ File.should_receive(:read).with('/base/path/config.json').and_return(configuration)
56
+ JSON.should_receive(:parse).with(configuration, :symbolize_names => true)
57
+
58
+ Imap::Backup::Configuration::Store.new
59
+ end
60
+
61
+ end
62
+
63
+ context '#save' do
64
+
65
+ before :each do
66
+ # initialize
67
+ File.stub!(:directory?).with('/base/path').and_return(false)
68
+ File.stub!(:exist?).with('/base/path/config.json').and_return(false)
69
+ # save
70
+ @file = stub('File')
71
+ File.stub!(:directory?).with('/base/path').and_return(false)
72
+ FileUtils.stub!(:mkdir).with('/base/path')
73
+ Imap::Backup::Utils.stub!(:stat).with('/base/path').and_return(0700)
74
+ FileUtils.stub!(:chmod).with(0700, '/base/path')
75
+ File.stub!(:open).with('/base/path/config.json', 'w') { |&b| b.call @file }
76
+ JSON.stub!(:pretty_generate => 'JSON output')
77
+ @file.stub!(:write).with('JSON output')
78
+ FileUtils.stub!(:chmod).with(0600, '/base/path/config.json')
79
+ end
80
+
81
+ subject { Imap::Backup::Configuration::Store.new(false) }
82
+
83
+ it 'should create the config directory' do
84
+ File.should_receive(:directory?).with('/base/path').and_return(false)
85
+ FileUtils.should_receive(:mkdir).with('/base/path')
86
+
87
+ subject.save
88
+ end
89
+
90
+ it 'should save the config file' do
91
+ @file.should_receive(:write).with('JSON output')
92
+
93
+ subject.save
94
+ end
95
+
96
+ it 'should set config perms to 0600' do
97
+ FileUtils.should_receive(:chmod).with(0600, '/base/path/config.json')
98
+
99
+ subject.save
100
+ end
101
+
102
+ context 'saving accounts' do
103
+
104
+ before :each do
105
+ # initialize
106
+ File.stub!(:exist?).with('/base/path/config.json').and_return(true)
107
+ Imap::Backup::Utils.stub!(:check_permissions).with('/base/path/config.json', 0600)
108
+ folders = [
109
+ { :name => 'A folder' },
110
+ ]
111
+ File.stub!(:read).with('/base/path/config.json').and_return('xxx')
112
+ JSON.stub!(:parse).with('xxx', :symbolize_names => true).and_return(configuration(folders))
113
+ # save
114
+ File.stub!(:directory?).with('/my/backup/path').and_return(false)
115
+ FileUtils.stub!(:mkdir).with('/my/backup/path')
116
+ Imap::Backup::Utils.stub!(:stat).with('/my/backup/path').and_return(0700)
117
+ File.stub!(:directory?).with('/my/backup/path/A folder').and_return(false)
118
+ FileUtils.stub!(:mkdir).with('/my/backup/path/A folder')
119
+ Imap::Backup::Utils.stub!(:stat).with('/my/backup/path/A folder').and_return(0700)
120
+ end
121
+
122
+ def configuration(folders)
123
+ {
124
+ :accounts => [
125
+ :local_path => '/my/backup/path',
126
+ :folders => folders
127
+ ]
128
+ }
129
+ end
130
+
131
+ subject { Imap::Backup::Configuration::Store.new }
132
+
133
+ it 'should create account directories' do
134
+ File.should_receive(:directory?).with('/my/backup/path').and_return(false)
135
+ FileUtils.should_receive(:mkdir).with('/my/backup/path')
136
+
137
+ subject.save
138
+ end
139
+
140
+ it 'should create folder directories' do
141
+ File.should_receive(:directory?).with('/my/backup/path/A folder').and_return(false)
142
+ FileUtils.should_receive(:mkdir).with('/my/backup/path/A folder')
143
+
144
+ subject.save
145
+ end
146
+
147
+ it 'should set directory permissions, if necessary' do
148
+ Imap::Backup::Utils.stub!(:stat).with('/my/backup/path/A folder').and_return(0755)
149
+ FileUtils.should_receive(:chmod).with(0700, '/my/backup/path/A folder')
150
+
151
+ subject.save
152
+ end
153
+
154
+ it 'should create a path for folders with slashes' do
155
+ folders = [
156
+ { :name => 'folder/path' },
157
+ ]
158
+ JSON.stub!(:parse).with('xxx', :symbolize_names => true).and_return(configuration(folders))
159
+
160
+ File.should_receive(:directory?).with('/my/backup/path/folder').and_return(true)
161
+ Imap::Backup::Utils.should_receive(:stat).with('/my/backup/path/folder').and_return(0700)
162
+ File.should_receive(:directory?).with('/my/backup/path/folder/path').and_return(true)
163
+ Imap::Backup::Utils.should_receive(:stat).with('/my/backup/path/folder/path').and_return(0700)
164
+
165
+ subject.save
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+