imap-backup 2.0.0 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.rspec-all +2 -0
  4. data/.rubocop.yml +15 -2
  5. data/.rubocop_todo.yml +58 -0
  6. data/.travis.yml +15 -2
  7. data/README.md +14 -22
  8. data/Rakefile +6 -3
  9. data/bin/imap-backup +5 -11
  10. data/imap-backup.gemspec +10 -6
  11. data/lib/email/mboxrd/message.rb +16 -16
  12. data/lib/imap/backup/account/connection.rb +38 -22
  13. data/lib/imap/backup/account/folder.rb +23 -7
  14. data/lib/imap/backup/configuration/account.rb +25 -21
  15. data/lib/imap/backup/configuration/asker.rb +3 -2
  16. data/lib/imap/backup/configuration/connection_tester.rb +1 -1
  17. data/lib/imap/backup/configuration/folder_chooser.rb +32 -5
  18. data/lib/imap/backup/configuration/list.rb +2 -0
  19. data/lib/imap/backup/configuration/setup.rb +2 -1
  20. data/lib/imap/backup/configuration/store.rb +3 -6
  21. data/lib/imap/backup/downloader.rb +8 -7
  22. data/lib/imap/backup/serializer/mbox.rb +44 -25
  23. data/lib/imap/backup/serializer/mbox_enumerator.rb +31 -0
  24. data/lib/imap/backup/serializer/mbox_store.rb +35 -32
  25. data/lib/imap/backup/uploader.rb +11 -2
  26. data/lib/imap/backup/utils.rb +11 -9
  27. data/lib/imap/backup/version.rb +2 -2
  28. data/spec/features/backup_spec.rb +6 -5
  29. data/spec/features/helper.rb +1 -1
  30. data/spec/features/restore_spec.rb +75 -27
  31. data/spec/features/support/backup_directory.rb +7 -7
  32. data/spec/features/support/email_server.rb +15 -11
  33. data/spec/features/support/shared/connection_context.rb +2 -2
  34. data/spec/features/support/shared/message_fixtures.rb +8 -0
  35. data/spec/spec_helper.rb +1 -1
  36. data/spec/support/fixtures.rb +2 -2
  37. data/spec/support/higline_test_helpers.rb +1 -1
  38. data/spec/unit/email/mboxrd/message_spec.rb +73 -53
  39. data/spec/unit/email/provider_spec.rb +3 -5
  40. data/spec/unit/imap/backup/account/connection_spec.rb +82 -59
  41. data/spec/unit/imap/backup/account/folder_spec.rb +75 -37
  42. data/spec/unit/imap/backup/configuration/account_spec.rb +95 -61
  43. data/spec/unit/imap/backup/configuration/asker_spec.rb +43 -45
  44. data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +21 -22
  45. data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +66 -33
  46. data/spec/unit/imap/backup/configuration/list_spec.rb +32 -11
  47. data/spec/unit/imap/backup/configuration/setup_spec.rb +97 -56
  48. data/spec/unit/imap/backup/configuration/store_spec.rb +30 -25
  49. data/spec/unit/imap/backup/downloader_spec.rb +28 -26
  50. data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +45 -0
  51. data/spec/unit/imap/backup/serializer/mbox_spec.rb +109 -51
  52. data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +232 -20
  53. data/spec/unit/imap/backup/uploader_spec.rb +23 -9
  54. data/spec/unit/imap/backup/utils_spec.rb +14 -15
  55. data/spec/unit/imap/backup_spec.rb +28 -0
  56. metadata +13 -7
@@ -1,6 +1,6 @@
1
1
  module EmailServerHelpers
2
- REQUESTED_ATTRIBUTES = ["RFC822", "FLAGS", "INTERNALDATE"]
3
- DEFAULT_EMAIL = "address@example.org"
2
+ REQUESTED_ATTRIBUTES = %w(RFC822 FLAGS INTERNALDATE).freeze
3
+ DEFAULT_EMAIL = "address@example.org".freeze
4
4
 
5
5
  def send_email(folder, options)
6
6
  message = message_as_server_message(options)
@@ -11,13 +11,14 @@ module EmailServerHelpers
11
11
  from = options[:from] || DEFAULT_EMAIL
