imap-backup 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec-all +2 -0
  3. data/.rubocop.yml +10 -1
  4. data/.travis.yml +1 -0
  5. data/README.md +1 -1
  6. data/Rakefile +0 -1
  7. data/bin/imap-backup +3 -9
  8. data/imap-backup.gemspec +5 -5
  9. data/lib/email/mboxrd/message.rb +2 -2
  10. data/lib/imap/backup/account/connection.rb +11 -3
  11. data/lib/imap/backup/account/folder.rb +11 -6
  12. data/lib/imap/backup/configuration/account.rb +7 -7
  13. data/lib/imap/backup/configuration/asker.rb +2 -1
  14. data/lib/imap/backup/configuration/connection_tester.rb +1 -1
  15. data/lib/imap/backup/configuration/folder_chooser.rb +32 -5
  16. data/lib/imap/backup/configuration/list.rb +2 -0
  17. data/lib/imap/backup/configuration/setup.rb +2 -1
  18. data/lib/imap/backup/configuration/store.rb +3 -6
  19. data/lib/imap/backup/downloader.rb +8 -7
  20. data/lib/imap/backup/serializer/mbox.rb +2 -1
  21. data/lib/imap/backup/serializer/mbox_store.rb +14 -6
  22. data/lib/imap/backup/uploader.rb +1 -0
  23. data/lib/imap/backup/utils.rb +11 -9
  24. data/lib/imap/backup/version.rb +1 -1
  25. data/spec/features/backup_spec.rb +6 -5
  26. data/spec/features/support/backup_directory.rb +5 -5
  27. data/spec/features/support/email_server.rb +11 -8
  28. data/spec/features/support/shared/connection_context.rb +2 -2
  29. data/spec/support/fixtures.rb +1 -1
  30. data/spec/support/higline_test_helpers.rb +1 -1
  31. data/spec/unit/email/mboxrd/message_spec.rb +51 -42
  32. data/spec/unit/email/provider_spec.rb +0 -2
  33. data/spec/unit/imap/backup/account/connection_spec.rb +18 -11
  34. data/spec/unit/imap/backup/account/folder_spec.rb +26 -12
  35. data/spec/unit/imap/backup/configuration/account_spec.rb +22 -19
  36. data/spec/unit/imap/backup/configuration/asker_spec.rb +30 -31
  37. data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +16 -13
  38. data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +45 -18
  39. data/spec/unit/imap/backup/configuration/list_spec.rb +8 -13
  40. data/spec/unit/imap/backup/configuration/setup_spec.rb +36 -30
  41. data/spec/unit/imap/backup/configuration/store_spec.rb +7 -4
  42. data/spec/unit/imap/backup/downloader_spec.rb +11 -7
  43. data/spec/unit/imap/backup/serializer/mbox_spec.rb +2 -5
  44. data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +4 -4
  45. data/spec/unit/imap/backup/uploader_spec.rb +0 -2
  46. data/spec/unit/imap/backup/utils_spec.rb +1 -3
  47. metadata +6 -6
@@ -1,5 +1,3 @@
1
- require "spec_helper"
2
-
3
1
  describe Email::Provider do
4
2
  describe ".for_address" do
5
3
  context "known providers" do
@@ -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" }
@@ -48,8 +48,6 @@ 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
52
  it "sets up the IMAP connection" do
55
53
  expect(Net::IMAP).to have_received(:new)
@@ -78,10 +76,10 @@ describe Imap::Backup::Account::Connection do
78
76
  end
79
77
 
80
78
  describe "#imap" do
81
- before { @result = subject.imap }
79
+ let!(:result) { subject.imap }
82
80
 
83
81
  it "returns the IMAP connection" do
84
- expect(@result).to eq(imap)
82
+ expect(result).to eq(imap)
85
83
  end
86
84
 
87
85
  include_examples "connects to IMAP"
@@ -108,7 +106,7 @@ describe Imap::Backup::Account::Connection do
108
106
  allow(Imap::Backup::Serializer::Mbox).to receive(:new) { serializer }
