imap-backup 2.1.1 → 3.0.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/.rubocop.yml +5 -4
- data/.rubocop_todo.yml +29 -11
- data/.travis.yml +1 -1
- data/README.md +10 -13
- data/bin/imap-backup +5 -2
- data/docs/01-credentials-screen.png +0 -0
- data/docs/02-new-project.png +0 -0
- data/docs/03-initial-credentials-for-project.png +0 -0
- data/docs/04-credential-type-selection.png +0 -0
- data/docs/05-cant-create-without-consent-setup.png +0 -0
- data/docs/06-user-type-selection.png +0 -0
- data/docs/07-consent-screen-form.png +0 -0
- data/docs/08-app-scopes.png +0 -0
- data/docs/09-scope-selection.png +0 -0
- data/docs/10-updated-app-scopes.png +0 -0
- data/docs/11-test-users.png +0 -0
- data/docs/12-add-users.png +0 -0
- data/docs/13-create-oauth-client.png +0 -0
- data/docs/14-application-details.png +0 -0
- data/docs/16-initial-menu.png +0 -0
- data/docs/17-inputting-the-email-address.png +0 -0
- data/docs/18-choose-password.png +0 -0
- data/docs/19-supply-client-info.png +0 -0
- data/docs/20-choose-gmail-account.png +0 -0
- data/docs/21-accept-warnings.png +0 -0
- data/docs/22-grant-access.png +0 -0
- data/docs/24-confirm-choices.png +0 -0
- data/docs/25-success-code.png +0 -0
- data/docs/26-type-code-into-imap-backup.png +0 -0
- data/docs/27-success.png +0 -0
- data/docs/setting-up-gmail.md +166 -0
- data/imap-backup.gemspec +3 -9
- data/lib/email/mboxrd/message.rb +4 -3
- data/lib/email/provider.rb +3 -1
- data/lib/gmail/authenticator.rb +160 -0
- data/lib/google/auth/stores/in_memory_token_store.rb +9 -0
- data/lib/imap/backup.rb +2 -1
- data/lib/imap/backup/account/connection.rb +59 -34
- data/lib/imap/backup/account/folder.rb +10 -1
- data/lib/imap/backup/configuration/account.rb +9 -1
- data/lib/imap/backup/configuration/gmail_oauth2.rb +82 -0
- data/lib/imap/backup/configuration/setup.rb +4 -1
- data/lib/imap/backup/serializer/mbox.rb +4 -0
- data/lib/imap/backup/serializer/mbox_enumerator.rb +1 -1
- data/lib/imap/backup/serializer/mbox_store.rb +20 -4
- data/lib/imap/backup/uploader.rb +10 -2
- data/lib/imap/backup/version.rb +5 -4
- data/spec/features/backup_spec.rb +3 -3
- data/spec/features/helper.rb +1 -1
- data/spec/features/restore_spec.rb +75 -27
- data/spec/features/support/backup_directory.rb +2 -2
- data/spec/features/support/email_server.rb +1 -3
- data/spec/features/support/shared/message_fixtures.rb +8 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/fixtures.rb +1 -1
- data/spec/unit/email/mboxrd/message_spec.rb +2 -8
- data/spec/unit/email/provider_spec.rb +2 -2
- data/spec/unit/gmail/authenticator_spec.rb +138 -0
- data/spec/unit/google/auth/stores/in_memory_token_store_spec.rb +15 -0
- data/spec/unit/imap/backup/account/connection_spec.rb +157 -79
- data/spec/unit/imap/backup/account/folder_spec.rb +30 -20
- data/spec/unit/imap/backup/configuration/account_spec.rb +65 -46
- data/spec/unit/imap/backup/configuration/asker_spec.rb +20 -17
- data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +6 -10
- data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +16 -10
- data/spec/unit/imap/backup/configuration/gmail_oauth2_spec.rb +84 -0
- data/spec/unit/imap/backup/configuration/list_spec.rb +6 -3
- data/spec/unit/imap/backup/configuration/setup_spec.rb +89 -54
- data/spec/unit/imap/backup/configuration/store_spec.rb +18 -16
- data/spec/unit/imap/backup/downloader_spec.rb +14 -14
- data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +6 -1
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +62 -40
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +94 -35
- data/spec/unit/imap/backup/uploader_spec.rb +23 -7
- data/spec/unit/imap/backup/utils_spec.rb +10 -9
- metadata +68 -9
@@ -0,0 +1,15 @@
|
|
1
|
+
require "google/auth/stores/in_memory_token_store"
|
2
|
+
|
3
|
+
describe Google::Auth::Stores::InMemoryTokenStore do
|
4
|
+
KEY = "key".freeze
|
5
|
+
VALUE = "value".freeze
|
6
|
+
|
7
|
+
subject { described_class.new }
|
8
|
+
|
9
|
+
describe "#load" do
|
10
|
+
it "returns an item's value" do
|
11
|
+
subject[KEY] = VALUE
|
12
|
+
expect(subject.load(KEY)).to eq(VALUE)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,58 +1,57 @@
|
|
1
|
-
|
2
|
-
def self.backup_folder
|
3
|
-
"backup_folder"
|
4
|
-
end
|
1
|
+
require "ostruct"
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
describe Imap::Backup::Account::Connection do
|
4
|
+
BACKUP_FOLDER = "backup_folder".freeze
|
5
|
+
FOLDER_CONFIG = {name: BACKUP_FOLDER}.freeze
|
6
|
+
FOLDER_NAME = "my_folder".freeze
|
7
|
+
GMAIL_IMAP_SERVER = "imap.gmail.com".freeze
|
8
|
+
LOCAL_PATH = "local_path".freeze
|
9
|
+
LOCAL_UID = "local_uid".freeze
|
10
|
+
PASSWORD = "secret".freeze
|
11
|
+
ROOT_NAME = "foo".freeze
|
12
|
+
SERVER = "imap.example.com".freeze
|
13
|
+
USERNAME = "username@example.com".freeze
|
9
14
|
|
10
15
|
subject { described_class.new(options) }
|
11
16
|
|
12
17
|
let(:imap) do
|
13
|
-
instance_double(Net::IMAP, login: nil, disconnect: nil)
|
18
|
+
instance_double(Net::IMAP, authenticate: nil, login: nil, disconnect: nil)
|
14
19
|
end
|
15
20
|
let(:imap_folders) { [] }
|
16
21
|
let(:options) do
|
17
22
|
{
|
18
|
-
username:
|
19
|
-
password:
|
20
|
-
local_path:
|
21
|
-
folders: backup_folders
|
23
|
+
username: USERNAME,
|
24
|
+
password: PASSWORD,
|
25
|
+
local_path: LOCAL_PATH,
|
26
|
+
folders: backup_folders,
|
27
|
+
server: server
|
22
28
|
}
|
23
29
|
end
|
24
|
-
let(:
|
25
|
-
let(:backup_folders) { [self.class.folder_config] }
|
26
|
-
let(:username) { "username@gmail.com" }
|
30
|
+
let(:backup_folders) { [FOLDER_CONFIG] }
|
27
31
|
let(:root_info) do
|
28
|
-
instance_double(Net::IMAP::MailboxList, name:
|
32
|
+
instance_double(Net::IMAP::MailboxList, name: ROOT_NAME)
|
29
33
|
end
|
30
|
-
let(:root_name) { "foo" }
|
31
34
|
let(:serializer) do
|
32
35
|
instance_double(
|
33
36
|
Imap::Backup::Serializer::Mbox,
|
34
37
|
folder: serialized_folder,
|
35
38
|
force_uid_validity: nil,
|
36
39
|
apply_uid_validity: new_uid_validity,
|
37
|
-
uids: [
|
40
|
+
uids: [LOCAL_UID]
|
38
41
|
)
|
39
42
|
end
|
40
43
|
let(:serialized_folder) { nil }
|
44
|
+
let(:server) { SERVER }
|
41
45
|
let(:new_uid_validity) { nil }
|
42
|
-
let(:local_uid) { "local_uid" }
|
43
46
|
|
44
47
|
before do
|
45
48
|
allow(Net::IMAP).to receive(:new) { imap }
|
46
49
|
allow(imap).to receive(:list).with("", "") { [root_info] }
|
47
|
-
allow(imap).to receive(:list).with(
|
50
|
+
allow(imap).to receive(:list).with(ROOT_NAME, "*") { imap_folders }
|
48
51
|
allow(Imap::Backup::Utils).to receive(:make_folder)
|
49
52
|
end
|
50
53
|
|
51
54
|
shared_examples "connects to IMAP" do
|
52
|
-
it "sets up the IMAP connection" do
|
53
|
-
expect(Net::IMAP).to have_received(:new)
|
54
|
-
end
|
55
|
-
|
56
55
|
it "logs in to the imap server" do
|
57
56
|
expect(imap).to have_received(:login)
|
58
57
|
end
|
@@ -60,18 +59,21 @@ describe Imap::Backup::Account::Connection do
|
|
60
59
|
|
61
60
|
describe "#initialize" do
|
62
61
|
[
|
63
|
-
[:username,
|
64
|
-
[:
|
65
|
-
[:
|
62
|
+
[:username, USERNAME],
|
63
|
+
[:password, PASSWORD],
|
64
|
+
[:local_path, LOCAL_PATH],
|
65
|
+
[:backup_folders, [FOLDER_CONFIG]],
|
66
|
+
[:server, SERVER]
|
66
67
|
].each do |attr, expected|
|
67
68
|
it "expects #{attr}" do
|
68
|
-
expect(subject.
|
69
|
+
expect(subject.public_send(attr)).to eq(expected)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
73
|
it "creates the path" do
|
74
|
+
expect(Imap::Backup::Utils).to receive(:make_folder)
|
75
|
+
|
73
76
|
subject.username
|
74
|
-
expect(Imap::Backup::Utils).to have_received(:make_folder)
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
@@ -82,6 +84,61 @@ describe Imap::Backup::Account::Connection do
|
|
82
84
|
expect(result).to eq(imap)
|
83
85
|
end
|
84
86
|
|
87
|
+
it "uses the password" do
|
88
|
+
expect(imap).to have_received(:login).with(USERNAME, PASSWORD)
|
89
|
+
end
|
90
|
+
|
91
|
+
context "with the GMail IMAP server" do
|
92
|
+
ACCESS_TOKEN = "access_token".freeze
|
93
|
+
|
94
|
+
let(:server) { GMAIL_IMAP_SERVER }
|
95
|
+
let(:refresh_token) { true }
|
96
|
+
let(:result) { nil }
|
97
|
+
let(:authenticator) do
|
98
|
+
instance_double(
|
99
|
+
Gmail::Authenticator,
|
100
|
+
credentials: credentials
|
101
|
+
)
|
102
|
+
end
|
103
|
+
let(:credentials) { OpenStruct.new(access_token: ACCESS_TOKEN) }
|
104
|
+
|
105
|
+
before do
|
106
|
+
allow(Gmail::Authenticator).
|
107
|
+
to receive(:refresh_token?) { refresh_token }
|
108
|
+
allow(Gmail::Authenticator).
|
109
|
+
to receive(:new).
|
110
|
+
with(email: USERNAME, token: PASSWORD) { authenticator }
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when the password is our copy of a GMail refresh token" do
|
114
|
+
it "uses the OAuth2 access_token to authenticate" do
|
115
|
+
subject.imap
|
116
|
+
|
117
|
+
expect(imap).to have_received(:authenticate).with(
|
118
|
+
"XOAUTH2", USERNAME, ACCESS_TOKEN
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when the refresh token is invalid" do
|
123
|
+
let(:credentials) { nil }
|
124
|
+
|
125
|
+
it "raises" do
|
126
|
+
expect { subject.imap }.to raise_error(String)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when the password is not our copy of a GMail refresh token" do
|
132
|
+
let(:refresh_token) { false }
|
133
|
+
|
134
|
+
it "uses the password" do
|
135
|
+
subject.imap
|
136
|
+
|
137
|
+
expect(imap).to have_received(:login).with(USERNAME, PASSWORD)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
85
142
|
include_examples "connects to IMAP"
|
86
143
|
end
|
87
144
|
|
@@ -102,16 +159,16 @@ describe Imap::Backup::Account::Connection do
|
|
102
159
|
let(:remote_uid) { "remote_uid" }
|
103
160
|
|
104
161
|
before do
|
105
|
-
allow(Imap::Backup::Account::Folder).to receive(:new)
|
162
|
+
allow(Imap::Backup::Account::Folder).to receive(:new) { folder }
|
106
163
|
allow(Imap::Backup::Serializer::Mbox).to receive(:new) { serializer }
|
107
164
|
end
|
108
165
|
|
109
166
|
it "returns the names of folders" do
|
110
|
-
expect(subject.status[0][:name]).to eq(
|
167
|
+
expect(subject.status[0][:name]).to eq(BACKUP_FOLDER)
|
111
168
|
end
|
112
169
|
|
113
170
|
it "returns local message uids" do
|
114
|
-
expect(subject.status[0][:local]).to eq([
|
171
|
+
expect(subject.status[0][:local]).to eq([LOCAL_UID])
|
115
172
|
end
|
116
173
|
|
117
174
|
it "retrieves the available uids" do
|
@@ -135,59 +192,59 @@ describe Imap::Backup::Account::Connection do
|
|
135
192
|
before do
|
136
193
|
allow(Imap::Backup::Downloader).
|
137
194
|
to receive(:new).with(folder, serializer) { downloader }
|
195
|
+
allow(Imap::Backup::Account::Folder).to receive(:new).
|
196
|
+
with(subject, BACKUP_FOLDER) { folder }
|
197
|
+
allow(Imap::Backup::Serializer::Mbox).to receive(:new).
|
198
|
+
with(LOCAL_PATH, BACKUP_FOLDER) { serializer }
|
138
199
|
end
|
139
200
|
|
140
201
|
context "with supplied backup_folders" do
|
141
|
-
before do
|
142
|
-
allow(Imap::Backup::Account::Folder).to receive(:new).
|
143
|
-
with(subject, self.class.backup_folder).and_return(folder)
|
144
|
-
allow(Imap::Backup::Serializer::Mbox).to receive(:new).
|
145
|
-
with(local_path, self.class.backup_folder).and_return(serializer)
|
146
|
-
subject.run_backup
|
147
|
-
end
|
148
|
-
|
149
202
|
it "runs the downloader" do
|
150
|
-
expect(downloader).to
|
203
|
+
expect(downloader).to receive(:run)
|
204
|
+
|
205
|
+
subject.run_backup
|
151
206
|
end
|
152
207
|
|
153
208
|
context "when a folder does not exist" do
|
154
209
|
let(:exists) { false }
|
155
210
|
|
156
211
|
it "does not run the downloader" do
|
157
|
-
expect(downloader).to_not
|
212
|
+
expect(downloader).to_not receive(:run)
|
213
|
+
|
214
|
+
subject.run_backup
|
158
215
|
end
|
159
216
|
end
|
160
217
|
end
|
161
218
|
|
162
219
|
context "without supplied backup_folders" do
|
163
220
|
let(:imap_folders) do
|
164
|
-
[instance_double(Net::IMAP::MailboxList, name:
|
221
|
+
[instance_double(Net::IMAP::MailboxList, name: ROOT_NAME)]
|
165
222
|
end
|
166
223
|
|
167
224
|
before do
|
168
225
|
allow(Imap::Backup::Account::Folder).to receive(:new).
|
169
|
-
with(subject,
|
226
|
+
with(subject, ROOT_NAME) { folder }
|
170
227
|
allow(Imap::Backup::Serializer::Mbox).to receive(:new).
|
171
|
-
with(
|
228
|
+
with(LOCAL_PATH, ROOT_NAME) { serializer }
|
172
229
|
end
|
173
230
|
|
174
231
|
context "when supplied backup_folders is nil" do
|
175
232
|
let(:backup_folders) { nil }
|
176
233
|
|
177
|
-
before { subject.run_backup }
|
178
|
-
|
179
234
|
it "runs the downloader for each folder" do
|
180
|
-
expect(downloader).to
|
235
|
+
expect(downloader).to receive(:run).exactly(:once)
|
236
|
+
|
237
|
+
subject.run_backup
|
181
238
|
end
|
182
239
|
end
|
183
240
|
|
184
241
|
context "when supplied backup_folders is an empty list" do
|
185
242
|
let(:backup_folders) { [] }
|
186
243
|
|
187
|
-
before { subject.run_backup }
|
188
|
-
|
189
244
|
it "runs the downloader for each folder" do
|
190
|
-
expect(downloader).to
|
245
|
+
expect(downloader).to receive(:run).exactly(:once)
|
246
|
+
|
247
|
+
subject.run_backup
|
191
248
|
end
|
192
249
|
end
|
193
250
|
|
@@ -200,6 +257,12 @@ describe Imap::Backup::Account::Connection do
|
|
200
257
|
end
|
201
258
|
end
|
202
259
|
end
|
260
|
+
|
261
|
+
context "when run" do
|
262
|
+
before { subject.run_backup }
|
263
|
+
|
264
|
+
include_examples "connects to IMAP"
|
265
|
+
end
|
203
266
|
end
|
204
267
|
|
205
268
|
describe "#restore" do
|
@@ -207,12 +270,12 @@ describe Imap::Backup::Account::Connection do
|
|
207
270
|
instance_double(
|
208
271
|
Imap::Backup::Account::Folder,
|
209
272
|
create: nil,
|
210
|
-
|
211
|
-
name:
|
273
|
+
uids: uids,
|
274
|
+
name: FOLDER_NAME,
|
212
275
|
uid_validity: uid_validity
|
213
276
|
)
|
214
277
|
end
|
215
|
-
let(:
|
278
|
+
let(:uids) { [99] }
|
216
279
|
let(:uid_validity) { 123 }
|
217
280
|
let(:serialized_folder) { "old name" }
|
218
281
|
let(:uploader) do
|
@@ -236,9 +299,9 @@ describe Imap::Backup::Account::Connection do
|
|
236
299
|
|
237
300
|
before do
|
238
301
|
allow(Imap::Backup::Account::Folder).to receive(:new).
|
239
|
-
with(subject,
|
302
|
+
with(subject, FOLDER_NAME) { folder }
|
240
303
|
allow(Imap::Backup::Serializer::Mbox).to receive(:new).
|
241
|
-
with(anything,
|
304
|
+
with(anything, FOLDER_NAME) { serializer }
|
242
305
|
allow(Imap::Backup::Account::Folder).to receive(:new).
|
243
306
|
with(subject, "new name") { updated_folder }
|
244
307
|
allow(Imap::Backup::Serializer::Mbox).to receive(:new).
|
@@ -248,75 +311,90 @@ describe Imap::Backup::Account::Connection do
|
|
248
311
|
allow(Imap::Backup::Uploader).to receive(:new).
|
249
312
|
with(updated_folder, updated_serializer) { updated_uploader }
|
250
313
|
allow(Pathname).to receive(:glob).
|
251
|
-
and_yield(Pathname.new(File.join(
|
252
|
-
subject.restore
|
314
|
+
and_yield(Pathname.new(File.join(LOCAL_PATH, "#{FOLDER_NAME}.imap")))
|
253
315
|
end
|
254
316
|
|
255
317
|
it "sets local uid validity" do
|
256
|
-
expect(serializer).
|
257
|
-
|
318
|
+
expect(serializer).to receive(:apply_uid_validity).with(uid_validity)
|
319
|
+
|
320
|
+
subject.restore
|
258
321
|
end
|
259
322
|
|
260
|
-
context "when folders exist" do
|
323
|
+
context "when folders exist with contents" do
|
261
324
|
context "when the local folder is renamed" do
|
262
325
|
let(:new_uid_validity) { "new name" }
|
263
326
|
|
264
327
|
it "creates the new folder" do
|
265
|
-
expect(updated_folder).to
|
328
|
+
expect(updated_folder).to receive(:create)
|
329
|
+
|
330
|
+
subject.restore
|
266
331
|
end
|
267
332
|
|
268
333
|
it "sets the renamed folder's uid validity" do
|
269
334
|
expect(updated_serializer).
|
270
|
-
to
|
335
|
+
to receive(:force_uid_validity).with("new uid validity")
|
336
|
+
|
337
|
+
subject.restore
|
271
338
|
end
|
272
339
|
|
273
340
|
it "creates the uploader with updated folder and serializer" do
|
274
|
-
expect(updated_uploader).to
|
341
|
+
expect(updated_uploader).to receive(:run)
|
342
|
+
|
343
|
+
subject.restore
|
275
344
|
end
|
276
345
|
end
|
277
346
|
|
278
347
|
context "when the local folder is not renamed" do
|
279
348
|
it "runs the uploader" do
|
280
|
-
expect(uploader).to
|
349
|
+
expect(uploader).to receive(:run)
|
350
|
+
|
351
|
+
subject.restore
|
281
352
|
end
|
282
353
|
end
|
283
354
|
end
|
284
355
|
|
285
|
-
context "when folders don't exist" do
|
286
|
-
let(:
|
356
|
+
context "when folders don't exist or are empty" do
|
357
|
+
let(:uids) { [] }
|
287
358
|
|
288
359
|
it "creates the folder" do
|
289
|
-
expect(folder).to
|
360
|
+
expect(folder).to receive(:create)
|
361
|
+
|
362
|
+
subject.restore
|
290
363
|
end
|
291
364
|
|
292
|
-
it "
|
365
|
+
it "forces local uid validity" do
|
366
|
+
expect(serializer).to receive(:force_uid_validity).with(uid_validity)
|
367
|
+
|
368
|
+
subject.restore
|
293
369
|
end
|
294
370
|
|
295
371
|
it "runs the uploader" do
|
296
|
-
expect(uploader).to
|
372
|
+
expect(uploader).to receive(:run)
|
373
|
+
|
374
|
+
subject.restore
|
297
375
|
end
|
298
376
|
end
|
299
377
|
end
|
300
378
|
|
301
379
|
describe "#reconnect" do
|
302
|
-
before { subject.reconnect }
|
303
|
-
|
304
380
|
it "disconnects from the server" do
|
305
|
-
expect(imap).to
|
381
|
+
expect(imap).to receive(:disconnect)
|
382
|
+
|
383
|
+
subject.reconnect
|
306
384
|
end
|
307
385
|
|
308
386
|
it "causes reconnection on future access" do
|
309
|
-
|
310
|
-
|
311
|
-
|
387
|
+
expect(Net::IMAP).to receive(:new)
|
388
|
+
|
389
|
+
subject.reconnect
|
312
390
|
end
|
313
391
|
end
|
314
392
|
|
315
393
|
describe "#disconnect" do
|
316
|
-
before { subject.disconnect }
|
317
|
-
|
318
394
|
it "disconnects from the server" do
|
319
|
-
expect(imap).to
|
395
|
+
expect(imap).to receive(:disconnect)
|
396
|
+
|
397
|
+
subject.disconnect
|
320
398
|
end
|
321
399
|
end
|
322
400
|
end
|
@@ -28,7 +28,7 @@ describe Imap::Backup::Account::Folder do
|
|
28
28
|
describe "#uids" do
|
29
29
|
let(:uids) { [5678, 123] }
|
30
30
|
|
31
|
-
before { allow(imap).to receive(:uid_search)
|
31
|
+
before { allow(imap).to receive(:uid_search) { uids } }
|
32
32
|
|
33
33
|
it "lists available messages" do
|
34
34
|
expect(subject.uids).to eq(uids.reverse)
|
@@ -43,6 +43,20 @@ describe Imap::Backup::Account::Folder do
|
|
43
43
|
expect(subject.uids).to eq([])
|
44
44
|
end
|
45
45
|
end
|
46
|
+
|
47
|
+
context "with no SEARCH response in Net::IMAP" do
|
48
|
+
let(:no_method_error) do
|
49
|
+
NoMethodError.new("Somethimes SEARCH responses come out undefined")
|
50
|
+
end
|
51
|
+
|
52
|
+
before do
|
53
|
+
allow(imap).to receive(:examine).and_raise(no_method_error)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns an empty array" do
|
57
|
+
expect(subject.uids).to eq([])
|
58
|
+
end
|
59
|
+
end
|
46
60
|
end
|
47
61
|
|
48
62
|
describe "#fetch" do
|
@@ -83,12 +97,6 @@ describe Imap::Backup::Account::Folder do
|
|
83
97
|
expect(subject.fetch(123)).to be_nil
|
84
98
|
end
|
85
99
|
end
|
86
|
-
|
87
|
-
it "sets the encoding on the message" do
|
88
|
-
subject.fetch(123)
|
89
|
-
|
90
|
-
expect(message_body).to have_received(:force_encoding).with("utf-8")
|
91
|
-
end
|
92
100
|
end
|
93
101
|
|
94
102
|
describe "#folder" do
|
@@ -117,21 +125,22 @@ describe Imap::Backup::Account::Folder do
|
|
117
125
|
|
118
126
|
describe "#create" do
|
119
127
|
context "when the folder exists" do
|
120
|
-
before { subject.create }
|
121
|
-
|
122
128
|
it "is does not create the folder" do
|
123
|
-
expect(imap).to_not
|
129
|
+
expect(imap).to_not receive(:create)
|
130
|
+
|
131
|
+
subject.create
|
124
132
|
end
|
125
133
|
end
|
126
134
|
|
127
135
|
context "when the folder doesn't exist" do
|
128
136
|
before do
|
129
137
|
allow(imap).to receive(:examine).and_raise(missing_mailbox_error)
|
130
|
-
subject.create
|
131
138
|
end
|
132
139
|
|
133
140
|
it "is does not create the folder" do
|
134
|
-
expect(imap).to
|
141
|
+
expect(imap).to receive(:create)
|
142
|
+
|
143
|
+
subject.create
|
135
144
|
end
|
136
145
|
end
|
137
146
|
end
|
@@ -168,26 +177,27 @@ describe Imap::Backup::Account::Folder do
|
|
168
177
|
let(:append_response) do
|
169
178
|
OpenStruct.new(data: OpenStruct.new(code: OpenStruct.new(data: "1 2")))
|
170
179
|
end
|
171
|
-
let(:result) { subject.append(message) }
|
172
|
-
|
173
|
-
before do
|
174
|
-
result
|
175
|
-
end
|
176
180
|
|
177
181
|
it "appends the message" do
|
178
|
-
expect(imap).to
|
182
|
+
expect(imap).to receive(:append)
|
183
|
+
|
184
|
+
subject.append(message)
|
179
185
|
end
|
180
186
|
|
181
187
|
it "sets the date and time" do
|
182
|
-
expect(imap).to
|
188
|
+
expect(imap).to receive(:append).
|
183
189
|
with(anything, anything, anything, message_date)
|
190
|
+
|
191
|
+
subject.append(message)
|
184
192
|
end
|
185
193
|
|
186
194
|
it "returns the new uid" do
|
187
|
-
expect(
|
195
|
+
expect(subject.append(message)).to eq(2)
|
188
196
|
end
|
189
197
|
|
190
198
|
it "set the new uid validity" do
|
199
|
+
subject.append(message)
|
200
|
+
|
191
201
|
expect(subject.uid_validity).to eq(1)
|
192
202
|
end
|
193
203
|
end
|