12
12
  subject = options[:subject]
13
13
  body = options[:body]
14
- message = <<-EOT.gsub("\n", "\r\n")
15
- From: #{from}
16
- Subject: #{subject}
17
14
 
18
- #{body}
15
+ <<~MESSAGE.gsub("\n", "\r\n")
16
+ From: #{from}
17
+ Subject: #{subject}
19
18
 
20
- EOT
19
+ #{body}
20
+
21
+ MESSAGE
21
22
  end
22
23
 
23
24
  def server_messages(folder)
@@ -32,18 +33,18 @@ Subject: #{subject}
32
33
 
33
34
  def server_fetch_email(folder, uid)
34
35
  examine folder
36
+
35
37
  fetch_data_items = imap.uid_fetch([uid.to_i], REQUESTED_ATTRIBUTES)
36
38
  return nil if fetch_data_items.nil?
39
+
37
40
  fetch_data_item = fetch_data_items[0]
38
- attributes = fetch_data_item.attr
39
- attributes["RFC822"].force_encoding("utf-8")
40
- attributes
41
+ fetch_data_item.attr
41
42
  end
42
43
 
43
44
  def delete_emails(folder)
44
45
  imap.select(folder)
45
46
  uids = imap.uid_search(["ALL"]).sort
46
- imap.store(1 .. uids.size, "+FLAGS", [:Deleted])
47
+ imap.store(1..uids.size, "+FLAGS", [:Deleted])
47
48
  imap.expunge
48
49
  end
49
50
 
@@ -82,6 +83,9 @@ Subject: #{subject}
82
83
  def server_delete_folder(folder)
83
84
  imap.delete folder
84
85
  imap.disconnect
86
+ rescue StandardError => e
87
+ puts e.to_s
88
+ ensure
85
89
  @imap = nil
86
90
  end
87
91
 
@@ -3,10 +3,10 @@ shared_context "imap-backup connection" do
3
3
  let(:default_connection) { fixture("connection") }
4
4
  let(:backup_folders) { nil }
5
5
  let(:connection_options) do
6
- default_connection.merge({
6
+ default_connection.merge(
7
7
  local_path: local_backup_path,
8
8
  folders: backup_folders
9
- })
9
+ )
10
10
  end
11
11
  let(:connection) { Imap::Backup::Account::Connection.new(connection_options) }
12
12
  end
@@ -2,7 +2,15 @@ shared_context "message-fixtures" do
2
2
  let(:uid1) { 123 }
3
3
  let(:uid2) { 345 }
4
4
  let(:uid3) { 567 }
5
+ let(:uid_iso8859) { 890 }
5
6
  let(:msg1) { {uid: uid1, subject: "Test 1", body: "body 1\nHi"} }
6
7
  let(:msg2) { {uid: uid2, subject: "Test 2", body: "body 2"} }
7
8
  let(:msg3) { {uid: uid3, subject: "Test 3", body: "body 3"} }
9
+ let(:msg_iso8859) do
10
+ {
11
+ uid: uid_iso8859,
12
+ subject: "iso8859 Body",
13
+ body: "Ma, perchè?".encode(Encoding::ISO_8859_1).force_encoding("binary")
14
+ }
15
+ end
8
16
  end
@@ -7,7 +7,7 @@ spec_path = File.dirname(__FILE__)
7
7
  $LOAD_PATH << File.expand_path("../lib", spec_path)
8
8
 
9
9
  support_glob = File.join(spec_path, "support", "**", "*.rb")
10
- Dir[support_glob].each { |f| require f }
10
+ Dir[support_glob].sort.each { |f| require f }
11
11
 
12
12
  require "simplecov"
13
13
  SimpleCov.start do
@@ -1,6 +1,6 @@
1
1
  def fixture(name)
2
2
  spec_root = File.expand_path("..", File.dirname(__FILE__))
3
- fixture_path = File.join(spec_root, "fixtures", name + ".yml")
3
+ fixture_path = File.join(spec_root, "fixtures", "#{name}.yml")
4
4
  fixture = File.read(fixture_path)
5
- YAML.load(fixture)
5
+ YAML.safe_load(fixture, [Symbol])
6
6
  end