109
107
  end
110
108
 
111
- it "should return the names of folders" do
109
+ it "returns the names of folders" do
112
110
  expect(subject.status[0][:name]).to eq(self.class.backup_folder)
113
111
  end
114
112
 
@@ -116,7 +114,7 @@ describe Imap::Backup::Account::Connection do
116
114
  expect(subject.status[0][:local]).to eq([local_uid])
117
115
  end
118
116
 
119
- it "should retrieve the available uids" do
117
+ it "retrieves the available uids" do
120
118
  expect(subject.status[0][:remote]).to eq([remote_uid])
121
119
  end
122
120
  end
@@ -126,9 +124,11 @@ describe Imap::Backup::Account::Connection do
126
124
  instance_double(
127
125
  Imap::Backup::Account::Folder,
128
126
  name: "folder",
127
+ exist?: exists,
129
128
  uid_validity: uid_validity
130
129
  )
131
130
  end
131
+ let(:exists) { true }
132
132
  let(:uid_validity) { 123 }
133
133
  let(:downloader) { instance_double(Imap::Backup::Downloader, run: nil) }
134
134
 
@@ -143,13 +143,20 @@ describe Imap::Backup::Account::Connection do
143
143
  with(subject, self.class.backup_folder).and_return(folder)
144
144
  allow(Imap::Backup::Serializer::Mbox).to receive(:new).
145
145
  with(local_path, self.class.backup_folder).and_return(serializer)
146
+ subject.run_backup
146
147
  end
147
148
 
148
- before { subject.run_backup }
149
-
150
149
  it "runs the downloader" do
151
150
  expect(downloader).to have_received(:run)
152
151
  end
152
+
153
+ context "when a folder does not exist" do
154
+ let(:exists) { false }
155
+
156
+ it "does not run the downloader" do
157
+ expect(downloader).to_not have_received(:run)
158
+ end
159
+ end
153
160
  end
154
161
 
155
162
  context "without supplied backup_folders" do
@@ -1,6 +1,8 @@
1
- require "spec_helper"
1
+ # rubocop:disable RSpec/PredicateMatcher
2
2
 
3
3
  describe Imap::Backup::Account::Folder do
4
+ subject { described_class.new(connection, "my_folder") }
5
+
4
6
  let(:imap) do
5
7
  instance_double(
6
8
  Net::IMAP,
@@ -10,21 +12,19 @@ describe Imap::Backup::Account::Folder do
10
12
  responses: responses
11
13
  )
12
14
  end
13
- let(:connection) { double("Imap::Backup::Account::Connection", imap: imap) }
14
- let(:missing_mailbox_data) do
15
- double("Data", text: "Unknown Mailbox: my_folder")
15
+ let(:connection) do
16
+ instance_double(Imap::Backup::Account::Connection, imap: imap)
16
17
  end
17
- let(:missing_mailbox_response) do
18
- double("Response", data: missing_mailbox_data)
18
+ let(:missing_mailbox_data) do
19
+ OpenStruct.new(text: "Unknown Mailbox: my_folder")
19
20
  end
21
+ let(:missing_mailbox_response) { OpenStruct.new(data: missing_mailbox_data) }
20
22
  let(:missing_mailbox_error) do
21
23
  Net::IMAP::NoResponseError.new(missing_mailbox_response)
22
24
  end
23
25
  let(:responses) { [] }
24
26
  let(:append_response) { nil }
25
27
 
26
- subject { described_class.new(connection, "my_folder") }
27
-
28
28
  context "#uids" do
29
29
  let(:uids) { [5678, 123] }
30
30
 
@@ -46,7 +46,7 @@ describe Imap::Backup::Account::Folder do
46
46
  end
47
47
 
48
48
  context "#fetch" do
49
- let(:message_body) { double("the body", force_encoding: nil) }
49
+ let(:message_body) { instance_double(String, force_encoding: nil) }
50
50
  let(:attributes) { {"RFC822" => message_body, "other" => "xxx"} }
