imap-backup 4.0.3 → 4.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/email/provider/apple_mail.rb +2 -2
  3. data/lib/email/provider/base.rb +8 -0
  4. data/lib/email/provider/fastmail.rb +2 -2
  5. data/lib/email/provider/gmail.rb +2 -2
  6. data/lib/email/provider/{default.rb → unknown.rb} +2 -3
  7. data/lib/email/provider.rb +2 -2
  8. data/lib/imap/backup/account/connection.rb +23 -31
  9. data/lib/imap/backup/account/folder.rb +1 -1
  10. data/lib/imap/backup/account.rb +98 -0
  11. data/lib/imap/backup/cli/helpers.rb +1 -1
  12. data/lib/imap/backup/cli/local.rb +1 -1
  13. data/lib/imap/backup/configuration/account.rb +38 -30
  14. data/lib/imap/backup/configuration/folder_chooser.rb +7 -9
  15. data/lib/imap/backup/configuration/list.rb +1 -1
  16. data/lib/imap/backup/configuration/setup.rb +10 -8
  17. data/lib/imap/backup/configuration/store.rb +33 -11
  18. data/lib/imap/backup/version.rb +1 -1
  19. data/lib/imap/backup.rb +1 -0
  20. data/spec/features/support/shared/connection_context.rb +7 -5
  21. data/spec/unit/email/provider/{default_spec.rb → base_spec.rb} +1 -7
  22. data/spec/unit/email/provider_spec.rb +2 -2
  23. data/spec/unit/imap/backup/account/connection_spec.rb +8 -17
  24. data/spec/unit/imap/backup/cli/local_spec.rb +9 -2
  25. data/spec/unit/imap/backup/cli/utils_spec.rb +44 -42
  26. data/spec/unit/imap/backup/configuration/account_spec.rb +47 -46
  27. data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +17 -18
  28. data/spec/unit/imap/backup/configuration/list_spec.rb +12 -5
  29. data/spec/unit/imap/backup/configuration/setup_spec.rb +33 -12
  30. data/spec/unit/imap/backup/configuration/store_spec.rb +21 -22
  31. metadata +32 -32
  32. data/spec/support/shared_examples/account_flagging.rb +0 -23
@@ -1,11 +1,14 @@
1
1
  require "json"
2
2
  require "os"
3
3
 
4
+ require "imap/backup/account"
5
+
4
6
  module Imap::Backup
5
7
  module Configuration; end
6
8
 
7
9
  class Configuration::Store
8
10
  CONFIGURATION_DIRECTORY = File.expand_path("~/.imap-backup")
11
+ VERSION = "2.0"
9
12
 
10
13
  attr_reader :pathname
11
14
 
@@ -19,6 +22,7 @@ module Imap::Backup
19
22
 
20
23
  def initialize(pathname = self.class.default_pathname)
21
24
  @pathname = pathname
25
+ @debug = nil
22
26
  end
23
27
 
24
28
  def path
@@ -26,53 +30,71 @@ module Imap::Backup
26
30
  end
27
31
 
28
32
  def save
33
+ ensure_loaded!
29
34
  FileUtils.mkdir(path) if !File.directory?(path)
30
35
  make_private(path) if !windows?
31
36
  remove_modified_flags
32
37
  remove_deleted_accounts
33
- File.open(pathname, "w") { |f| f.write(JSON.pretty_generate(data)) }
38
+ save_data = {
39
+ version: VERSION,
40
+ accounts: accounts.map(&:to_h),
41
+ debug: debug?
42
+ }
43
+ File.open(pathname, "w") { |f| f.write(JSON.pretty_generate(save_data)) }
34
44
  FileUtils.chmod(0o600, pathname) if !windows?
35
45
  end
36
46
 
37
47
  def accounts
38
- data[:accounts]
48
+ @accounts ||= begin
49
+ ensure_loaded!
50
+ data[:accounts].map { |data| Account.new(data) }
51
+ end
39
52
  end
40
53
 
41
54
  def modified?
42
- accounts.any? { |a| a[:modified] || a[:delete] }
55
+ ensure_loaded!
56
+ accounts.any? { |a| a.modified? || a.marked_for_deletion? }
43
57
  end
44
58
 
45
59
  def debug?
46
- data[:debug]
60
+ ensure_loaded!
61
+ @debug
47
62
  end