@@ -1,6 +1,6 @@
1
1
  module HighLineTestHelpers
2
2
  def prepare_highline
3
- @input = double("stdin", eof?: false, gets: "q\n")
3
+ @input = instance_double(IO, eof?: false, gets: "q\n")
4
4
  @output = StringIO.new
5
5
  Imap::Backup::Configuration::Setup.highline = HighLine.new(@input, @output)
6
6
  [@input, @output]
@@ -1,79 +1,82 @@
1
- require "spec_helper"
2
-
3
- msg_no_from = %Q|Delivered-To: you@example.com
4
- From: example <www.example.com>
5
- To: FirstName LastName <you@example.com>
6
- Subject: Re: no subject|
7
-
8
- msg_bad_from = %Q|Delivered-To: you@example.com
9
- from: "FirstName LastName (TEXT)" <"TEXT*" <no-reply@example.com>>
10
- To: FirstName LastName <you@example.com>
11
- Subject: Re: no subject|
12
-
13
- msg_no_from_but_return_path = %Q|Delivered-To: you@example.com
14
- From: example <www.example.com>
15
- To: FirstName LastName <you@example.com>
16
- Return-Path: <me@example.com>
17
- Subject: Re: no subject|
18
-
19
- msg_no_from_but_sender = %Q|Delivered-To: you@example.com
20
- To: FirstName LastName <you@example.com>
21
- Subject: Re: no subject
22
- Sender: FistName LastName <me@example.com>|
1
+ msg_no_from = <<~NO_FROM
2
+ Delivered-To: you@example.com
3
+ From: example <www.example.com>
4
+ To: FirstName LastName <you@example.com>
5
+ Subject: Re: no subject
6
+ NO_FROM
7
+
8
+ msg_bad_from = <<~BAD_FROM
9
+ Delivered-To: you@example.com
10
+ from: "FirstName LastName (TEXT)" <"TEXT*" <no-reply@example.com>>
11
+ To: FirstName LastName <you@example.com>
12
+ Subject: Re: no subject
13
+ BAD_FROM
14
+
15
+ msg_no_from_but_return_path = <<~RETURN_PATH
16
+ Delivered-To: you@example.com
17
+ From: example <www.example.com>
18
+ To: FirstName LastName <you@example.com>
19
+ Return-Path: <me@example.com>
20
+ Subject: Re: no subject
21
+ RETURN_PATH
22
+
23
+ msg_no_from_but_sender = <<~NOT_SENDER
24
+ Delivered-To: you@example.com
25
+ To: FirstName LastName <you@example.com>
26
+ Subject: Re: no subject
27
+ Sender: FistName LastName <me@example.com>
28
+ NOT_SENDER
23
29
 
24
30
  describe Email::Mboxrd::Message do
31
+ subject { described_class.new(message_body) }
32
+
25
33
  let(:from) { "me@example.com" }
26
34
  let(:date) { DateTime.new(2012, 12, 13, 18, 23, 45) }
27
35
  let(:message_body) do
28
- double("Body", clone: cloned_message_body, force_encoding: nil)
36
+ instance_double(String, clone: cloned_message_body, force_encoding: nil)
29
37
  end
30
38
  let(:cloned_message_body) do
31
39
  "Foo\nBar\nFrom at the beginning of the line\n>>From quoted"
32
40
  end
33
41
  let(:msg_good) do
34
- %Q|Delivered-To: you@example.com
35
- From: Foo <foo@example.com>
36
- To: FirstName LastName <you@example.com>
37
- Date: #{date.rfc822}
38
- Subject: Re: no subject|
42
+ <<~GOOD
43
+ Delivered-To: you@example.com
44
+ From: Foo <foo@example.com>
45
+ To: FirstName LastName <you@example.com>
46
+ Date: #{date.rfc822}
47
+ Subject: Re: no subject
48
+ GOOD
39
49
  end
40
50
 
41
51
  let(:msg_bad_date) do