51
51
  let(:fetch_data_item) do
52
52
  instance_double(Net::IMAP::FetchData, attr: attributes)
@@ -134,6 +134,18 @@ describe Imap::Backup::Account::Folder do
134
134
  it "is returned" do
135
135
  expect(subject.uid_validity).to eq("uid validity")
136
136
  end
137
+
138
+ context "when the folder doesn't exist" do
139
+ before do
140
+ allow(imap).to receive(:examine).and_raise(missing_mailbox_error)
141
+ end
142
+
143
+ it "raises an error" do
144
+ expect do
145
+ subject.uid_validity
146
+ end.to raise_error(Imap::Backup::FolderNotFound)
147
+ end
148
+ end
137
149
  end
138
150
 
139
151
  context "#append" do
@@ -144,12 +156,12 @@ describe Imap::Backup::Account::Folder do
144
156
  date: Time.now
145
157
  )
146
158
  end
147
- let(:append_response) { "response" }
159
+ let(:append_response) do
160
+ OpenStruct.new(data: OpenStruct.new(code: OpenStruct.new(data: "1 2")))
161
+ end
148
162
  let(:result) { subject.append(message) }
149
163
 
150
164
  before do
151
- allow(append_response).
152
- to receive_message_chain("data.code.data") { "1 2" }
153
165
  result
154
166
  end
155
167
 
@@ -166,3 +178,5 @@ describe Imap::Backup::Account::Folder do
166
178
  end
167
179
  end
168
180
  end
181
+
182
+ # rubocop:enable RSpec/PredicateMatcher
@@ -1,4 +1,4 @@
1
- require "spec_helper"
1
+ # rubocop:disable RSpec/NestedGroups
2
2
 
3
3
  describe Imap::Backup::Configuration::Account do
4
4
  class MockHighlineMenu
@@ -19,12 +19,12 @@ describe Imap::Backup::Configuration::Account do
19
19
  end
20
20
 
21
21
  context "#initialize" do
22
+ subject { described_class.new(store, account, highline) }
23
+
22
24
  let(:store) { "store" }
23
25
  let(:account) { "account" }
24
26
  let(:highline) { "highline" }
25
27
 
26
- subject { described_class.new(store, account, highline) }
27
-
28
28
  [:store, :account, :highline].each do |param|
29
29
  it "expects #{param}" do
30
30
  expect(subject.send(param)).to eq(send(param))
@@ -33,10 +33,12 @@ describe Imap::Backup::Configuration::Account do
33
33
  end
34
34
 
35
35
  context "#run" do
36
- let(:highline) { double("Highline") }
36
+ subject { described_class.new(store, account, highline) }
37
+
38
+ let(:highline) { instance_double(HighLine) }
37
39
  let(:menu) { MockHighlineMenu.new }
38
40
  let(:store) do
39
- double("Imap::Backup::Configuration::Store", accounts: accounts)
41
+ instance_double(Imap::Backup::Configuration::Store, accounts: accounts)
40
42
  end
41
43
  let(:accounts) { [account, account1] }
42
44
  let(:account) do
@@ -45,13 +47,13 @@ describe Imap::Backup::Configuration::Account do
45
47
  server: existing_server,
46
48
  local_path: "/backup/path",
47
49
  folders: [{name: "my_folder"}],
48
- password: existing_password,
50
+ password: existing_password
49
51
  }
50
52
  end
51
53
  let(:account1) do
52
54
  {
53
55
  username: other_email,
54
- local_path: other_existing_path,
56
+ local_path: other_existing_path
55
57
  }
56
58
  end
57
59
  let(:existing_email) { "user@example.com" }
@@ -62,21 +64,19 @@ describe Imap::Backup::Configuration::Account do
62
64
  let(:other_existing_path) { "/other/existing/path" }
63
65
 
64
66
  before do
