imap-backup 2.0.0 → 2.2.2
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 +0 -1
- data/.rspec-all +2 -0
- data/.rubocop.yml +15 -2
- data/.rubocop_todo.yml +58 -0
- data/.travis.yml +15 -2
- data/README.md +14 -22
- data/Rakefile +6 -3
- data/bin/imap-backup +5 -11
- data/imap-backup.gemspec +10 -6
- data/lib/email/mboxrd/message.rb +16 -16
- data/lib/imap/backup/account/connection.rb +38 -22
- data/lib/imap/backup/account/folder.rb +23 -7
- data/lib/imap/backup/configuration/account.rb +25 -21
- data/lib/imap/backup/configuration/asker.rb +3 -2
- 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 +44 -25
- data/lib/imap/backup/serializer/mbox_enumerator.rb +31 -0
- data/lib/imap/backup/serializer/mbox_store.rb +35 -32
- data/lib/imap/backup/uploader.rb +11 -2
- data/lib/imap/backup/utils.rb +11 -9
- data/lib/imap/backup/version.rb +2 -2
- data/spec/features/backup_spec.rb +6 -5
- data/spec/features/helper.rb +1 -1
- data/spec/features/restore_spec.rb +75 -27
- data/spec/features/support/backup_directory.rb +7 -7
- data/spec/features/support/email_server.rb +15 -11
- data/spec/features/support/shared/connection_context.rb +2 -2
- data/spec/features/support/shared/message_fixtures.rb +8 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/fixtures.rb +2 -2
- data/spec/support/higline_test_helpers.rb +1 -1
- data/spec/unit/email/mboxrd/message_spec.rb +73 -53
- data/spec/unit/email/provider_spec.rb +3 -5
- data/spec/unit/imap/backup/account/connection_spec.rb +82 -59
- data/spec/unit/imap/backup/account/folder_spec.rb +75 -37
- data/spec/unit/imap/backup/configuration/account_spec.rb +95 -61
- data/spec/unit/imap/backup/configuration/asker_spec.rb +43 -45
- data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +21 -22
- data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +66 -33
- data/spec/unit/imap/backup/configuration/list_spec.rb +32 -11
- data/spec/unit/imap/backup/configuration/setup_spec.rb +97 -56
- data/spec/unit/imap/backup/configuration/store_spec.rb +30 -25
- data/spec/unit/imap/backup/downloader_spec.rb +28 -26
- data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +45 -0
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +109 -51
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +232 -20
- data/spec/unit/imap/backup/uploader_spec.rb +23 -9
- data/spec/unit/imap/backup/utils_spec.rb +14 -15
- data/spec/unit/imap/backup_spec.rb +28 -0
- metadata +13 -7
@@ -0,0 +1,45 @@
|
|
1
|
+
require "imap/backup/serializer/mbox_enumerator"
|
2
|
+
|
3
|
+
describe Imap::Backup::Serializer::MboxEnumerator do
|
4
|
+
subject { described_class.new(mbox_pathname) }
|
5
|
+
|
6
|
+
let(:mbox_pathname) { "/mbox/pathname" }
|
7
|
+
let(:mbox_file) { instance_double(File) }
|
8
|
+
let(:lines) { message1 + message2 + [nil] }
|
9
|
+
let(:message1) do
|
10
|
+
[
|
11
|
+
"From Frida\r\n",
|
12
|
+
"Hello\r\n"
|
13
|
+
]
|
14
|
+
end
|
15
|
+
let(:message2) do
|
16
|
+
[
|
17
|
+
"From John\r\n",
|
18
|
+
"Hi\r\n"
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
allow(File).to receive(:open).and_call_original
|
24
|
+
allow(File).to receive(:open).with(mbox_pathname, "rb").and_yield(mbox_file)
|
25
|
+
allow(mbox_file).to receive(:gets).and_return(*lines)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#each" do
|
29
|
+
it "reads files as binary" do
|
30
|
+
expect(File).to receive(:open).with(mbox_pathname, "rb")
|
31
|
+
subject.each {}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "yields messages" do
|
35
|
+
expect { |b| subject.each(&b) }.
|
36
|
+
to yield_successive_args(message1.join, message2.join)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "without a block" do
|
40
|
+
it "returns an Enumerator" do
|
41
|
+
expect(subject.each).to be_a(Enumerator)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
describe Imap::Backup::Serializer::Mbox do
|
2
|
+
subject { described_class.new(base_path, imap_folder) }
|
3
|
+
|
2
4
|
let(:base_path) { "/base/path" }
|
3
5
|
let(:store) do
|
4
6
|
instance_double(
|
@@ -7,7 +9,8 @@ describe Imap::Backup::Serializer::Mbox do
|
|
7
9
|
rename: nil,
|
8
10
|
uids: nil,
|
9
11
|
uid_validity: existing_uid_validity,
|
10
|
-
"uid_validity=": nil
|
12
|
+
"uid_validity=": nil,
|
13
|
+
update_uid: nil
|
11
14
|
)
|
12
15
|
end
|
13
16
|
let(:imap_folder) { "folder" }
|
@@ -20,103 +23,91 @@ describe Imap::Backup::Serializer::Mbox do
|
|
20
23
|
allow(Imap::Backup::Utils).to receive(:mode) { permissions }
|
21
24
|
allow(Imap::Backup::Utils).to receive(:check_permissions) { true }
|
22
25
|
allow(File).to receive(:directory?) { dir_exists }
|
23
|
-
end
|
24
|
-
|
25
|
-
subject { described_class.new(base_path, imap_folder) }
|
26
|
-
|
27
|
-
before do
|
28
26
|
allow(FileUtils).to receive(:chmod)
|
29
27
|
allow(Imap::Backup::Serializer::MboxStore).to receive(:new) { store }
|
30
28
|
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
context "when the IMAP folder has multiple elements" do
|
30
|
+
describe "folder path" do
|
31
|
+
context "when it has multiple elements" do
|
36
32
|
let(:imap_folder) { "folder/path" }
|
37
33
|
|
38
34
|
context "when the containing directory is missing" do
|
39
35
|
let(:dir_exists) { false }
|
40
36
|
|
41
37
|
it "is created" do
|
42
|
-
expect(Imap::Backup::Utils).to
|
38
|
+
expect(Imap::Backup::Utils).to receive(:make_folder).
|
43
39
|
with(base_path, File.dirname(imap_folder), 0o700)
|
40
|
+
|
41
|
+
subject.uids
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
48
|
-
context "when
|
46
|
+
context "when permissions are incorrect" do
|
49
47
|
let(:permissions) { 0o777 }
|
50
48
|
|
51
49
|
it "corrects them" do
|
52
50
|
path = File.expand_path(File.join(base_path, File.dirname(imap_folder)))
|
53
|
-
expect(FileUtils).to
|
51
|
+
expect(FileUtils).to receive(:chmod).with(0o700, path)
|
52
|
+
|
53
|
+
subject.uids
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
context "when
|
57
|
+
context "when permissons are correct" do
|
58
58
|
it "does nothing" do
|
59
|
-
expect(FileUtils).to_not
|
59
|
+
expect(FileUtils).to_not receive(:chmod)
|
60
|
+
|
61
|
+
subject.uids
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
context "when
|
65
|
+
context "when it exists" do
|
64
66
|
it "is not created" do
|
65
|
-
expect(Imap::Backup::Utils).to_not
|
67
|
+
expect(Imap::Backup::Utils).to_not receive(:make_folder).
|
66
68
|
with(base_path, File.dirname(imap_folder), 0o700)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "#uids" do
|
72
|
-
it "calls the store" do
|
73
|
-
subject.uids
|
74
|
-
|
75
|
-
expect(store).to have_received(:uids)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
context "#save" do
|
80
|
-
it "calls the store" do
|
81
|
-
subject.save("foo", "bar")
|
82
69
|
|
83
|
-
|
70
|
+
subject.uids
|
71
|
+
end
|
84
72
|
end
|
85
73
|
end
|
86
74
|
|
87
|
-
|
88
|
-
let(:result) { subject.set_uid_validity("aaa") }
|
89
|
-
|
75
|
+
describe "#apply_uid_validity" do
|
90
76
|
context "when the existing uid validity is unset" do
|
91
|
-
let!(:result) { super() }
|
92
|
-
|
93
77
|
it "sets uid validity" do
|
94
|
-
expect(store).to
|
78
|
+
expect(store).to receive(:uid_validity=).with("aaa")
|
79
|
+
|
80
|
+
subject.apply_uid_validity("aaa")
|
95
81
|
end
|
96
82
|
|
97
83
|
it "does not rename the store" do
|
98
|
-
expect(store).to_not
|
84
|
+
expect(store).to_not receive(:rename)
|
85
|
+
|
86
|
+
subject.apply_uid_validity("aaa")
|
99
87
|
end
|
100
88
|
|
101
89
|
it "returns nil" do
|
102
|
-
expect(
|
90
|
+
expect(subject.apply_uid_validity("aaa")).to be_nil
|
103
91
|
end
|
104
92
|
end
|
105
93
|
|
106
94
|
context "when the uid validity is unchanged" do
|
107
|
-
let!(:result) { super() }
|
108
95
|
let(:existing_uid_validity) { "aaa" }
|
109
96
|
|
110
97
|
it "does not set uid validity" do
|
111
|
-
expect(store).to_not
|
98
|
+
expect(store).to_not receive(:uid_validity=)
|
99
|
+
|
100
|
+
subject.apply_uid_validity("aaa")
|
112
101
|
end
|
113
102
|
|
114
103
|
it "does not rename the store" do
|
115
|
-
expect(store).to_not
|
104
|
+
expect(store).to_not receive(:rename)
|
105
|
+
|
106
|
+
subject.apply_uid_validity("aaa")
|
116
107
|
end
|
117
108
|
|
118
109
|
it "returns nil" do
|
119
|
-
expect(
|
110
|
+
expect(subject.apply_uid_validity("aaa")).to be_nil
|
120
111
|
end
|
121
112
|
end
|
122
113
|
|
@@ -131,20 +122,23 @@ describe Imap::Backup::Serializer::Mbox do
|
|
131
122
|
allow(Imap::Backup::Serializer::MboxStore).
|
132
123
|
to receive(:new).with(anything, /bbb/) { existing_store }
|
133
124
|
allow(existing_store).to receive(:exist?).and_return(exists, false)
|
134
|
-
result
|
135
125
|
end
|
136
126
|
|
137
127
|
it "sets uid validity" do
|
138
|
-
expect(store).to
|
128
|
+
expect(store).to receive(:uid_validity=).with("aaa")
|
129
|
+
|
130
|
+
subject.apply_uid_validity("aaa")
|
139
131
|
end
|
140
132
|
|
141
133
|
context "when adding the uid validity does not cause a name clash" do
|
142
134
|
it "renames the store, adding the existing uid validity" do
|
143
|
-
expect(store).to
|
135
|
+
expect(store).to receive(:rename).with("folder.bbb")
|
136
|
+
|
137
|
+
subject.apply_uid_validity("aaa")
|
144
138
|
end
|
145
139
|
|
146
140
|
it "returns the new name" do
|
147
|
-
expect(
|
141
|
+
expect(subject.apply_uid_validity("aaa")).to eq("folder.bbb")
|
148
142
|
end
|
149
143
|
end
|
150
144
|
|
@@ -152,13 +146,77 @@ describe Imap::Backup::Serializer::Mbox do
|
|
152
146
|
let(:exists) { true }
|
153
147
|
|
154
148
|
it "renames the store, adding the existing uid validity and a digit" do
|
155
|
-
expect(store).to
|
149
|
+
expect(store).to receive(:rename).with("folder.bbb.1")
|
150
|
+
|
151
|
+
subject.apply_uid_validity("aaa")
|
156
152
|
end
|
157
153
|
|
158
154
|
it "returns the new name" do
|
159
|
-
expect(
|
155
|
+
expect(subject.apply_uid_validity("aaa")).to eq("folder.bbb.1")
|
160
156
|
end
|
161
157
|
end
|
162
158
|
end
|
163
159
|
end
|
160
|
+
|
161
|
+
describe "#force_uid_validity" do
|
162
|
+
it "sets the uid_validity" do
|
163
|
+
expect(store).to receive(:uid_validity=).with("66")
|
164
|
+
|
165
|
+
subject.force_uid_validity("66")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#uids" do
|
170
|
+
it "calls the store" do
|
171
|
+
expect(store).to receive(:uids)
|
172
|
+
|
173
|
+
subject.uids
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#load" do
|
178
|
+
before { allow(store).to receive(:load).with("66") { "xxx" } }
|
179
|
+
|
180
|
+
it "returns the value loaded by the store" do
|
181
|
+
expect(subject.load("66")).to eq("xxx")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "#each_message" do
|
186
|
+
it "calls the store" do
|
187
|
+
expect(store).to receive(:each_message).with([1])
|
188
|
+
|
189
|
+
subject.each_message([1])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "#save" do
|
194
|
+
it "calls the store" do
|
195
|
+
expect(store).to receive(:add).with("foo", "bar")
|
196
|
+
|
197
|
+
subject.save("foo", "bar")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "#rename" do
|
202
|
+
it "calls the store" do
|
203
|
+
expect(store).to receive(:rename).with("foo")
|
204
|
+
|
205
|
+
subject.rename("foo")
|
206
|
+
end
|
207
|
+
|
208
|
+
it "updates the folder name" do
|
209
|
+
subject.rename("foo")
|
210
|
+
|
211
|
+
expect(subject.folder).to eq("foo")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "#update_uid" do
|
216
|
+
it "calls the store" do
|
217
|
+
expect(store).to receive(:update_uid).with("foo", "bar")
|
218
|
+
|
219
|
+
subject.update_uid("foo", "bar")
|
220
|
+
end
|
221
|
+
end
|
164
222
|
end
|
@@ -1,23 +1,24 @@
|
|
1
1
|
describe Imap::Backup::Serializer::MboxStore do
|
2
|
+
subject { described_class.new(base_path, folder) }
|
3
|
+
|
2
4
|
let(:base_path) { "/base/path" }
|
3
5
|
let(:folder) { "the/folder" }
|
4
6
|
let(:folder_path) { File.join(base_path, folder) }
|
5
|
-
let(:imap_pathname) { folder_path
|
7
|
+
let(:imap_pathname) { "#{folder_path}.imap" }
|
6
8
|
let(:imap_exists) { true }
|
7
|
-
let(:imap_file) {
|
8
|
-
let(:mbox_pathname) { folder_path
|
9
|
+
let(:imap_file) { instance_double(File, write: nil, close: nil) }
|
10
|
+
let(:mbox_pathname) { "#{folder_path}.mbox" }
|
9
11
|
let(:mbox_exists) { true }
|
10
|
-
let(:mbox_file) {
|
12
|
+
let(:mbox_file) { instance_double(File, write: nil, close: nil) }
|
11
13
|
let(:uids) { [3, 2, 1] }
|
12
14
|
let(:imap_content) do
|
13
15
|
{
|
14
16
|
version: Imap::Backup::Serializer::MboxStore::CURRENT_VERSION,
|
15
|
-
uid_validity:
|
16
|
-
uids: uids
|
17
|
+
uid_validity: uid_validity,
|
18
|
+
uids: uids
|
17
19
|
}.to_json
|
18
20
|
end
|
19
|
-
|
20
|
-
subject { described_class.new(base_path, folder) }
|
21
|
+
let(:uid_validity) { 123 }
|
21
22
|
|
22
23
|
before do
|
23
24
|
allow(File).to receive(:exist?).and_call_original
|
@@ -40,9 +41,32 @@ describe Imap::Backup::Serializer::MboxStore do
|
|
40
41
|
allow(FileUtils).to receive(:chmod)
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
describe "#uid_validity=" do
|
45
|
+
let(:new_uid_validity) { "13" }
|
46
|
+
let(:updated_imap_content) do
|
47
|
+
{
|
48
|
+
version: Imap::Backup::Serializer::MboxStore::CURRENT_VERSION,
|
49
|
+
uid_validity: new_uid_validity,
|
50
|
+
uids: uids
|
51
|
+
}.to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
it "sets uid_validity" do
|
55
|
+
subject.uid_validity = new_uid_validity
|
56
|
+
|
57
|
+
expect(subject.uid_validity).to eq(new_uid_validity)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "writes the imap file" do
|
61
|
+
expect(imap_file).to receive(:write).with(updated_imap_content)
|
62
|
+
|
63
|
+
subject.uid_validity = new_uid_validity
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#uids" do
|
68
|
+
it "returns the backed-up uids as integers" do
|
69
|
+
expect(subject.uids).to eq(uids.map(&:to_i))
|
46
70
|
end
|
47
71
|
|
48
72
|
context "when the imap file does not exist" do
|
@@ -53,6 +77,34 @@ describe Imap::Backup::Serializer::MboxStore do
|
|
53
77
|
end
|
54
78
|
end
|
55
79
|
|
80
|
+
context "when the imap file is malformed" do
|
81
|
+
before do
|
82
|
+
allow(JSON).to receive(:parse).and_raise(JSON::ParserError)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns an empty Array" do
|
86
|
+
expect(subject.uids).to eq([])
|
87
|
+
end
|
88
|
+
|
89
|
+
it "deletes the imap file" do
|
90
|
+
expect(File).to receive(:unlink).with(imap_pathname)
|
91
|
+
|
92
|
+
subject.uids
|
93
|
+
end
|
94
|
+
|
95
|
+
it "deletes the mbox file" do
|
96
|
+
expect(File).to receive(:unlink).with(mbox_pathname)
|
97
|
+
|
98
|
+
subject.uids
|
99
|
+
end
|
100
|
+
|
101
|
+
it "writes a blank mbox file" do
|
102
|
+
expect(mbox_file).to receive(:write).with("")
|
103
|
+
|
104
|
+
subject.uids
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
56
108
|
context "when the mbox does not exist" do
|
57
109
|
let(:mbox_exists) { false }
|
58
110
|
|
@@ -62,7 +114,7 @@ describe Imap::Backup::Serializer::MboxStore do
|
|
62
114
|
end
|
63
115
|
end
|
64
116
|
|
65
|
-
|
117
|
+
describe "#add" do
|
66
118
|
let(:mbox_formatted_message) { "message in mbox format" }
|
67
119
|
let(:message_uid) { "999" }
|
68
120
|
let(:message) do
|
@@ -74,27 +126,36 @@ describe Imap::Backup::Serializer::MboxStore do
|
|
74
126
|
let(:updated_imap_content) do
|
75
127
|
{
|
76
128
|
version: Imap::Backup::Serializer::MboxStore::CURRENT_VERSION,
|
77
|
-
uid_validity:
|
78
|
-
uids:
|
129
|
+
uid_validity: uid_validity,
|
130
|
+
uids: uids + [999]
|
79
131
|
}.to_json
|
80
132
|
end
|
81
133
|
|
82
134
|
before do
|
83
|
-
allow(Email::Mboxrd::Message).to receive(:new)
|
135
|
+
allow(Email::Mboxrd::Message).to receive(:new) { message }
|
84
136
|
allow(File).to receive(:open).with(mbox_pathname, "ab") { mbox_file }
|
85
|
-
subject.uid_validity = 123
|
86
137
|
end
|
87
138
|
|
88
139
|
it "saves the message to the mbox" do
|
89
|
-
|
140
|
+
expect(mbox_file).to receive(:write).with(mbox_formatted_message)
|
90
141
|
|
91
|
-
|
142
|
+
subject.add(message_uid, "The\nemail\n")
|
92
143
|
end
|
93
144
|
|
94
145
|
it "saves the uid to the imap file" do
|
146
|
+
expect(imap_file).to receive(:write).with(updated_imap_content)
|
147
|
+
|
95
148
|
subject.add(message_uid, "The\nemail\n")
|
149
|
+
end
|
150
|
+
|
151
|
+
context "when the message is already downloaded" do
|
152
|
+
let(:uids) { [999] }
|
96
153
|
|
97
|
-
|
154
|
+
it "skips the message" do
|
155
|
+
expect(mbox_file).to_not receive(:write)
|
156
|
+
|
157
|
+
subject.add(message_uid, "The\nemail\n")
|
158
|
+
end
|
98
159
|
end
|
99
160
|
|
100
161
|
context "when the message causes parsing errors" do
|
@@ -103,8 +164,9 @@ describe Imap::Backup::Serializer::MboxStore do
|
|
103
164
|
end
|
104
165
|
|
105
166
|
it "skips the message" do
|
167
|
+
expect(mbox_file).to_not receive(:write)
|
168
|
+
|
106
169
|
subject.add(message_uid, "The\nemail\n")
|
107
|
-
expect(mbox_file).to_not have_received(:write)
|
108
170
|
end
|
109
171
|
|
110
172
|
it "does not fail" do
|
@@ -114,4 +176,154 @@ describe Imap::Backup::Serializer::MboxStore do
|
|
114
176
|
end
|
115
177
|
end
|
116
178
|
end
|
179
|
+
|
180
|
+
describe "#load" do
|
181
|
+
let(:uid) { "1" }
|
182
|
+
let(:enumerator) do
|
183
|
+
instance_double(Imap::Backup::Serializer::MboxEnumerator)
|
184
|
+
end
|
185
|
+
let(:enumeration) { instance_double(Enumerator) }
|
186
|
+
|
187
|
+
before do
|
188
|
+
allow(Imap::Backup::Serializer::MboxEnumerator).
|
189
|
+
to receive(:new) { enumerator }
|
190
|
+
allow(enumerator).to receive(:each) { enumeration }
|
191
|
+
allow(enumeration).
|
192
|
+
to receive(:with_index).
|
193
|
+
and_yield("", 0).
|
194
|
+
and_yield("", 1).
|
195
|
+
and_yield("ciao", 2)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "returns the message" do
|
199
|
+
expect(subject.load(uid).supplied_body).to eq("ciao")
|
200
|
+
end
|
201
|
+
|
202
|
+
context "when the UID is unknown" do
|
203
|
+
let(:uid) { "99" }
|
204
|
+
|
205
|
+
it "returns nil" do
|
206
|
+
expect(subject.load(uid)).to be_nil
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "#each_message" do
|
212
|
+
let(:enumerator) do
|
213
|
+
instance_double(Imap::Backup::Serializer::MboxEnumerator)
|
214
|
+
end
|
215
|
+
let(:enumeration) { instance_double(Enumerator) }
|
216
|
+
|
217
|
+
before do
|
218
|
+
allow(Imap::Backup::Serializer::MboxEnumerator).
|
219
|
+
to receive(:new) { enumerator }
|
220
|
+
allow(enumerator).to receive(:each) { enumeration }
|
221
|
+
allow(enumeration).
|
222
|
+
to receive(:with_index).
|
223
|
+
and_yield("", 0).
|
224
|
+
and_yield("", 1).
|
225
|
+
and_yield("ciao", 2)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "yields messages" do
|
229
|
+
expect { |b| subject.each_message([1], &b) }.
|
230
|
+
to yield_successive_args([1, instance_of(Email::Mboxrd::Message)])
|
231
|
+
end
|
232
|
+
|
233
|
+
it "yields the requested message uid" do
|
234
|
+
subject.each_message([1]) do |uid, _message|
|
235
|
+
expect(uid).to eq(1)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
it "yields the requested message" do
|
240
|
+
subject.each_message([1]) do |_uid, message|
|
241
|
+
expect(message.supplied_body).to eq("ciao")
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context "without a block" do
|
246
|
+
it "returns an Enumerator" do
|
247
|
+
expect(subject.each_message([1])).to be_a(Enumerator)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "#update_uid" do
|
253
|
+
let(:old_uid) { "2" }
|
254
|
+
let(:updated_imap_content) do
|
255
|
+
{
|
256
|
+
version: Imap::Backup::Serializer::MboxStore::CURRENT_VERSION,
|
257
|
+
uid_validity: uid_validity,
|
258
|
+
uids: [3, 999, 1]
|
259
|
+
}.to_json
|
260
|
+
end
|
261
|
+
|
262
|
+
it "updates the stored UID" do
|
263
|
+
expect(imap_file).to receive(:write).with(updated_imap_content)
|
264
|
+
|
265
|
+
subject.update_uid(old_uid, "999")
|
266
|
+
end
|
267
|
+
|
268
|
+
context "when the UID is unknown" do
|
269
|
+
let(:old_uid) { "42" }
|
270
|
+
|
271
|
+
it "does nothing" do
|
272
|
+
expect(imap_file).to_not receive(:write)
|
273
|
+
|
274
|
+
subject.update_uid(old_uid, "999")
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe "#reset" do
|
280
|
+
it "deletes the imap file" do
|
281
|
+
expect(File).to receive(:unlink).with(imap_pathname)
|
282
|
+
|
283
|
+
subject.reset
|
284
|
+
end
|
285
|
+
|
286
|
+
it "deletes the mbox file" do
|
287
|
+
expect(File).to receive(:unlink).with(mbox_pathname)
|
288
|
+
|
289
|
+
subject.reset
|
290
|
+
end
|
291
|
+
|
292
|
+
it "writes a blank mbox file" do
|
293
|
+
expect(mbox_file).to receive(:write).with("")
|
294
|
+
|
295
|
+
subject.reset
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
describe "#rename" do
|
300
|
+
let(:new_name) { "new_name" }
|
301
|
+
let(:new_folder_path) { File.join(base_path, new_name) }
|
302
|
+
let(:new_imap_name) { "#{new_folder_path}.imap" }
|
303
|
+
let(:new_mbox_name) { "#{new_folder_path}.mbox" }
|
304
|
+
|
305
|
+
before do
|
306
|
+
allow(File).to receive(:rename).and_call_original
|
307
|
+
allow(File).to receive(:rename).with(imap_pathname, new_imap_name)
|
308
|
+
allow(File).to receive(:rename).with(mbox_pathname, new_mbox_name)
|
309
|
+
end
|
310
|
+
|
311
|
+
it "renames the imap file" do
|
312
|
+
expect(File).to receive(:rename).with(imap_pathname, new_imap_name)
|
313
|
+
|
314
|
+
subject.rename(new_name)
|
315
|
+
end
|
316
|
+
|
317
|
+
it "renames the mbox file" do
|
318
|
+
expect(File).to receive(:rename).with(mbox_pathname, new_mbox_name)
|
319
|
+
|
320
|
+
subject.rename(new_name)
|
321
|
+
end
|
322
|
+
|
323
|
+
it "updates the folder name" do
|
324
|
+
subject.rename(new_name)
|
325
|
+
|
326
|
+
expect(subject.folder).to eq(new_name)
|
327
|
+
end
|
328
|
+
end
|
117
329
|
end
|