42
- %Q|Delivered-To: you@example.com
43
- From: Foo <foo@example.com>
44
- To: FirstName LastName <you@example.com>
45
- Date: Mon,5 May 2014 08:97:99 GMT
46
- Subject: Re: no subject|
52
+ <<~BAD
53
+ Delivered-To: you@example.com
54
+ From: Foo <foo@example.com>
55
+ To: FirstName LastName <you@example.com>
56
+ Date: Mon,5 May 2014 08:97:99 GMT
57
+ Subject: Re: no subject
58
+ BAD
47
59
  end
48
60
 
49
- subject { described_class.new(message_body) }
50
-
51
61
  describe ".from_serialized" do
52
62
  let(:serialized_message) { "From foo@a.com\n#{imap_message}" }
53
63
  let(:imap_message) { "Delivered-To: me@example.com\nFrom Me\n" }
54
-
55
- before { @result = described_class.from_serialized(serialized_message) }
64
+ let!(:result) { described_class.from_serialized(serialized_message) }
56
65
 
57
66
  it "returns the message" do
58
- expect(@result).to be_a(described_class)
67
+ expect(result).to be_a(described_class)
59
68
  end
60
69
 
61
70
  it "removes one level of > before From" do
62
- expect(@result.supplied_body).to eq(imap_message)
71
+ expect(result.supplied_body).to eq(imap_message)
63
72
  end
64
73
  end
65
74
 
66
- context "#to_serialized" do
67
- let(:mail) { double("Mail", from: [from], date: date) }
75
+ describe "#to_serialized" do
76
+ let(:mail) { instance_double(Mail::Message, from: [from], date: date) }
68
77
 
69
78
  before do
70
- allow(Mail).to receive(:new).with(cloned_message_body).and_return(mail)
71
- end
72
-
73
- it "does not modify the message" do
74
- subject.to_serialized
75
-
76
- expect(message_body).to_not have_received(:force_encoding).with("binary")
79
+ allow(Mail).to receive(:new).with(cloned_message_body) { mail }
77
80
  end
78
81
 
79
82
  it "adds a 'From ' line at the start" do
@@ -98,7 +101,7 @@ Subject: Re: no subject|
98
101
  end
99
102
  end
100
103
 
101
- context "#from" do
104
+ describe "From" do
102
105
  before do
103
106
  # call original for these tests because we want to test the behaviour of
104
107
  # class-under-test given different behaviour of the Mail parser
@@ -113,7 +116,7 @@ Subject: Re: no subject|
113
116
  end
114
117
  end
115
118
 
116
- context "when original message 'from' is a string but not well-formed address" do
119
+ context "when original message 'from' is not a well-formed address" do
117
120
  let(:message_body) { msg_bad_from }
118
121
 
119
122
  it "'from' is empty string" do
@@ -126,7 +129,7 @@ Subject: Re: no subject|
126
129
  let(:message_body) { msg_no_from_but_return_path }
127
130
 
128
131
  it "'return path' is used as 'from'" do
129
- expect(subject.to_serialized).to start_with("From " + from + "\n")
132
+ expect(subject.to_serialized).to start_with("From #{from}\n")
130
133
  end
131
134
  end
132
135
 
@@ -134,12 +137,12 @@ Subject: Re: no subject|
134
137
  let(:message_body) { msg_no_from_but_sender }
135
138
 
136
139
  it "Sender is used as 'from'" do
137
- expect(subject.to_serialized).to start_with("From " + from + "\n")
140
+ expect(subject.to_serialized).to start_with("From #{from}\n")
138
141
  end
139
142
  end
140
143
  end
141
144
 
142
- context "#date" do
145
+ describe "#date" do
143
146
  let(:message_body) { msg_good }
144
147
 
145
148
  it "returns the date" do
@@ -154,4 +157,21 @@ Subject: Re: no subject|
154
157
  end
155
158
  end
156
159
  end
160
+
161
+ describe "#imap_body" do
162
+ let(:message_body) { "Ciao" }
163
+
164
+ it "returns the supplied body" do
165
+ expect(subject.imap_body).to eq(message_body)
166
+ end
167
+
168
+ context "when newlines are not IMAP standard" do
169
+ let(:message_body) { "Ciao\nHello" }
170
+ let(:corrected) { "Ciao\r\nHello" }
171
+
172
+ it "corrects them" do
173
+ expect(subject.imap_body).to eq(corrected)
174
+ end
175
+ end
176
+ end
157
177
  end