48
63
 
49
64
  def debug=(value)
50
- data[:debug] = [true, false].include?(value) ? value : false
65
+ ensure_loaded!
66
+ @debug = [true, false].include?(value) ? value : false
51
67
  end
52
68
 
53
69
  private
54
70
 
71
+ def ensure_loaded!
72
+ return true if @data
73
+
74
+ data
75
+ @debug = data.key?(:debug) ? data[:debug] == true : false
76
+ true
77
+ end
78
+
55
79
  def data
56
80
  @data ||=
57
81
  begin
58
82
  if File.exist?(pathname)
59
83
  Utils.check_permissions(pathname, 0o600) if !windows?
60
84
  contents = File.read(pathname)
61
- data = JSON.parse(contents, symbolize_names: true)
85
+ JSON.parse(contents, symbolize_names: true)
62
86
  else
63
- data = {accounts: []}
87
+ {accounts: []}
64
88
  end
65
- data[:debug] = data.key?(:debug) ? data[:debug] == true : false
66
- data
67
89
  end
68
90
  end
69
91
 
70
92
  def remove_modified_flags
71
- accounts.each { |a| a.delete(:modified) }
93
+ accounts.each { |a| a.clear_changes! }
72
94
  end
73
95
 
74
96
  def remove_deleted_accounts
75
- accounts.reject! { |a| a[:delete] }
97
+ accounts.reject! { |a| a.marked_for_deletion? }
76
98
  end
77
99
 
78
100
  def make_private(path)
@@ -3,7 +3,7 @@ module Imap; end
3
3
  module Imap::Backup
4
4
  MAJOR = 4
5
5
  MINOR = 0
6
- REVISION = 3
6
+ REVISION = 7
7
7
  PRE = nil
8
8
  VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
9
9
  end
data/lib/imap/backup.rb CHANGED
@@ -29,6 +29,7 @@ module Imap::Backup
29
29
 
30
30
  def initialize
31
31
  @logger = ::Logger.new($stdout)
32
+ $stdout.sync = true
32
33
  end
33
34
  end
34
35
 
@@ -2,11 +2,13 @@ shared_context "imap-backup connection" do
2
2
  let(:local_backup_path) { Dir.mktmpdir(nil, "tmp") }
3
3
  let(:default_connection) { fixture("connection") }
4
4
  let(:backup_folders) { nil }
