imap-backup 2.0.0 → 2.1.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 +4 -4
- data/.rspec-all +2 -0
- data/.rubocop.yml +10 -1
- data/.travis.yml +1 -0
- data/README.md +1 -1
- data/Rakefile +0 -1
- data/bin/imap-backup +3 -9
- data/imap-backup.gemspec +5 -5
- data/lib/email/mboxrd/message.rb +2 -2
- data/lib/imap/backup/account/connection.rb +11 -3
- data/lib/imap/backup/account/folder.rb +11 -6
- data/lib/imap/backup/configuration/account.rb +7 -7
- data/lib/imap/backup/configuration/asker.rb +2 -1
- data/lib/imap/backup/configuration/connection_tester.rb +1 -1
- data/lib/imap/backup/configuration/folder_chooser.rb +32 -5
- data/lib/imap/backup/configuration/list.rb +2 -0
- data/lib/imap/backup/configuration/setup.rb +2 -1
- data/lib/imap/backup/configuration/store.rb +3 -6
- data/lib/imap/backup/downloader.rb +8 -7
- data/lib/imap/backup/serializer/mbox.rb +2 -1
- data/lib/imap/backup/serializer/mbox_store.rb +14 -6
- data/lib/imap/backup/uploader.rb +1 -0
- data/lib/imap/backup/utils.rb +11 -9
- data/lib/imap/backup/version.rb +1 -1
- data/spec/features/backup_spec.rb +6 -5
- data/spec/features/support/backup_directory.rb +5 -5
- data/spec/features/support/email_server.rb +11 -8
- data/spec/features/support/shared/connection_context.rb +2 -2
- data/spec/support/fixtures.rb +1 -1
- data/spec/support/higline_test_helpers.rb +1 -1
- data/spec/unit/email/mboxrd/message_spec.rb +51 -42
- data/spec/unit/email/provider_spec.rb +0 -2
- data/spec/unit/imap/backup/account/connection_spec.rb +18 -11
- data/spec/unit/imap/backup/account/folder_spec.rb +26 -12
- data/spec/unit/imap/backup/configuration/account_spec.rb +22 -19
- data/spec/unit/imap/backup/configuration/asker_spec.rb +30 -31
- data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +16 -13
- data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +45 -18
- data/spec/unit/imap/backup/configuration/list_spec.rb +8 -13
- data/spec/unit/imap/backup/configuration/setup_spec.rb +36 -30
- data/spec/unit/imap/backup/configuration/store_spec.rb +7 -4
- data/spec/unit/imap/backup/downloader_spec.rb +11 -7
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +2 -5
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +4 -4
- data/spec/unit/imap/backup/uploader_spec.rb +0 -2
- data/spec/unit/imap/backup/utils_spec.rb +1 -3
- metadata +6 -6
@@ -1,15 +1,16 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
1
|
describe Imap::Backup::Configuration::ConnectionTester do
|
4
2
|
context ".test" do
|
5
|
-
let(:connection)
|
3
|
+
let(:connection) do
|
4
|
+
instance_double(Imap::Backup::Account::Connection, imap: nil)
|
5
|
+
end
|
6
|
+
let(:result) { subject.test("foo") }
|
6
7
|
|
7
8
|
before do
|
8
9
|
allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
|
9
10
|
end
|
10
11
|
|
11
12
|
context "call" do
|
12
|
-
before {
|
13
|
+
before { result }
|
13
14
|
|
14
15
|
it "tries to connect" do
|
15
16
|
expect(connection).to have_received(:imap)
|
@@ -17,34 +18,36 @@ describe Imap::Backup::Configuration::ConnectionTester do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
context "success" do
|
20
|
-
before {
|
21
|
+
before { result }
|
21
22
|
|
22
23
|
it "returns success" do
|
23
|
-
expect(
|
24
|
+
expect(result).to match(/successful/)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
28
|
context "failure" do
|
28
29
|
before do
|
29
30
|
allow(connection).to receive(:imap).and_raise(error)
|
30
|
-
|
31
|
+
result
|
31
32
|
end
|
32
33
|
|
33
34
|
context "no connection" do
|
34
35
|
let(:error) do
|
35
|
-
data =
|
36
|
-
|
36
|
+
data = OpenStruct.new(text: "bar")
|
37
|
+
response = OpenStruct.new(data: data)
|
38
|
+
Net::IMAP::NoResponseError.new(response)
|
37
39
|
end
|
38
40
|
|
39
|
-
it "returns
|
40
|
-
expect(
|
41
|
+
it "returns error" do
|
42
|
+
expect(result).to match(/no response/i)
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
46
|
context "other" do
|
45
47
|
let(:error) { "Error" }
|
46
|
-
|
47
|
-
|
48
|
+
|
49
|
+
it "returns error" do
|
50
|
+
expect(result).to match(/unexpected error/i)
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
@@ -1,22 +1,23 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
1
|
describe Imap::Backup::Configuration::FolderChooser do
|
4
2
|
include HighLineTestHelpers
|
5
3
|
|
6
4
|
context "#run" do
|
5
|
+
subject { described_class.new(account) }
|
6
|
+
|
7
7
|
let(:connection) do
|
8
|
-
|
8
|
+
instance_double(
|
9
|
+
Imap::Backup::Account::Connection, folders: remote_folders
|
10
|
+
)
|
9
11
|
end
|
10
12
|
let(:account) { {folders: []} }
|
11
13
|
let(:remote_folders) { [] }
|
12
|
-
|
13
|
-
|
14
|
+
let!(:highline_streams) { prepare_highline }
|
15
|
+
let(:input) { highline_streams[0] }
|
16
|
+
let(:output) { highline_streams[1] }
|
14
17
|
|
15
18
|
before do
|
16
|
-
allow(Imap::Backup::Account::Connection).
|
17
|
-
|
18
|
-
@input, @output = prepare_highline
|
19
|
-
allow(subject).to receive(:system)
|
19
|
+
allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
|
20
|
+
allow(Kernel).to receive(:system)
|
20
21
|
allow(Imap::Backup.logger).to receive(:warn)
|
21
22
|
end
|
22
23
|
|
@@ -24,11 +25,11 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
24
25
|
before { subject.run }
|
25
26
|
|
26
27
|
it "clears the screen" do
|
27
|
-
expect(
|
28
|
+
expect(Kernel).to have_received(:system).with("clear")
|
28
29
|
end
|
29
30
|
|
30
|
-
it "
|
31
|
-
expect(
|
31
|
+
it "shows the menu" do
|
32
|
+
expect(output.string).to match %r{Add/remove folders}
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
@@ -36,8 +37,12 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
36
37
|
let(:account) { {folders: [{name: "my_folder"}]} }
|
37
38
|
let(:remote_folders) do
|
38
39
|
# this one is already backed up:
|
39
|
-
folder1 =
|
40
|
-
|
40
|
+
folder1 = instance_double(
|
41
|
+
Imap::Backup::Account::Folder, name: "my_folder"
|
42
|
+
)
|
43
|
+
folder2 = instance_double(
|
44
|
+
Imap::Backup::Account::Folder, name: "another_folder"
|
45
|
+
)
|
41
46
|
[folder1, folder2]
|
42
47
|
end
|
43
48
|
|
@@ -45,17 +50,17 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
45
50
|
before { subject.run }
|
46
51
|
|
47
52
|
it "shows folders which are being backed up" do
|
48
|
-
expect(
|
53
|
+
expect(output.string).to include("+ my_folder")
|
49
54
|
end
|
50
55
|
|
51
56
|
it "shows folders which are not being backed up" do
|
52
|
-
expect(
|
57
|
+
expect(output.string).to include("- another_folder")
|
53
58
|
end
|
54
59
|
end
|
55
60
|
|
56
61
|
context "adding folders" do
|
57
62
|
before do
|
58
|
-
allow(
|
63
|
+
allow(input).to receive(:gets).and_return("2\n", "q\n")
|
59
64
|
|
60
65
|
subject.run
|
61
66
|
end
|
@@ -69,7 +74,7 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
69
74
|
|
70
75
|
context "removing folders" do
|
71
76
|
before do
|
72
|
-
allow(
|
77
|
+
allow(input).to receive(:gets).and_return("1\n", "q\n")
|
73
78
|
|
74
79
|
subject.run
|
75
80
|
end
|
@@ -82,6 +87,28 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
90
|
+
context "with missing remote folders" do
|
91
|
+
let(:account) do
|
92
|
+
{folders: [{name: "on_server"}, {name: "not_on_server"}]}
|
93
|
+
end
|
94
|
+
let(:remote_folders) do
|
95
|
+
[
|
96
|
+
instance_double(Imap::Backup::Account::Folder, name: "on_server")
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
100
|
+
before do
|
101
|
+
allow(Kernel).to receive(:puts)
|
102
|
+
subject.run
|
103
|
+
end
|
104
|
+
|
105
|
+
specify "are removed from the account" do
|
106
|
+
expect(account[:folders]).to_not include(name: "not_on_server")
|
107
|
+
end
|
108
|
+
|
109
|
+
include_examples "it flags the account as modified"
|
110
|
+
end
|
111
|
+
|
85
112
|
context "when folders are not available" do
|
86
113
|
let(:remote_folders) { nil }
|
87
114
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
1
|
describe Imap::Backup::Configuration::List do
|
2
|
+
subject { described_class.new }
|
3
|
+
|
4
4
|
let(:accounts) do
|
5
5
|
[
|
6
6
|
{username: "a1@example.com"},
|
@@ -8,14 +8,14 @@ describe Imap::Backup::Configuration::List do
|
|
8
8
|
]
|
9
9
|
end
|
10
10
|
let(:store) do
|
11
|
-
|
11
|
+
instance_double(Imap::Backup::Configuration::Store, accounts: accounts)
|
12
12
|
end
|
13
13
|
let(:exists) { true }
|
14
14
|
let(:connection1) do
|
15
|
-
|
15
|
+
instance_double(Imap::Backup::Account::Connection, disconnect: nil)
|
16
16
|
end
|
17
17
|
let(:connection2) do
|
18
|
-
|
18
|
+
instance_double(Imap::Backup::Account::Connection, disconnect: nil)
|
19
19
|
end
|
20
20
|
|
21
21
|
before do
|
@@ -28,11 +28,6 @@ describe Imap::Backup::Configuration::List do
|
|
28
28
|
to receive(:new).with(accounts[1]) { connection2 }
|
29
29
|
end
|
30
30
|
|
31
|
-
subject { described_class.new }
|
32
|
-
|
33
|
-
context "#initialize" do
|
34
|
-
end
|
35
|
-
|
36
31
|
context "#each_connection" do
|
37
32
|
specify "calls the block with each account's connection" do
|
38
33
|
connections = []
|
@@ -45,7 +40,7 @@ describe Imap::Backup::Configuration::List do
|
|
45
40
|
context "with account parameter" do
|
46
41
|
subject { described_class.new(["a2@example.com"]) }
|
47
42
|
|
48
|
-
it "
|
43
|
+
it "only creates requested accounts" do
|
49
44
|
connections = []
|
50
45
|
|
51
46
|
subject.each_connection { |a| connections << a }
|
@@ -58,9 +53,9 @@ describe Imap::Backup::Configuration::List do
|
|
58
53
|
let(:exists) { false }
|
59
54
|
|
60
55
|
it "fails" do
|
61
|
-
expect
|
56
|
+
expect do
|
62
57
|
subject.each_connection {}
|
63
|
-
|
58
|
+
end.to raise_error(Imap::Backup::ConfigurationNotFound, /not found/)
|
64
59
|
end
|
65
60
|
end
|
66
61
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# rubocop:disable RSpec/NestedGroups
|
2
2
|
|
3
3
|
describe Imap::Backup::Configuration::Setup do
|
4
4
|
include HighLineTestHelpers
|
@@ -12,39 +12,41 @@ describe Imap::Backup::Configuration::Setup do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
context "#run" do
|
15
|
+
subject { described_class.new }
|
16
|
+
|
15
17
|
let(:normal) { {username: "account@example.com"} }
|
16
18
|
let(:accounts) { [normal] }
|
17
19
|
let(:store) do
|
18
|
-
|
19
|
-
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
instance_double(
|
21
|
+
Imap::Backup::Configuration::Store,
|
22
|
+
"accounts": accounts,
|
23
|
+
"path": "/base/path",
|
24
|
+
"save": nil,
|
25
|
+
"debug?": debug,
|
26
|
+
"debug=": nil,
|
27
|
+
"modified?": modified
|
26
28
|
)
|
27
29
|
end
|
28
30
|
let(:debug) { false }
|
29
31
|
let(:modified) { false }
|
32
|
+
let!(:highline_streams) { prepare_highline }
|
33
|
+
let(:input) { highline_streams[0] }
|
34
|
+
let(:output) { highline_streams[1] }
|
30
35
|
|
31
|
-
before
|
36
|
+
before do
|
32
37
|
allow(Imap::Backup::Configuration::Store).to receive(:new) { store }
|
33
38
|
allow(Imap::Backup).to receive(:setup_logging)
|
34
|
-
|
35
|
-
allow(
|
36
|
-
allow(
|
37
|
-
allow(subject).to receive(:system)
|
39
|
+
allow(input).to receive(:eof?) { false }
|
40
|
+
allow(input).to receive(:gets) { "exit\n" }
|
41
|
+
allow(Kernel).to receive(:system)
|
38
42
|
end
|
39
43
|
|
40
|
-
subject { described_class.new }
|
41
|
-
|
42
44
|
context "main menu" do
|
43
45
|
before { subject.run }
|
44
46
|
|
45
47
|
%w(add\ account save\ and\ exit exit\ without\ saving).each do |choice|
|
46
48
|
it "includes #{choice}" do
|
47
|
-
expect(
|
49
|
+
expect(output.string).to include(choice)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -52,7 +54,7 @@ describe Imap::Backup::Configuration::Setup do
|
|
52
54
|
it "clears the screen" do
|
53
55
|
subject.run
|
54
56
|
|
55
|
-
expect(
|
57
|
+
expect(Kernel).to have_received(:system).with("clear")
|
56
58
|
end
|
57
59
|
|
58
60
|
it "updates logging status" do
|
@@ -70,19 +72,19 @@ describe Imap::Backup::Configuration::Setup do
|
|
70
72
|
|
71
73
|
context "normal accounts" do
|
72
74
|
it "are listed" do
|
73
|
-
expect(
|
75
|
+
expect(output.string).to match(/account@example.com/)
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
77
79
|
context "modified accounts" do
|
78
80
|
it "are flagged" do
|
79
|
-
expect(
|
81
|
+
expect(output.string).to match(/modified@example.com \*/)
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
83
85
|
context "deleted accounts" do
|
84
86
|
it "are hidden" do
|
85
|
-
expect(
|
87
|
+
expect(output.string).to_not match(/delete@example.com/)
|
86
88
|
end
|
87
89
|
end
|
88
90
|
end
|
@@ -96,10 +98,12 @@ describe Imap::Backup::Configuration::Setup do
|
|
96
98
|
folders: []
|
97
99
|
}
|
98
100
|
end
|
99
|
-
let(:account)
|
101
|
+
let(:account) do
|
102
|
+
instance_double(Imap::Backup::Configuration::Account, run: nil)
|
103
|
+
end
|
100
104
|
|
101
105
|
before do
|
102
|
-
allow(
|
106
|
+
allow(input).to receive(:gets).and_return("add\n", "exit\n")
|
103
107
|
allow(Imap::Backup::Configuration::Asker).to receive(:email).
|
104
108
|
with(no_args).and_return("new@example.com")
|
105
109
|
allow(Imap::Backup::Configuration::Account).to receive(:new).
|
@@ -120,12 +124,12 @@ describe Imap::Backup::Configuration::Setup do
|
|
120
124
|
context "logging" do
|
121
125
|
context "when debug logging is disabled" do
|
122
126
|
before do
|
123
|
-
allow(
|
127
|
+
allow(input).to receive(:gets).and_return("start\n", "exit\n")
|
124
128
|
subject.run
|
125
129
|
end
|
126
130
|
|
127
131
|
it "shows a menu item" do
|
128
|
-
expect(
|
132
|
+
expect(output.string).to include("start logging")
|
129
133
|
end
|
130
134
|
|
131
135
|
context "when selected" do
|
@@ -143,17 +147,17 @@ describe Imap::Backup::Configuration::Setup do
|
|
143
147
|
let(:debug) { true }
|
144
148
|
|
145
149
|
before do
|
146
|
-
allow(
|
150
|
+
allow(input).to receive(:gets).and_return("stop\n", "exit\n")
|
147
151
|
subject.run
|
148
152
|
end
|
149
153
|
|
150
154
|
it "shows a menu item" do
|
151
|
-
expect(
|
155
|
+
expect(output.string).to include("stop logging")
|
152
156
|
end
|
153
157
|
|
154
158
|
context "when selected" do
|
155
159
|
before do
|
156
|
-
allow(
|
160
|
+
allow(input).to receive(:gets).and_return("stop\n", "exit\n")
|
157
161
|
end
|
158
162
|
|
159
163
|
it "unsets the debug flag" do
|
@@ -169,7 +173,7 @@ describe Imap::Backup::Configuration::Setup do
|
|
169
173
|
|
170
174
|
context "when 'save' is selected" do
|
171
175
|
before do
|
172
|
-
allow(
|
176
|
+
allow(input).to receive(:gets).and_return("save\n")
|
173
177
|
subject.run
|
174
178
|
end
|
175
179
|
|
@@ -184,7 +188,7 @@ describe Imap::Backup::Configuration::Setup do
|
|
184
188
|
|
185
189
|
context "when 'exit without saving' is selected" do
|
186
190
|
before do
|
187
|
-
allow(
|
191
|
+
allow(input).to receive(:gets).and_return("exit\n")
|
188
192
|
|
189
193
|
subject.run
|
190
194
|
end
|
@@ -209,3 +213,5 @@ describe Imap::Backup::Configuration::Setup do
|
|
209
213
|
end
|
210
214
|
end
|
211
215
|
end
|
216
|
+
|
217
|
+
# rubocop:enable RSpec/NestedGroups
|
@@ -1,6 +1,7 @@
|
|
1
|
-
require "spec_helper"
|
2
1
|
require "json"
|
3
2
|
|
3
|
+
# rubocop:disable RSpec/PredicateMatcher
|
4
|
+
|
4
5
|
describe Imap::Backup::Configuration::Store do
|
5
6
|
let(:directory) { "/base/path" }
|
6
7
|
let(:file_path) { File.join(directory, "/config.json") }
|
@@ -130,8 +131,10 @@ describe Imap::Backup::Configuration::Store do
|
|
130
131
|
end
|
131
132
|
|
132
133
|
describe "#save" do
|
134
|
+
subject { described_class.new }
|
135
|
+
|
133
136
|
let(:directory_exists) { false }
|
134
|
-
let(:file) {
|
137
|
+
let(:file) { instance_double(File, write: nil) }
|
135
138
|
|
136
139
|
before do
|
137
140
|
allow(FileUtils).to receive(:mkdir)
|
@@ -140,8 +143,6 @@ describe Imap::Backup::Configuration::Store do
|
|
140
143
|
allow(JSON).to receive(:pretty_generate).and_return("JSON output")
|
141
144
|
end
|
142
145
|
|
143
|
-
subject { described_class.new }
|
144
|
-
|
145
146
|
it "creates the config directory" do
|
146
147
|
subject.save
|
147
148
|
|
@@ -219,3 +220,5 @@ describe Imap::Backup::Configuration::Store do
|
|
219
220
|
end
|
220
221
|
end
|
221
222
|
end
|
223
|
+
|
224
|
+
# rubocop:enable RSpec/PredicateMatcher
|
@@ -1,17 +1,21 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
1
|
describe Imap::Backup::Downloader do
|
4
2
|
describe "#run" do
|
3
|
+
subject { described_class.new(folder, serializer) }
|
4
|
+
|
5
5
|
let(:message) { {"RFC822" => "blah"} }
|
6
6
|
let(:folder) do
|
7
|
-
|
7
|
+
instance_double(
|
8
|
+
Imap::Backup::Account::Folder,
|
9
|
+
fetch: message,
|
10
|
+
name: "folder"
|
11
|
+
)
|
12
|
+
end
|
13
|
+
let(:folder_uids) { %w(111 222 333) }
|
14
|
+
let(:serializer) do
|
15
|
+
instance_double(Imap::Backup::Serializer::Mbox, save: nil)
|
8
16
|
end
|
9
|
-
let(:folder_uids) { ["111", "222", "333"] }
|
10
|
-
let(:serializer) { double("Imap::Backup::Serializer", save: nil) }
|
11
17
|
let(:serializer_uids) { ["222"] }
|
12
18
|
|
13
|
-
subject { described_class.new(folder, serializer) }
|
14
|
-
|
15
19
|
before do
|
16
20
|
allow(folder).to receive(:uids).and_return(folder_uids)
|
17
21
|
allow(serializer).to receive(:uids).and_return(serializer_uids)
|