@@ -1,8 +1,8 @@
1
- require "spec_helper"
2
-
3
1
  describe Email::Provider do
2
+ subject { described_class.new(:gmail) }
3
+
4
4
  describe ".for_address" do
5
- context "known providers" do
5
+ context "with known providers" do
6
6
  [
7
7
  ["gmail.com", :gmail],
8
8
  ["fastmail.fm", :fastmail]
@@ -22,8 +22,6 @@ describe Email::Provider do
22
22
  end
23
23
  end
24
24
 
25
- subject { described_class.new(:gmail) }
26
-
27
25
  describe "#options" do
28
26
  it "returns options" do
29
27
  expect(subject.options).to be_a(Hash)
@@ -1,5 +1,3 @@
1
- require "spec_helper"
2
-
3
1
  describe Imap::Backup::Account::Connection do
4
2
  def self.backup_folder
5
3
  "backup_folder"
@@ -9,6 +7,8 @@ describe Imap::Backup::Account::Connection do
9
7
  {name: backup_folder}
10
8
  end
11
9
 
10
+ subject { described_class.new(options) }
11
+
12
12
  let(:imap) do
13
13
  instance_double(Net::IMAP, login: nil, disconnect: nil)
14
14
  end
@@ -18,7 +18,7 @@ describe Imap::Backup::Account::Connection do
18
18
  username: username,
19
19
  password: "password",
20
20
  local_path: local_path,
21
- folders: backup_folders,
21
+ folders: backup_folders
22
22
  }
23
23
  end
24
24
  let(:local_path) { "local_path" }
@@ -33,7 +33,7 @@ describe Imap::Backup::Account::Connection do
33
33
  Imap::Backup::Serializer::Mbox,
34
34
  folder: serialized_folder,
35
35
  force_uid_validity: nil,
36
- set_uid_validity: new_uid_validity,
36
+ apply_uid_validity: new_uid_validity,
37
37
  uids: [local_uid]
38
38
  )
39
39
  end
@@ -48,19 +48,13 @@ describe Imap::Backup::Account::Connection do
48
48
  allow(Imap::Backup::Utils).to receive(:make_folder)
49
49
  end
50
50
 
51
- subject { described_class.new(options) }
52
-
53
51
  shared_examples "connects to IMAP" do
54
- it "sets up the IMAP connection" do
55
- expect(Net::IMAP).to have_received(:new)
56
- end
57
-
58
52
  it "logs in to the imap server" do
59
53
  expect(imap).to have_received(:login)
60
54
  end
61
55
  end
62
56
 