5
- let(:connection_options) do
6
- default_connection.merge(
7
- local_path: local_backup_path,
8
- folders: backup_folders
5
+ let(:account) do
6
+ Imap::Backup::Account.new(
7
+ default_connection.merge(
8
+ local_path: local_backup_path,
9
+ folders: backup_folders
10
+ )
9
11
  )
10
12
  end
11
- let(:connection) { Imap::Backup::Account::Connection.new(connection_options) }
13
+ let(:connection) { Imap::Backup::Account::Connection.new(account) }
12
14
  end
@@ -1,10 +1,4 @@
1
- describe Email::Provider::Default do
2
- describe "#host" do
3
- it "is unset" do
4
- expect(subject.host).to be_nil
5
- end
6
- end
7
-
1
+ describe Email::Provider::Base do
8
2
  describe "#options" do
9
3
  it "returns options" do
10
4
  expect(subject.options).to be_a(Hash)
@@ -17,10 +17,10 @@ describe Email::Provider do
17
17
  end
18
18
 
19
19
  context "with unknown providers" do
20
- it "returns a default provider" do
20
+ it "returns the Unknown provider" do
21
21
  result = described_class.for_address("foo@unknown.com")
22
22
 
23
- expect(result).to be_a(Email::Provider::Default)
23
+ expect(result).to be_a(Email::Provider::Unknown)
24
24
  end
25
25
  end
26
26
  end
@@ -12,7 +12,7 @@ describe Imap::Backup::Account::Connection do
12
12
  SERVER = "imap.example.com".freeze
13
13
  USERNAME = "username@example.com".freeze
14
14
 
15
- subject { described_class.new(options) }
15
+ subject { described_class.new(account) }
16
16
 
17
17
  let(:client) do
18
18
  instance_double(
@@ -20,14 +20,16 @@ describe Imap::Backup::Account::Connection do
20
20
  )
21
21
  end
22
22
  let(:imap_folders) { [] }
23
- let(:options) do
24
- {
23
+ let(:account) do
24
+ instance_double(
25
+ Imap::Backup::Account,
25
26
  username: USERNAME,
26
27
  password: PASSWORD,
27
28
  local_path: LOCAL_PATH,
28
29
  folders: config_folders,
29
- server: server
30
- }
30
+ server: server,
31
+ connection_options: nil
32
+ )
31
33
  end
32
34
  let(:config_folders) { [FOLDER_CONFIG] }
33
35
  let(:root_info) do
@@ -59,21 +61,10 @@ describe Imap::Backup::Account::Connection do
59
61
  end
60
62
 
61
63
  describe "#initialize" do
62
- [
63
- [:username, USERNAME],
64
- [:password, PASSWORD],
65
- [:local_path, LOCAL_PATH],
66
- [:server, SERVER]
67
- ].each do |attr, expected|
68
- it "expects #{attr}" do
69
- expect(subject.public_send(attr)).to eq(expected)
70
- end
71
- end
72
-
73
64
  it "creates the path" do
74
65
  expect(Imap::Backup::Utils).to receive(:make_folder)
75
66
 
76
- subject.username
67
+ subject
77
68
  end
78
69
  end
79
70
 
@@ -1,8 +1,15 @@
1
1
  describe Imap::Backup::CLI::Local do
2
2
  let(:list) do
3
- instance_double(Imap::Backup::Configuration::List, accounts: accounts)
3
+ instance_double(Imap::Backup::Configuration::List, accounts: [account])
4
+ end
5
+ let(:account) do
6
+ instance_double(
7
+ Imap::Backup::Account,
8
+ username: email,
9
+ marked_for_deletion?: false,
10
+ modified?: false
11
+ )
4
12
  end
5
- let(:accounts) { [{username: email}] }
6
13
  let(:connection) do
7
14
  instance_double(
8
15
  Imap::Backup::Account::Connection,
@@ -1,50 +1,52 @@
1
- describe Imap::Backup::CLI::Utils do
2
- let(:list) do
3
- instance_double(Imap::Backup::Configuration::List, accounts: accounts)
4
- end
5
- let(:accounts) { [{username: email}] }
6
- let(:connection) do
7
- instance_double(
8
- Imap::Backup::Account::Connection,
9
- local_folders: local_folders
10
- )
11
- end
12
- let(:local_folders) { [[serializer, folder]] }
13
- let(:folder) do
14
- instance_double(
15
- Imap::Backup::Account::Folder,
16
- exist?: true,
17
- name: "name",
18
- uid_validity: "uid_validity",
19
- uids: %w(123 456)
20
- )
21
- end
22
- let(:serializer) do
23
- instance_double(
24
- Imap::Backup::Serializer::Mbox,
25
- uids: %w(123 789),
26
- apply_uid_validity: nil,
27
- save: nil
28
- )
29
- end
30
- let(:email) { "foo@example.com" }
1
+ module Imap::Backup
2
+ describe CLI::Utils do
3
+ let(:list) do
4
+ instance_double(Configuration::List, accounts: [account])
5
+ end
6
+ let(:account) { instance_double(Account, username: email) }
7
+ let(:connection) do
8
+ instance_double(
9
+ Account::Connection,
10
+ local_folders: local_folders
11
+ )
12
+ end
13
+ let(:local_folders) { [[serializer, folder]] }
14
+ let(:folder) do
15
+ instance_double(
16
+ Account::Folder,
17
+ exist?: true,
18
+ name: "name",
19
+ uid_validity: "uid_validity",
20
+ uids: %w(123 456)
21
+ )
22
+ end
23
+ let(:serializer) do
24
+ instance_double(
25
+ Serializer::Mbox,
26
+ uids: %w(123 789),
27
+ apply_uid_validity: nil,
28
+ save: nil
29
+ )
30
+ end
31
+ let(:email) { "foo@example.com" }
31
32
 
32
- before do
33
- allow(Imap::Backup::Configuration::List).to receive(:new) { list }
34
- allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
35
- end
33
+ before do
34
+ allow(Configuration::List).to receive(:new) { list }
35
+ allow(Account::Connection).to receive(:new) { connection }
36
+ end
36
37
 
37
- describe "ignore_history" do
38
- it "ensures the local UID validity matches the server" do
39
- subject.ignore_history(email)
38
+ describe "ignore_history" do
39
+ it "ensures the local UID validity matches the server" do
40
+ subject.ignore_history(email)
40
41
 
41
- expect(serializer).to have_received(:apply_uid_validity).with("uid_validity")
42
- end
42
+ expect(serializer).to have_received(:apply_uid_validity).with("uid_validity")
43
+ end
43
44
 
44
- it "fills the local folder with fake emails" do
45
- subject.ignore_history(email)
45
+ it "fills the local folder with fake emails" do
46
+ subject.ignore_history(email)
46
47
 
47
- expect(serializer).to have_received(:save).with("456", /From: fake@email.com/)
48
+ expect(serializer).to have_received(:save).with("456", /From: fake@email.com/)
49
+ end
48
50
  end
49
51
  end
50
52
  end
@@ -6,7 +6,32 @@ describe Imap::Backup::Configuration::Account do
6
6
 
7
7
  subject { described_class.new(store, account, highline) }
8
8
 
9
- let(:account) { ACCOUNT }
9
+ let(:account) do
10
+ instance_double(
11
+ Imap::Backup::Account,
12
+ username: existing_email,
13
+ password: existing_password,
14
+ server: current_server,
15
+ connection_options: nil,
16
+ local_path: "/backup/path",
17
+ folders: [{name: "my_folder"}]
18
+ )
19
+ end
20
+ let(:account1) do
21
+ instance_double(
22
+ Imap::Backup::Account,
23
+ username: other_email,
24
+ local_path: other_existing_path
25
+ )
26
+ end
27
+ let(:accounts) { [account, account1] }
28
+ let(:existing_email) { "user@example.com" }
29
+ let(:new_email) { "foo@example.com" }
30
+ let(:current_server) { "imap.example.com" }
31
+ let(:existing_password) { "password" }
32
+ let(:other_email) { "other@example.com" }
33
+ let(:other_existing_path) { "/other/existing/path" }
34
+
10
35
  let(:highline) { HIGHLINE }
11
36
  let(:store) { STORE }
12
37
 
@@ -43,28 +68,6 @@ describe Imap::Backup::Configuration::Account do
43
68
  let(:store) do
44
69
  instance_double(Imap::Backup::Configuration::Store, accounts: accounts)
45
70
  end
46
- let(:accounts) { [account, account1] }
47
- let(:account) do
48
- {
49
- username: existing_email,
50
- server: current_server,
51
- local_path: "/backup/path",
52
- folders: [{name: "my_folder"}],
53
- password: existing_password
54
- }
55
- end
56
- let(:account1) do
57
- {
58
- username: other_email,
59
- local_path: other_existing_path
60
- }
61
- end
62
- let(:existing_email) { "user@example.com" }
63
- let(:new_email) { "foo@example.com" }
64
- let(:current_server) { "imap.example.com" }
65
- let(:existing_password) { "password" }
66
- let(:other_email) { "other@example.com" }
67
- let(:other_existing_path) { "/other/existing/path" }
68
71
 
69
72
  before do
70
73
  allow(Kernel).to receive(:system)
@@ -139,6 +142,8 @@ describe Imap::Backup::Configuration::Account do
139
142
 
140
143
  describe "choosing 'modify email'" do
141
144
  before do
145
+ allow(account).to receive(:"username=")
146
+ allow(account).to receive(:"server=")
142
147
  allow(Imap::Backup::Configuration::Asker).
143
148
  to receive(:email) { new_email }
144
149
  subject.run
@@ -158,7 +163,7 @@ describe Imap::Backup::Configuration::Account do
158
163
  let(:current_server) { nil }
159
164
 
160
165
  it "sets a default server" do
161
- expect(account[:server]).to eq(expected)
166
+ expect(account).to have_received(:"server=").with(expected)
162
167
  end
163
168
  end
164
169
 
@@ -166,7 +171,7 @@ describe Imap::Backup::Configuration::Account do
166
171
  let(:current_server) { "" }
167
172
 
168
173
  it "sets a default server" do
169
- expect(account[:server]).to eq(expected)
174
+ expect(account).to have_received(:"server=").with(expected)
170
175
  end
171
176
  end
172
177
  end
@@ -183,17 +188,15 @@ describe Imap::Backup::Configuration::Account do
183
188
  end
184
189
 
185
190
  it "does not set a default server" do
186
- expect(account[:server]).to be_nil
191
+ expect(account).to_not have_received(:"server=")
187
192
  end
188
193
  end
189
194
  end
190
195
 
191
196
  context "when the email is new" do
192
197
  it "modifies the email address" do
193
- expect(account[:username]).to eq(new_email)
198
+ expect(account).to have_received(:"username=").with(new_email)
194
199
  end
195
-
196
- include_examples "it flags the account as modified"
197
200
  end
198
201
 
199
202
  context "when the email already exists" do
@@ -205,10 +208,8 @@ describe Imap::Backup::Configuration::Account do
205
208
  end
206
209
 
207
210
  it "doesn't set the email" do
208
- expect(account[:username]).to eq(existing_email)
211
+ expect(account.username).to eq(existing_email)
209
212
  end
210
-
211
- include_examples "it doesn't flag the account as modified"
212
213
  end
213
214
  end
214
215
 
@@ -216,6 +217,7 @@ describe Imap::Backup::Configuration::Account do
216
217
  let(:new_password) { "new_password" }
217
218
 
218
219
  before do
220
+ allow(account).to receive(:"password=")
219
221
  allow(Imap::Backup::Configuration::Asker).
220
222
  to receive(:password) { new_password }
221
223
  subject.run
@@ -224,20 +226,16 @@ describe Imap::Backup::Configuration::Account do
224
226
 
225
227
  context "when the user enters a password" do
226
228
  it "updates the password" do
227
- expect(account[:password]).to eq(new_password)
229
+ expect(account).to have_received(:"password=").with(new_password)
228
230
  end
229
-
230
- include_examples "it flags the account as modified"
231
231
  end
232
232
 
233
233
  context "when the user cancels" do
234
234
  let(:new_password) { nil }
235
235
 
236
236
  it "does nothing" do
237
- expect(account[:password]).to eq(existing_password)
237
+ expect(account.password).to eq(existing_password)
238
238
  end
239
-
240
- include_examples "it doesn't flag the account as modified"
241
239
  end
242
240
  end
243
241
 
@@ -245,6 +243,7 @@ describe Imap::Backup::Configuration::Account do
245
243
  let(:server) { "server" }
246
244
 
247
245
  before do
246
+ allow(account).to receive(:"server=")
248
247
  allow(highline).to receive(:ask).with("server: ") { server }
249
248
 
250
249
  subject.run
@@ -253,16 +252,15 @@ describe Imap::Backup::Configuration::Account do
253
252
  end
254
253
 
255
254
  it "updates the server" do
256
- expect(account[:server]).to eq(server)
255
+ expect(account).to have_received(:"server=").with(server)
257
256
  end
258
-
259
- include_examples "it flags the account as modified"
260
257
  end
261
258
 
262
259
  describe "choosing 'modify backup path'" do
263
260
  let(:new_backup_path) { "/new/path" }
264
261
 
265
262
  before do
263
+ allow(account).to receive(:"local_path=")
266
264
  @validator = nil
267
265
  allow(
268
266
  Imap::Backup::Configuration::Asker
@@ -275,7 +273,7 @@ describe Imap::Backup::Configuration::Account do
275
273
  end
276
274
 
277
275
  it "updates the path" do
278
- expect(account[:local_path]).to eq(new_backup_path)
276
+ expect(account).to have_received(:"local_path=").with(new_backup_path)
279
277
  end
280
278
 
281
279
  context "when the path is not used by other backups" do
@@ -293,8 +291,6 @@ describe Imap::Backup::Configuration::Account do
293
291
  # rubocop:enable RSpec/InstanceVariable
294
292
  end
295
293
  end
296
-
297
- include_examples "it flags the account as modified"
298
294
  end
299
295
 
300
296
  describe "choosing 'choose backup folders'" do
@@ -333,6 +329,7 @@ describe Imap::Backup::Configuration::Account do
333
329
  let(:confirmed) { true }
334
330
 
335
331
  before do
332
+ allow(account).to receive(:mark_for_deletion!)
336
333
  allow(highline).to receive(:agree) { confirmed }
337
334
  subject.run
338
335
  catch :done do
@@ -345,13 +342,17 @@ describe Imap::Backup::Configuration::Account do
345
342
  end
346
343
 
347
344
  context "when the user confirms deletion" do
348
- include_examples "it flags the account to be deleted"
345
+ it "flags the account to be deleted" do
346
+ expect(account).to have_received(:mark_for_deletion!)
347
+ end
349
348
  end
350
349
 
351
350
  context "without confirmation" do
352
351
  let(:confirmed) { false }
353
352
 
354
- include_examples "it doesn't flag the account to be deleted"
353
+ it "doesn't flag the account to be deleted" do
354
+ expect(account).to_not have_received(:mark_for_deletion!)
355
+ end
355
356
  end
356
357
  end
357
358
  end
@@ -9,7 +9,14 @@ describe Imap::Backup::Configuration::FolderChooser do
9
9
  Imap::Backup::Account::Connection, folders: connection_folders
10
10
  )
11
11
  end
12
- let(:account) { {folders: []} }
12
+ let(:account) do
13
+ instance_double(
14
+ Imap::Backup::Account,
15
+ folders: account_folders,
16
+ "folders=": nil
17
+ )
18
+ end
19
+ let(:account_folders) { [] }
13
20
  let(:connection_folders) { [] }
14
21
  let!(:highline_streams) { prepare_highline }
15
22
  let(:input) { highline_streams[0] }
@@ -36,7 +43,7 @@ describe Imap::Backup::Configuration::FolderChooser do
36
43
  end
37
44
 
38
45
  describe "folder listing" do
39
- let(:account) { {folders: [{name: "my_folder"}]} }
46
+ let(:account_folders) { [{name: "my_folder"}]}
40
47
  let(:connection_folders) do
41
48
  # N.B. my_folder is already backed up
42
49
  %w(my_folder another_folder)
@@ -62,10 +69,9 @@ describe Imap::Backup::Configuration::FolderChooser do
62
69
  end
63
70
 
64
71
  specify "are added to the account" do
65
- expect(account[:folders]).to include(name: "another_folder")
72
+ expect(account).to have_received(:"folders=").
73
+ with([{name: "my_folder"}, {name: "another_folder"}])
66
74
  end
67
-
68
- include_examples "it flags the account as modified"
69
75
  end
70
76
 
71
77
  context "when removing folders" do
@@ -76,22 +82,16 @@ describe Imap::Backup::Configuration::FolderChooser do
76
82
  end
77
83
 
78
84
  specify "are removed from the account" do
79
- expect(account[:folders]).to_not include(name: "my_folder")
85
+ expect(account).to have_received(:"folders=").with([])
80
86
  end
81
-
82
- include_examples "it flags the account as modified"
83
87
  end
84
88
  end
85
89
 
86
90
  context "with missing remote folders" do
87
- let(:account) do
88
- {folders: [{name: "on_server"}, {name: "not_on_server"}]}
89
- end
90
- let(:connection_folders) do
91
- [
92
- instance_double(Imap::Backup::Account::Folder, name: "on_server")
93
- ]
91
+ let(:account_folders) do
92
+ [{name: "on_server"}, {name: "not_on_server"}]
94
93
  end
94
+ let(:connection_folders) { ["on_server"] }
95
95
 
96
96
  before do
97
97
  allow(Kernel).to receive(:puts)
@@ -99,10 +99,9 @@ describe Imap::Backup::Configuration::FolderChooser do
99
99
  end
100
100
 
101
101
  specify "are removed from the account" do
102
- expect(account[:folders]).to_not include(name: "not_on_server")
102
+ expect(account).to have_received(:"folders=").
103
+ with([{name: "on_server"}])
103
104
  end
104
-
105
- include_examples "it flags the account as modified"
106
105
  end
107
106
 
108
107
  context "when folders are not available" do
@@ -1,11 +1,18 @@
1
1
  describe Imap::Backup::Configuration::List do
2
2
  subject { described_class.new }
3
3
 
4
- let(:accounts) do
5
- [
6
- {username: "a1@example.com"},
7
- {username: "a2@example.com"}
8
- ]
4
+ let(:accounts) { [account1, account2] }
5
+ let(:account1) do
6
+ instance_double(
7
+ Imap::Backup::Account,
8
+ username: "a1@example.com"
9
+ )
10
+ end
11
+ let(:account2) do
12
+ instance_double(
13
+ Imap::Backup::Account,
14
+ username: "a2@example.com"
15
+ )
9
16
  end
10
17
  let(:store) do
11
18
  instance_double(Imap::Backup::Configuration::Store, accounts: accounts)