65
- allow(subject).to receive(:system).and_return(nil)
66
- allow(subject).to receive(:puts).and_return(nil)
67
+ allow(Kernel).to receive(:system)
68
+ allow(Kernel).to receive(:puts)
67
69
  allow(highline).to receive(:choose) do |&block|
68
70
  block.call(menu)
69
71
  throw :done
70
72
  end
71
73
  end
72
74
 
73
- subject { described_class.new(store, account, highline) }
74
-
75
75
  context "preparation" do
76
76
  before { subject.run }
77
77
 
78
78
  it "clears the screen" do
79
- expect(subject).to have_received(:system).with("clear")
79
+ expect(Kernel).to have_received(:system).with("clear")
80
80
  end
81
81
 
82
82
  context "menu" do
@@ -96,7 +96,7 @@ describe Imap::Backup::Configuration::Account do
96
96
  "test connection",
97
97
  "delete",
98
98
  "return to main menu",
99
- "quit", # TODO: quit is hidden
99
+ "quit" # TODO: quit is hidden
100
100
  ].each do |item|
101
101
  before { subject.run }
102
102
 
@@ -180,7 +180,7 @@ describe Imap::Backup::Configuration::Account do
180
180
  let(:new_email) { other_email }
181
181
 
182
182
  it "indicates the error" do
183
- expect(subject).to have_received(:puts).
183
+ expect(Kernel).to have_received(:puts).
184
184
  with("There is already an account set up with that email address")
185
185
  end
186
186
 
@@ -226,9 +226,6 @@ describe Imap::Backup::Configuration::Account do
226
226
 
227
227
  before do
228
228
  allow(highline).to receive(:ask).with("server: ").and_return(server)
229
- end
230
-
231
- before do
232
229
  subject.run
233
230
  menu.choices["modify server"].call
234
231
  end
@@ -247,7 +244,7 @@ describe Imap::Backup::Configuration::Account do
247
244
  @validator = nil
248
245
  allow(
249
246
  Imap::Backup::Configuration::Asker
250
- ).to receive(:backup_path) do |path, validator|
247
+ ).to receive(:backup_path) do |_path, validator|
251
248
  @validator = validator
252
249
  new_backup_path
253
250
  end
@@ -260,14 +257,18 @@ describe Imap::Backup::Configuration::Account do
260
257
  end
261
258
 
262
259
  it "validates that the path is not used by other backups" do
260
+ # rubocop:disable RSpec/InstanceVariable
263
261
  expect(@validator.call(other_existing_path)).to be_falsey
262
+ # rubocop:enable RSpec/InstanceVariable
264
263
  end
265
264
 
266
265
  include_examples "it flags the account as modified"
267
266
  end
268
267
 
269
268
  context "folders" do
270
- let(:chooser) { double(run: nil) }
269
+ let(:chooser) do
270
+ instance_double(Imap::Backup::Configuration::FolderChooser, run: nil)
271
+ end
271
272
 
272
273
  before do
273
274
  allow(Imap::Backup::Configuration::FolderChooser).
@@ -323,3 +324,5 @@ describe Imap::Backup::Configuration::Account do
323
324
  end
324
325
  end
325
326
  end
327
+
328
+ # rubocop:enable RSpec/NestedGroups
@@ -1,34 +1,34 @@
1
- require "spec_helper"
1
+ # rubocop:disable Metrics/ModuleLength
2
2
 
3
3
  module Imap::Backup
4
4
  describe Configuration::Asker do
5
+ subject { described_class.new(highline) }
6
+
5
7
  let(:highline) { double }
6
8
  let(:query) do
