imap-backup 5.2.0 → 6.0.1

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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -2
  3. data/docs/development.md +10 -4
  4. data/imap-backup.gemspec +5 -1
  5. data/lib/cli_coverage.rb +11 -11
  6. data/lib/email/provider/base.rb +2 -0
  7. data/lib/email/provider/unknown.rb +2 -0
  8. data/lib/email/provider.rb +2 -0
  9. data/lib/imap/backup/account/connection/backup_folders.rb +27 -0
  10. data/lib/imap/backup/account/connection/client_factory.rb +54 -0
  11. data/lib/imap/backup/account/connection/folder_names.rb +26 -0
  12. data/lib/imap/backup/account/connection.rb +17 -105
  13. data/lib/imap/backup/account/folder.rb +9 -6
  14. data/lib/imap/backup/account.rb +36 -16
  15. data/lib/imap/backup/cli/backup.rb +1 -3
  16. data/lib/imap/backup/cli/folders.rb +3 -3
  17. data/lib/imap/backup/cli/helpers.rb +24 -22
  18. data/lib/imap/backup/cli/local.rb +20 -13
  19. data/lib/imap/backup/cli/migrate.rb +5 -11
  20. data/lib/imap/backup/cli/restore.rb +8 -7
  21. data/lib/imap/backup/cli/setup.rb +10 -8
  22. data/lib/imap/backup/cli/stats.rb +78 -0
  23. data/lib/imap/backup/cli/status.rb +2 -2
  24. data/lib/imap/backup/cli/utils.rb +6 -8
  25. data/lib/imap/backup/cli.rb +24 -3
  26. data/lib/imap/backup/configuration.rb +9 -21
  27. data/lib/imap/backup/downloader.rb +56 -34
  28. data/lib/imap/backup/migrator.rb +5 -5
  29. data/lib/imap/backup/sanitizer.rb +3 -2
  30. data/lib/imap/backup/serializer/appender.rb +49 -0
  31. data/lib/imap/backup/serializer/directory.rb +37 -0
  32. data/lib/imap/backup/serializer/imap.rb +144 -0
  33. data/lib/imap/backup/serializer/mbox.rb +33 -88
  34. data/lib/imap/backup/serializer/mbox_enumerator.rb +2 -0
  35. data/lib/imap/backup/serializer/message_enumerator.rb +29 -0
  36. data/lib/imap/backup/serializer/unused_name_finder.rb +25 -0
  37. data/lib/imap/backup/serializer.rb +160 -3
  38. data/lib/imap/backup/setup/account/header.rb +75 -0
  39. data/lib/imap/backup/setup/account.rb +41 -95
  40. data/lib/imap/backup/setup/asker.rb +4 -15
  41. data/lib/imap/backup/setup/backup_path.rb +41 -0
  42. data/lib/imap/backup/setup/email.rb +45 -0
  43. data/lib/imap/backup/setup/folder_chooser.rb +3 -3
  44. data/lib/imap/backup/setup/helpers.rb +2 -2
  45. data/lib/imap/backup/setup.rb +5 -4
  46. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +41 -22
  47. data/lib/imap/backup/uploader.rb +46 -8
  48. data/lib/imap/backup/utils.rb +1 -1
  49. data/lib/imap/backup/version.rb +3 -3
  50. data/lib/imap/backup.rb +0 -2
  51. metadata +31 -105
  52. data/lib/imap/backup/serializer/mbox_store.rb +0 -217
  53. data/spec/features/backup_spec.rb +0 -108
  54. data/spec/features/configuration/minimal_configuration.rb +0 -15
  55. data/spec/features/configuration/missing_configuration.rb +0 -14
  56. data/spec/features/folders_spec.rb +0 -36
  57. data/spec/features/helper.rb +0 -2
  58. data/spec/features/local/list_accounts_spec.rb +0 -12
  59. data/spec/features/local/list_emails_spec.rb +0 -21
  60. data/spec/features/local/list_folders_spec.rb +0 -21
  61. data/spec/features/local/show_an_email_spec.rb +0 -34
  62. data/spec/features/migrate_spec.rb +0 -35
  63. data/spec/features/remote/list_account_folders_spec.rb +0 -16
  64. data/spec/features/restore_spec.rb +0 -162
  65. data/spec/features/status_spec.rb +0 -43
  66. data/spec/features/support/aruba.rb +0 -77
  67. data/spec/features/support/backup_directory.rb +0 -43
  68. data/spec/features/support/email_server.rb +0 -110
  69. data/spec/features/support/shared/connection_context.rb +0 -14
  70. data/spec/features/support/shared/message_fixtures.rb +0 -16
  71. data/spec/fixtures/connection.yml +0 -7
  72. data/spec/spec_helper.rb +0 -15
  73. data/spec/support/fixtures.rb +0 -11
  74. data/spec/support/higline_test_helpers.rb +0 -8
  75. data/spec/support/silence_logging.rb +0 -7
  76. data/spec/unit/email/mboxrd/message_spec.rb +0 -177
  77. data/spec/unit/email/provider/apple_mail_spec.rb +0 -7
  78. data/spec/unit/email/provider/base_spec.rb +0 -11
  79. data/spec/unit/email/provider/fastmail_spec.rb +0 -7
  80. data/spec/unit/email/provider/gmail_spec.rb +0 -7
  81. data/spec/unit/email/provider_spec.rb +0 -27
  82. data/spec/unit/imap/backup/account/connection_spec.rb +0 -405
  83. data/spec/unit/imap/backup/account/folder_spec.rb +0 -251
  84. data/spec/unit/imap/backup/cli/accounts_spec.rb +0 -47
  85. data/spec/unit/imap/backup/cli/helpers_spec.rb +0 -87
  86. data/spec/unit/imap/backup/cli/local_spec.rb +0 -81
  87. data/spec/unit/imap/backup/cli/utils_spec.rb +0 -62
  88. data/spec/unit/imap/backup/client/default_spec.rb +0 -22
  89. data/spec/unit/imap/backup/configuration_spec.rb +0 -238
  90. data/spec/unit/imap/backup/downloader_spec.rb +0 -44
  91. data/spec/unit/imap/backup/logger_spec.rb +0 -48
  92. data/spec/unit/imap/backup/migrator_spec.rb +0 -58
  93. data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +0 -45
  94. data/spec/unit/imap/backup/serializer/mbox_spec.rb +0 -222
  95. data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +0 -329
  96. data/spec/unit/imap/backup/setup/account_spec.rb +0 -366
  97. data/spec/unit/imap/backup/setup/asker_spec.rb +0 -137
  98. data/spec/unit/imap/backup/setup/connection_tester_spec.rb +0 -51
  99. data/spec/unit/imap/backup/setup/folder_chooser_spec.rb +0 -146
  100. data/spec/unit/imap/backup/setup_spec.rb +0 -301
  101. data/spec/unit/imap/backup/uploader_spec.rb +0 -54
  102. data/spec/unit/imap/backup/utils_spec.rb +0 -92