63
- context "#initialize" do
57
+ describe "#initialize" do
64
58
  [
65
59
  [:username, "username@gmail.com"],
66
60
  [:local_path, "local_path"],
@@ -72,22 +66,23 @@ describe Imap::Backup::Account::Connection do
72
66
  end
73
67
 
74
68
  it "creates the path" do
69
+ expect(Imap::Backup::Utils).to receive(:make_folder)
70
+
75
71
  subject.username
76
- expect(Imap::Backup::Utils).to have_received(:make_folder)
77
72
  end
78
73
  end
79
74
 
80
75
  describe "#imap" do
81
- before { @result = subject.imap }
76
+ let!(:result) { subject.imap }
82
77
 
83
78
  it "returns the IMAP connection" do
84
- expect(@result).to eq(imap)
79
+ expect(result).to eq(imap)
85
80
  end
86
81
 
87
82
  include_examples "connects to IMAP"
88
83
  end
89
84
 
90
- context "#folders" do
85
+ describe "#folders" do
91
86
  let(:imap_folders) do
92
87
  [instance_double(Net::IMAP::MailboxList)]
93
88
  end
@@ -97,18 +92,18 @@ describe Imap::Backup::Account::Connection do
97
92
  end
98
93
  end
99
94
 
100
- context "#status" do
95
+ describe "#status" do
101
96
  let(:folder) do
102
97
  instance_double(Imap::Backup::Account::Folder, uids: [remote_uid])
103
98
  end
104
99
  let(:remote_uid) { "remote_uid" }
105
100
 
106
101
  before do
107
- allow(Imap::Backup::Account::Folder).to receive(:new).and_return(folder)
102
+ allow(Imap::Backup::Account::Folder).to receive(:new) { folder }
108
103
  allow(Imap::Backup::Serializer::Mbox).to receive(:new) { serializer }
109
104
  end
110
105
 
111
- it "should return the names of folders" do
106
+ it "returns the names of folders" do
112
107
  expect(subject.status[0][:name]).to eq(self.class.backup_folder)
113
108
  end
114
109
 
@@ -116,19 +111,21 @@ describe Imap::Backup::Account::Connection do
116
111
  expect(subject.status[0][:local]).to eq([local_uid])
117
112
  end
118
113
 
119
- it "should retrieve the available uids" do
114
+ it "retrieves the available uids" do
120
115
  expect(subject.status[0][:remote]).to eq([remote_uid])
121
116
  end
122
117
  end
123
118
 
124
- context "#run_backup" do
119
+ describe "#run_backup" do
125
120
  let(:folder) do
126
121
  instance_double(
127
122
  Imap::Backup::Account::Folder,
128
123
  name: "folder",
124
+ exist?: exists,
129
125
  uid_validity: uid_validity
130
126
  )
131
127
  end
128
+ let(:exists) { true }
132
129
  let(:uid_validity) { 123 }
133
130
  let(:downloader) { instance_double(Imap::Backup::Downloader, run: nil) }
134
131
 
@@ -140,15 +137,25 @@ describe Imap::Backup::Account::Connection do
140
137
  context "with supplied backup_folders" do
141
138
  before do
142
139
  allow(Imap::Backup::Account::Folder).to receive(:new).
143
- with(subject, self.class.backup_folder).and_return(folder)
140
+ with(subject, self.class.backup_folder) { folder }
144
141
  allow(Imap::Backup::Serializer::Mbox).to receive(:new).
145
- with(local_path, self.class.backup_folder).and_return(serializer)
142
+ with(local_path, self.class.backup_folder) { serializer }
146
143
  end
147
144
 
148
- before { subject.run_backup }
149
-
150
145
  it "runs the downloader" do
151
- expect(downloader).to have_received(:run)
146
+ expect(downloader).to receive(:run)
147
+
148
+ subject.run_backup
149
+ end
150
+
151
+ context "when a folder does not exist" do
152
+ let(:exists) { false }
153
+
154
+ it "does not run the downloader" do
155
+ expect(downloader).to_not receive(:run)
156
+
157
+ subject.run_backup
158
+ end
152
159
  end
153
160
  end
154
161
 
@@ -159,28 +166,28 @@ describe Imap::Backup::Account::Connection do
159
166
 
160
167
  before do
161
168
  allow(Imap::Backup::Account::Folder).to receive(:new).
162
- with(subject, "foo").and_return(folder)
169
+ with(subject, "foo") { folder }
163
170
  allow(Imap::Backup::Serializer::Mbox).to receive(:new).
164
- with(local_path, "foo").and_return(serializer)
171
+ with(local_path, "foo") { serializer }
165
172
  end
166
173
 
167
174
  context "when supplied backup_folders is nil" do
168
175
  let(:backup_folders) { nil }
169
176
 
170
- before { subject.run_backup }
171
-
172
177
  it "runs the downloader for each folder" do
173
- expect(downloader).to have_received(:run).exactly(:once)
178
+ expect(downloader).to receive(:run).exactly(:once)
179
+
180
+ subject.run_backup
174
181
  end
175
182
  end
176
183
 
177
184
  context "when supplied backup_folders is an empty list" do
178
185
  let(:backup_folders) { [] }
179
186
 
180
- before { subject.run_backup }
181
-
182
187
  it "runs the downloader for each folder" do
183
- expect(downloader).to have_received(:run).exactly(:once)
188
+ expect(downloader).to receive(:run).exactly(:once)
189
+
190
+ subject.run_backup
184
191
  end
185
192
  end
186
193
 
@@ -195,17 +202,17 @@ describe Imap::Backup::Account::Connection do
195
202
  end
196
203
  end
197
204
 
198
- context "#restore" do
205
+ describe "#restore" do
199
206
  let(:folder) do
200
207
  instance_double(
201
208
  Imap::Backup::Account::Folder,
202
209
  create: nil,
203
- exist?: exists,
210
+ uids: uids,
204
211
  name: "my_folder",
205
212
  uid_validity: uid_validity
206
213
  )
207
214
  end
208
- let(:exists) { true }
215
+ let(:uids) { [99] }
209
216
  let(:uid_validity) { 123 }
210
217
  let(:serialized_folder) { "old name" }
211
218
  let(:uploader) do
@@ -242,73 +249,89 @@ describe Imap::Backup::Account::Connection do
242
249
  with(updated_folder, updated_serializer) { updated_uploader }
243
250
  allow(Pathname).to receive(:glob).
244
251
  and_yield(Pathname.new(File.join(local_path, "my_folder.imap")))
245
- subject.restore
246
252
  end
247
253
 
248
254
  it "sets local uid validity" do
249
- expect(serializer).to have_received(:set_uid_validity).with(uid_validity)
255
+ expect(serializer).to receive(:apply_uid_validity).with(uid_validity)
256
+
257
+ subject.restore
250
258
  end
251
259
 
252
- context "when folders exist" do
260
+ context "when folders exist with contents" do
253
261
  context "when the local folder is renamed" do
254
262
  let(:new_uid_validity) { "new name" }
255
263
 
256
264
  it "creates the new folder" do
257
- expect(updated_folder).to have_received(:create)
265
+ expect(updated_folder).to receive(:create)
266
+
267
+ subject.restore
258
268
  end
259
269
 
260
270
  it "sets the renamed folder's uid validity" do
261
271
  expect(updated_serializer).
262
- to have_received(:force_uid_validity).with("new uid validity")
272
+ to receive(:force_uid_validity).with("new uid validity")
273
+
274
+ subject.restore
263
275
  end
264
276
 
265
277
  it "creates the uploader with updated folder and serializer" do
266
- expect(updated_uploader).to have_received(:run)
278
+ expect(updated_uploader).to receive(:run)
279
+
280
+ subject.restore
267
281
  end
268
282
  end
269
283
 
270
284
  context "when the local folder is not renamed" do
271
285
  it "runs the uploader" do
272
- expect(uploader).to have_received(:run)
286
+ expect(uploader).to receive(:run)
287
+
288
+ subject.restore
273
289
  end
274
290
  end
275
291
  end
276
292
 
277
- context "when folders don't exist" do
278
- let(:exists) { false }
293
+ context "when folders don't exist or are empty" do
294
+ let(:uids) { [] }
279
295
 
280
296
  it "creates the folder" do
281
- expect(folder).to have_received(:create)
297
+ expect(folder).to receive(:create)
298
+
299
+ subject.restore
282
300
  end
283
301
 
284
- it "sets local uid validity" do
302
+ it "forces local uid validity" do
303
+ expect(serializer).to receive(:force_uid_validity).with(uid_validity)
304
+
305
+ subject.restore
285
306
  end
286
307
 
287
308
  it "runs the uploader" do
288
- expect(uploader).to have_received(:run)
309
+ expect(uploader).to receive(:run)
310
+
311
+ subject.restore
289
312
  end
290
313
  end
291
314
  end
292
315
 
293
- context "#reconnect" do
294
- before { subject.reconnect }
295
-
316
+ describe "#reconnect" do
296
317
  it "disconnects from the server" do
297
- expect(imap).to have_received(:disconnect)
318
+ expect(imap).to receive(:disconnect)
319
+
320
+ subject.reconnect
298
321
  end
299
322
 
300
323
  it "causes reconnection on future access" do
301
- allow(Net::IMAP).to receive(:new) { imap }
302
- subject.imap
303
- expect(Net::IMAP).to have_received(:new).twice
324
+ expect(Net::IMAP).to receive(:new)
325
+
326
+ subject.reconnect
304
327
  end
305
328
  end
306
329
 
307
- context "#disconnect" do
308
- before { subject.disconnect }
309
-
330
+ describe "#disconnect" do
310
331
  it "disconnects from the server" do
311
- expect(imap).to have_received(:disconnect)
332
+ expect(imap).to receive(:disconnect)
333
+
334
+ subject.disconnect
312
335
  end
313
336
  end
314
337
  end