7
- double(
8
- "Query",
9
- :default= => nil,
10
- :readline= => nil,
11
- :validate= => nil,
12
- :responses => {},
13
- :echo= => nil
9
+ instance_double(
10
+ HighLine::Question,
11
+ "default=": nil,
12
+ "readline=": nil,
13
+ "validate=": nil,
14
+ "responses": {},
15
+ "echo=": nil
14
16
  )
15
17
  end
16
18
  let(:answer) { "foo" }
17
19
 
18
20
  before do
19
- allow(Configuration::Setup).to receive(:highline).and_return(highline)
21
+ allow(Configuration::Setup).to receive(:highline) { highline }
20
22
  allow(highline).to receive(:ask) do |&b|
21
23
  b.call query
22
24
  answer
23
25
  end
24
26
  end
25
27
 
26
- subject { described_class.new(highline) }
27
-
28
28
  [
29
29
  [:email, [], "email address"],
30
30
  [:password, [], "password"],
31
- [:backup_path, ["x", "y"], "backup directory"]
31
+ [:backup_path, %w(x y), "backup directory"]
32
32
  ].each do |method, params, prompt|
33
33
  context ".#{method}" do
34
34
  it "asks for input" do
@@ -58,39 +58,35 @@ module Imap::Backup
58
58
  context "#email" do
59
59
  let(:email) { "email@example.com" }
60
60
  let(:answer) { email }
61
+ let(:result) { subject.email }
61
62
 
62
- before do
63
- @result = subject.email
64
- end
63
+ before { result }
65
64
 
66
65
  it "asks for an email" do
67
66
  expect(highline).to have_received(:ask).with(/email/)
68
67
  end
69
68
 
70
69
  it "returns the address" do
71
- expect(@result).to eq(email)
70
+ expect(result).to eq(email)
72
71
  end
73
72
  end
74
73
 
75
74
  context "#password" do
76
75
  let(:password1) { "password" }
77
76
  let(:password2) { "password" }
78
- let(:answers) { [answer1, answer2] }
79
- let(:answer1) { true }
80
- let(:answer2) { false }
77
+ let(:answers) { [true, false] }
78
+ let(:result) { subject.password }
81
79
 
82
80
  before do
83
- @i = 0
84
- allow(highline).to receive(:ask).
85
- with("password: ").and_return(password1)
86
- allow(highline).to receive(:ask).
87
- with("repeat password: ").and_return(password2)
81
+ i = 0
82
+ allow(highline).to receive(:ask).with("password: ") { password1 }
83
+ allow(highline).to receive(:ask).with("repeat password: ") { password2 }
88
84
  allow(highline).to receive(:agree) do
89
- answer = answers[@i]
90
- @i += 1
85
+ answer = answers[i]
86
+ i += 1
91
87
  answer
92
88
  end
93
- @result = subject.password
89
+ result
94
90
  end
95
91
 
96
92
  it "asks for a password" do
@@ -102,7 +98,7 @@ module Imap::Backup
102
98
  end
103
99
 
104
100
  it "returns the password" do
105
- expect(@result).to eq(password1)
101
+ expect(result).to eq(password1)
106
102
  end
107
103
 
108
104
  context "different answers" do
@@ -110,7 +106,7 @@ module Imap::Backup
110
106
 
111
107
  it "asks to continue" do
112
108
  expect(highline).to have_received(:agree).
113
- at_least(1).times.with(/Continue\?/)
109
+ at_least(:once).with(/Continue\?/)
114
110
  end
115
111
  end
116
112
  end
@@ -118,13 +114,14 @@ module Imap::Backup
118
114
  context "#backup_path" do
119
115
  let(:path) { "/path" }
120
116
  let(:answer) { path }
117
+ let(:result) { subject.backup_path("", //) }
121
118
 
122
119
  before do
123
120
  allow(highline).to receive(:ask) do |&b|
124
121
  b.call query
125
122
  path
126
123
  end
127
- @result = subject.backup_path("", //)
124
+ result
128
125
  end
129
126
 
130
127
  it "asks for a directory" do
@@ -132,8 +129,10 @@ module Imap::Backup
132
129
  end
133
130
 
134
131
  it "returns the path" do
135
- expect(@result).to eq(path)
132
+ expect(result).to eq(path)
136
133
  end
137
134
  end
138
135
  end
139
136
  end
137
+
138
+ # rubocop:enable Metrics/ModuleLength