@@ -1,137 +0,0 @@
1
- module Imap::Backup
2
- describe Setup::Asker do
3
- subject { described_class.new(highline) }
4
-
5
- let(:highline) { double }
6
- let(:query) do
7
- instance_double(
8
- HighLine::Question,
9
- "default=": nil,
10
- "readline=": nil,
11
- "validate=": nil,
12
- "responses": {},
13
- "echo=": nil
14
- )
15
- end
16
- let(:answer) { "foo" }
17
-
18
- before do
19
- allow(Setup).to receive(:highline) { highline }
20
- allow(highline).to receive(:ask) do |&b|
21
- b.call query
22
- answer
23
- end
24
- end
25
-
26
- [
27
- [:email, [], "email address"],
28
- [:password, [], "password"],
29
- [:backup_path, %w(x y), "backup directory"]
30
- ].each do |method, params, prompt|
31
- context ".#{method}" do
32
- it "asks for input" do
33
- expect(highline).to receive(:ask).with("#{prompt}: ")
34
-
35
- described_class.send(method, *params)
36
- end
37
-
38
- it "returns the answer" do
39
- expect(described_class.send(method, *params)).to eq(answer)
40
- end
41
- end
42
- end
43
-
44
- describe "#initialize" do
45
- it "requires 1 parameter" do
46
- expect do
47
- described_class.new
48
- end.to raise_error(ArgumentError, /wrong number/)
49
- end
50
-
51
- it "expects a higline" do
52
- expect(subject.highline).to eq(highline)
53
- end
54
- end
55
-
56
- describe "#email" do
57
- let(:email) { "email@example.com" }
58
- let(:answer) { email }
59
-
60
- it "asks for an email" do
61
- expect(highline).to receive(:ask).with(/email/)
62
-
63
- subject.email
64
- end
65
-
66
- it "returns the address" do
67
- expect(subject.email).to eq(email)
68
- end
69
- end
70
-
71
- describe "#password" do
72
- let(:password1) { "password" }
73
- let(:password2) { "password" }
74
- let(:answers) { [true, false] }
75
-
76
- before do
77
- i = 0
78
- allow(highline).to receive(:ask).with("password: ") { password1 }
79
- allow(highline).to receive(:ask).with("repeat password: ") { password2 }
80
- allow(highline).to receive(:agree) do
81
- answer = answers[i]
82
- i += 1
83
- answer
84
- end
85
- end
86
-
87
- it "asks for a password" do
88
- expect(highline).to receive(:ask).with("password: ")
89
-
90
- subject.password
91
- end
92
-
93
- it "asks for confirmation" do
94
- expect(highline).to receive(:ask).with("repeat password: ")
95
-
96
- subject.password
97
- end
98
-
99
- it "returns the password" do
100
- expect(subject.password).to eq(password1)
101
- end
102
-
103
- context "with different answers" do
104
- let(:password2) { "secret" }
105
-
106
- it "asks to continue" do
107
- expect(highline).to receive(:agree).
108
- at_least(:once).with(/Continue\?/)
109
-
110
- subject.password
111
- end
112
- end
113
- end
114
-
115
- describe "#backup_path" do
116
- let(:path) { "/path" }
117
- let(:answer) { path }
118
-
119
- before do
120
- allow(highline).to receive(:ask) do |&b|
121
- b.call query
122
- path
123
- end
124
- end
125
-
126
- it "asks for a directory" do
127
- expect(highline).to receive(:ask).with(/directory/)
128
-
129
- subject.backup_path("", //)
130
- end
131
-
132
- it "returns the path" do
133
- expect(subject.backup_path("", //)).to eq(path)
134
- end
135
- end
136
- end
137
- end
@@ -1,51 +0,0 @@
1
- describe Imap::Backup::Setup::ConnectionTester do
2
- describe "#test" do
3
- subject { described_class.new("foo") }
4
-
5
- let(:connection) do
6
- instance_double(Imap::Backup::Account::Connection, client: nil)
7
- end
8
-
9
- before do
10
- allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
11
- end
12
-
13
- it "tries to connect" do
14
- expect(connection).to receive(:client)
15
-
16
- subject.test
17
- end
18
-
19
- describe "success" do
20
- it "returns success" do
21
- expect(subject.test).to match(/successful/)
22
- end
23
- end
24
-
25
- describe "failure" do
26
- before do
27
- allow(connection).to receive(:client).and_raise(error)
28
- end
29
-
30
- context "with no connection" do
31
- let(:error) do
32
- data = OpenStruct.new(text: "bar")
33
- response = OpenStruct.new(data: data)
34
- Net::IMAP::NoResponseError.new(response)
35
- end
36
-
37
- it "returns error" do
38
- expect(subject.test).to match(/no response/i)
39
- end
40
- end
41
-
42
- context "when caused by other errors" do
43
- let(:error) { "Error" }
44
-
45
- it "returns error" do
46
- expect(subject.test).to match(/unexpected error/i)
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,146 +0,0 @@
1
- describe Imap::Backup::Setup::FolderChooser do
2
- include HighLineTestHelpers
3
-
4
- describe "#run" do
5
- subject { described_class.new(account) }
6
-
7
- let(:connection) do
8
- instance_double(
9
- Imap::Backup::Account::Connection, folder_names: connection_folders
10
- )
11
- end
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) { [] }
20
- let(:connection_folders) { [] }
21
- let!(:highline_streams) { prepare_highline }
22
- let(:input) { highline_streams[0] }
23
- let(:output) { highline_streams[1] }
24
-
25
- before do
26
- allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
27
- allow(Kernel).to receive(:system)
28
- allow(Imap::Backup::Logger.logger).to receive(:warn)
29
- end
30
-
31
- describe "display" do
32
- it "clears the screen" do
33
- expect(Kernel).to receive(:system).with("clear")
34
-
35
- subject.run
36
- end
37
-
38
- it "shows the menu" do
39
- subject.run
40
-
41
- expect(output.string).to match %r{Add/remove folders}
42
- end
43
- end
44
-
45
- describe "folder listing" do
46
- let(:account_folders) { [{name: "my_folder"}]}
47
- let(:connection_folders) do
48
- # N.B. my_folder is already backed up
49
- %w(my_folder another_folder)
50
- end
51
-
52
- describe "display" do
53
- before { subject.run }
54
-
55
- it "shows folders which are being backed up" do
56
- expect(output.string).to include("+ my_folder")
57
- end
58
-
59
- it "shows folders which are not being backed up" do
60
- expect(output.string).to include("- another_folder")
61
- end
62
- end
63
-
64
- context "when adding folders" do
65
- before do
66
- allow(input).to receive(:gets).and_return("2\n", "q\n")
67
-
68
- subject.run
69
- end
70
-
71
- specify "are added to the account" do
72
- expect(account).to have_received(:"folders=").
73
- with([{name: "my_folder"}, {name: "another_folder"}])
74
- end
75
- end
76
-
77
- context "when removing folders" do
78
- before do
79
- allow(input).to receive(:gets).and_return("1\n", "q\n")
80
-
81
- subject.run
82
- end
83
-
84
- specify "are removed from the account" do
85
- expect(account).to have_received(:"folders=").with([])
86
- end
87
- end
88
- end
89
-
90
- context "with missing remote folders" do
91
- let(:account_folders) do
92
- [{name: "on_server"}, {name: "not_on_server"}]
93
- end
94
- let(:connection_folders) { ["on_server"] }
95
-
96
- before do
97
- allow(Kernel).to receive(:puts)
98
- subject.run
99
- end
100
-
101
- specify "are removed from the account" do
102
- expect(account).to have_received(:"folders=").
103
- with([{name: "on_server"}])
104
- end
105
- end
106
-
107
- context "when folders are not available" do
108
- let(:connection_folders) { nil }
109
-
110
- before do
111
- allow(Imap::Backup::Setup.highline).
112
- to receive(:ask) { "q" }
113
- end
114
-
115
- it "asks to press a key" do
116
- expect(Imap::Backup::Setup.highline).
117
- to receive(:ask).with("Press a key ")
118
-
119
- subject.run
120
- end
121
- end
122
-
123
- context "with connection errors" do
124
- before do
125
- allow(Imap::Backup::Account::Connection).
126
- to receive(:new).with(account).and_raise("error")
127
- allow(Imap::Backup::Setup.highline).
128
- to receive(:ask) { "q" }
129
- end
130
-
131
- it "prints an error message" do
132
- expect(Imap::Backup::Logger.logger).
133
- to receive(:warn).with("Connection failed")
134
-
135
- subject.run
136
- end
137
-
138
- it "asks to continue" do
139
- expect(Imap::Backup::Setup.highline).
140
- to receive(:ask).with("Press a key ")
141
-
142
- subject.run
143
- end
144
- end
145
- end
146
- end
@@ -1,301 +0,0 @@
1
- describe Imap::Backup::Setup do
2
- include HighLineTestHelpers
3
-
4
- subject { described_class.new }
5
-
6
- let(:normal_account) do
7
- instance_double(
8
- Imap::Backup::Account,
9
- username: "account@example.com",
10
- marked_for_deletion?: false,
11
- modified?: false
12
- )
13
- end
14
- let(:modified_account) do
15
- instance_double(
16
- Imap::Backup::Account,
17
- username: "modified@example.com",
18
- marked_for_deletion?: false,
19
- modified?: true
20
- )
21
- end
22
- let(:deleted_account) do
23
- instance_double(
24
- Imap::Backup::Account,
25
- username: "delete@example.com",
26
- marked_for_deletion?: true,
27
- modified?: false
28
- )
29
- end
30
- let(:accounts) { [normal_account] }
31
- let(:store) do
32
- instance_double(
33
- Imap::Backup::Configuration,
34
- "accounts": accounts,
35
- "path": "/base/path",
36
- "save": nil,
37
- "debug?": debug,
38
- "debug=": nil,
39
- "modified?": config_modified
40
- )
41
- end
42
- let(:debug) { false }
43
- let(:config_modified) { false }
44
- let!(:highline_streams) { prepare_highline }
45
- let(:input) { highline_streams[0] }
46
- let(:output) { highline_streams[1] }
47
- let(:gmail_imap_server) { "imap.gmail.com" }
48
-
49
- describe "#initialize" do
50
- context "without a config file" do
51
- it "works" do
52
- described_class.new
53
- end
54
- end
55
- end
56
-
57
- describe "#run" do
58
- before do
59
- allow(Imap::Backup::Configuration).to receive(:new) { store }
60
- allow(Imap::Backup::Logger).to receive(:setup_logging)
61
- allow(input).to receive(:eof?) { false }
62
- allow(input).to receive(:gets) { "q\n" }
63
- allow(Kernel).to receive(:system)
64
- end
65
-
66
- describe "main menu" do
67
- context "when changes have not been made" do
68
- before { subject.run }
69
-
70
- ["add account", "quit"].each do |choice|
71
- it "includes #{choice}" do
72
- expect(output.string).to include(choice)
73
- end
74
- end
75
- end
76
-
77
- context "when changes have been made" do
78
- let(:config_modified) { true }
79
-
80
- before do
81
- allow(input).to receive(:gets) { "exit\n" }
82
- subject.run
83
- end
84
-
85
- ["save and exit", "exit without saving"].each do |choice|
86
- it "includes '#{choice}'" do
87
- expect(output.string).to include(choice)
88
- end
89
- end
90
- end
91
- end
92
-
93
- it "clears the screen" do
94
- expect(Kernel).to receive(:system).with("clear")
95
-
96
- subject.run
97
- end
98
-
99
- describe "listing" do
100
- let(:accounts) { [normal_account, modified_account, deleted_account] }
101
-
102
- before { subject.run }
103
-
104
- describe "normal accounts" do
105
- it "are listed" do
106
- expect(output.string).to match(/account@example.com/)
107
- end
108
- end
109
-
110
- describe "modified accounts" do
111
- it "are flagged" do
112
- expect(output.string).to match(/modified@example.com \*/)
113
- end
114
- end
115
-
116
- describe "deleted accounts" do
117
- it "are hidden" do
118
- expect(output.string).to_not match(/delete@example.com/)
119
- end
120
- end
121
- end
122
-
123
- context "when editing accounts" do
124
- let(:account) do
125
- instance_double(Imap::Backup::Setup::Account, run: nil)
126
- end
127
- let(:config_modified) { true }
128
-
129
- before do
130
- allow(input).to receive(:gets).and_return("1\n", "exit\n")
131
- allow(Imap::Backup::Setup::Asker).to receive(:email).
132
- with(no_args) { "new@example.com" }
133
- allow(Imap::Backup::Setup::Account).to receive(:new).
134
- with(store, normal_account, anything) { account }
135
- end
136
-
137
- it "edits the account" do
138
- expect(account).to receive(:run)
139
-
140
- subject.run
141
- end
142
- end
143
-
144
- context "when adding accounts" do
145
- let(:blank_account) do
146
- {
147
- username: added_email,
148
- password: "",
149
- local_path: local_path,
150
- folders: []
151
- }
152
- end
153
- let(:account) do
154
- instance_double(Imap::Backup::Setup::Account, run: nil)
155
- end
156
- let(:config_modified) { true }
157
- let(:added_email) { "new@example.com" }
158
- let(:local_path) { "/base/path/new_example.com" }
159
-
160
- before do
161
- allow(input).to receive(:gets).and_return("add\n", "exit\n")
162
- allow(Imap::Backup::Setup::Asker).to receive(:email).
163
- with(no_args) { added_email }
164
- allow(Imap::Backup::Setup::Account).to receive(:new).
165
- with(store, anything, anything) { account }
166
-
167
- subject.run
168
- end
169
-
170
- it "sets username" do
171
- expect(accounts[1].username).to eq(added_email)
172
- end
173
-
174
- it "sets blank password" do
175
- expect(accounts[1].password).to eq("")
176
- end
177
-
178
- it "sets local_path" do
179
- expect(accounts[1].local_path).to eq(local_path)
180
- end
181
-
182
- it "sets folders" do
183
- expect(accounts[1].folders).to eq([])
184
- end
185
-
186
- context "when the account is a GMail account" do
187
- let(:added_email) { "new@gmail.com" }
188
- let(:local_path) { "/base/path/new_gmail.com" }
189
-
190
- it "sets the server" do
191
- expect(accounts[1].server).to eq(gmail_imap_server)
192
- end
193
- end
194
-
195
- it "doesn't flag the unedited account as modified" do
196
- expect(accounts[1].modified?).to be_falsey
197
- end
198
- end
199
-
200
- describe "logging" do
201
- context "when debug logging is disabled" do
202
- let(:config_modified) { true }
203
-
204
- before do
205
- allow(input).to receive(:gets).and_return("start\n", "exit\n")
206
- end
207
-
208
- it "shows a menu item" do
209
- subject.run
210
-
211
- expect(output.string).to include("start logging")
212
- end
213
-
214
- context "when selected" do
215
- it "sets the debug flag" do
216
- expect(store).to receive(:debug=).with(true)
217
-
218
- subject.run
219
- end
220
-
221
- it "updates logging status" do
222
- expect(Imap::Backup::Logger).to receive(:setup_logging)
223
-
224
- subject.run
225
- end
226
- end
227
- end
228
-
229
- context "when debug logging is enabled" do
230
- let(:debug) { true }
231
- let(:config_modified) { true }
232
-
233
- before do
234
- allow(input).to receive(:gets).and_return("stop\n", "exit\n")
235
- end
236
-
237
- it "shows a menu item" do
238
- subject.run
239
-
240
- expect(output.string).to include("stop logging")
241
- end
242
-
243
- context "when selected" do
244
- before do
245
- allow(input).to receive(:gets).and_return("stop\n", "exit\n")
246
- end
247
-
248
- it "unsets the debug flag" do
249
- expect(store).to receive(:debug=).with(false)
250
-
251
- subject.run
252
- end
253
-
254
- it "updates logging status" do
255
- expect(Imap::Backup::Logger).to receive(:setup_logging)
256
-
257
- subject.run
258
- end
259
- end
260
- end
261
- end
262
-
263
- context "when 'save' is selected" do
264
- let(:config_modified) { true }
265
-
266
- before do
267
- allow(input).to receive(:gets) { "save\n" }
268
- end
269
-
270
- it "exits" do
271
- # N.B. this will hang forever if save does not cause an exit
272
- subject.run
273
- end
274
-
275
- it "saves the configuration" do
276
- expect(store).to receive(:save)
277
-
278
- subject.run
279
- end
280
- end
281
-
282
- context "when 'exit without saving' is selected" do
283
- let(:config_modified) { true }
284
-
285
- before do
286
- allow(input).to receive(:gets) { "exit\n" }
287
- end
288
-
289
- it "exits" do
290
- # N.B. this will hang forever if quit does not cause an exit
291
- subject.run
292
- end
293
-
294
- it "doesn't save the configuration" do
295
- expect(store).to_not receive(:save)
296
-
297
- subject.run
298
- end
299
- end
300
- end
301
- end
@@ -1,54 +0,0 @@
1
- describe Imap::Backup::Uploader do
2
- subject { described_class.new(folder, serializer) }
3
-
4
- let(:folder) do
5
- instance_double(
6
- Imap::Backup::Account::Folder, uids: [2, 3], append: 99, name: "foo"
7
- )
8
- end
9
- let(:serializer) do
10
- instance_double(
11
- Imap::Backup::Serializer::Mbox,
12
- uids: [1, 2],
13
- update_uid: nil
14
- )
15
- end
16
- let(:missing_message) do
17
- instance_double(Email::Mboxrd::Message, supplied_body: "missing message")
18
- end
19
- let(:existing_message) do
20
- instance_double(Email::Mboxrd::Message, supplied_body: "existing message")
21
- end
22
-
23
- def message_enumerator
24
- yield [1, missing_message]
25
- end
26
-
27
- describe "#run" do
28
- before do
29
- allow(serializer).to receive(:each_message).and_return(enum_for(:message_enumerator))
30
- end
31
-
32
- context "with messages that are missing" do
33
- it "restores them" do
34
- expect(folder).to receive(:append).with(missing_message)
35
-
36
- subject.run
37
- end
38
-
39
- it "updates the local message id" do
40
- expect(serializer).to receive(:update_uid).with(1, 99)
41
-
42
- subject.run
43
- end
44
- end
45
-
46
- context "with messages that are present on server" do
47
- it "does nothing" do
48
- expect(folder).to_not receive(:append).with(existing_message)
49
-
50
- subject.run
51
- end
52
- end
53
- end
54
- end