imap-backup 1.3.0 → 1.4.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +2 -1
  5. data/.travis.yml +1 -1
  6. data/README.md +12 -0
  7. data/bin/imap-backup +11 -6
  8. data/docker-compose.yml +15 -0
  9. data/imap-backup.gemspec +3 -2
  10. data/lib/email/mboxrd/message.rb +30 -4
  11. data/lib/email/provider.rb +2 -2
  12. data/lib/imap/backup.rb +0 -1
  13. data/lib/imap/backup/account/connection.rb +29 -15
  14. data/lib/imap/backup/account/folder.rb +3 -3
  15. data/lib/imap/backup/configuration/account.rb +15 -12
  16. data/lib/imap/backup/configuration/asker.rb +3 -1
  17. data/lib/imap/backup/configuration/folder_chooser.rb +5 -2
  18. data/lib/imap/backup/configuration/list.rb +12 -9
  19. data/lib/imap/backup/configuration/setup.rb +5 -3
  20. data/lib/imap/backup/configuration/store.rb +4 -4
  21. data/lib/imap/backup/downloader.rb +6 -2
  22. data/lib/imap/backup/serializer/base.rb +2 -2
  23. data/lib/imap/backup/serializer/mbox.rb +16 -7
  24. data/lib/imap/backup/utils.rb +8 -3
  25. data/lib/imap/backup/version.rb +1 -1
  26. data/spec/features/backup_spec.rb +27 -0
  27. data/spec/features/helper.rb +2 -0
  28. data/spec/features/support/backup_directory.rb +27 -0
  29. data/spec/features/support/email_server.rb +40 -0
  30. data/spec/features/support/shared/connection_context.rb +12 -0
  31. data/spec/features/support/shared/message_fixtures.rb +6 -0
  32. data/spec/fixtures/connection.yml +7 -0
  33. data/spec/support/fixtures.rb +6 -0
  34. data/spec/unit/account/connection_spec.rb +19 -7
  35. data/spec/unit/account/folder_spec.rb +15 -5
  36. data/spec/unit/configuration/account_spec.rb +18 -8
  37. data/spec/unit/configuration/asker_spec.rb +6 -3
  38. data/spec/unit/configuration/connection_tester_spec.rb +1 -1
  39. data/spec/unit/configuration/folder_chooser_spec.rb +21 -11
  40. data/spec/unit/configuration/list_spec.rb +13 -6
  41. data/spec/unit/configuration/setup_spec.rb +5 -3
  42. data/spec/unit/configuration/store_spec.rb +13 -8
  43. data/spec/unit/downloader_spec.rb +3 -1
  44. data/spec/unit/email/mboxrd/message_spec.rb +32 -13
  45. data/spec/unit/email/provider_spec.rb +7 -3
  46. data/spec/unit/serializer/base_spec.rb +3 -2
  47. data/spec/unit/serializer/mbox_spec.rb +9 -6
  48. data/spec/unit/utils_spec.rb +15 -13
  49. metadata +35 -5
  50. data/lib/imap/backup/serializer/directory.rb +0 -43
  51. data/spec/unit/serializer/directory_spec.rb +0 -69
@@ -35,7 +35,9 @@ describe Imap::Backup::Configuration::Account do
35
35
  context "#run" do
36
36
  let(:highline) { double("Highline") }
37
37
  let(:menu) { MockHighlineMenu.new }
38
- let(:store) { double("Imap::Backup::Configuration::Store", accounts: accounts) }
38
+ let(:store) do
39
+ double("Imap::Backup::Configuration::Store", accounts: accounts)
40
+ end
39
41
  let(:accounts) { [account, account1] }
40
42
  let(:account) do
41
43
  {
@@ -132,7 +134,8 @@ describe Imap::Backup::Configuration::Account do
132
134
 
133
135
  context "email" do
134
136
  before do
135
- allow(Imap::Backup::Configuration::Asker).to receive(:email).and_return(new_email)
137
+ allow(Imap::Backup::Configuration::Asker).
138
+ to receive(:email) { new_email }
136
139
  subject.run
137
140
  menu.choices["modify email"].call
138
141
  end
@@ -176,7 +179,8 @@ describe Imap::Backup::Configuration::Account do
176
179
  let(:new_email) { other_email }
177
180
 
178
181
  it "indicates the error" do
179
- expect(subject).to have_received(:puts).with("There is already an account set up with that email address")
182
+ expect(subject).to have_received(:puts).
183
+ with("There is already an account set up with that email address")
180
184
  end
181
185
 
182
186
  it "doesn't set the email" do
@@ -191,7 +195,8 @@ describe Imap::Backup::Configuration::Account do
191
195
  let(:new_password) { "new_password" }
192
196
 
193
197
  before do
194
- allow(Imap::Backup::Configuration::Asker).to receive(:password).and_return(new_password)
198
+ allow(Imap::Backup::Configuration::Asker).
199
+ to receive(:password) { new_password }
195
200
  subject.run
196
201
  menu.choices["modify password"].call
197
202
  end
@@ -239,7 +244,9 @@ describe Imap::Backup::Configuration::Account do
239
244
 
240
245
  before do
241
246
  @validator = nil
242
- allow(Imap::Backup::Configuration::Asker).to receive(:backup_path) do |path, validator|
247
+ allow(
248
+ Imap::Backup::Configuration::Asker
249
+ ).to receive(:backup_path) do |path, validator|
243
250
  @validator = validator
244
251
  new_backup_path
245
252
  end
@@ -262,7 +269,8 @@ describe Imap::Backup::Configuration::Account do
262
269
  let(:chooser) { double(run: nil) }
263
270
 
264
271
  before do
265
- allow(Imap::Backup::Configuration::FolderChooser).to receive(:new).and_return(chooser)
272
+ allow(Imap::Backup::Configuration::FolderChooser).
273
+ to receive(:new) { chooser }
266
274
  subject.run
267
275
  menu.choices["choose backup folders"].call
268
276
  end
@@ -274,14 +282,16 @@ describe Imap::Backup::Configuration::Account do
274
282
 
275
283
  context "connection test" do
276
284
  before do
277
- allow(Imap::Backup::Configuration::ConnectionTester).to receive(:test).and_return("All fine")
285
+ allow(Imap::Backup::Configuration::ConnectionTester).
286
+ to receive(:test).and_return("All fine")
278
287
  allow(highline).to receive(:ask)
279
288
  subject.run
280
289
  menu.choices["test connection"].call
281
290
  end
282
291
 
283
292
  it "tests the connection" do
284
- expect(Imap::Backup::Configuration::ConnectionTester).to have_received(:test).with(account)
293
+ expect(Imap::Backup::Configuration::ConnectionTester).
294
+ to have_received(:test).with(account)
285
295
  end
286
296
  end
287
297
 
@@ -81,8 +81,10 @@ module Imap::Backup
81
81
 
82
82
  before do
83
83
  @i = 0
84
- allow(highline).to receive(:ask).with("password: ").and_return(password1)
85
- allow(highline).to receive(:ask).with("repeat password: ").and_return(password2)
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)
86
88
  allow(highline).to receive(:agree) do
87
89
  answer = answers[@i]
88
90
  @i += 1
@@ -107,7 +109,8 @@ module Imap::Backup
107
109
  let(:password2) { "secret" }
108
110
 
109
111
  it "asks to continue" do
110
- expect(highline).to have_received(:agree).at_least(1).times.with(/Continue\?/)
112
+ expect(highline).to have_received(:agree).
113
+ at_least(1).times.with(/Continue\?/)
111
114
  end
112
115
  end
113
116
  end
@@ -5,7 +5,7 @@ describe Imap::Backup::Configuration::ConnectionTester do
5
5
  let(:connection) { double("Imap::Backup::Account::Connection", imap: nil) }
6
6
 
7
7
  before do
8
- allow(Imap::Backup::Account::Connection).to receive(:new).and_return(connection)
8
+ allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
9
9
  end
10
10
 
11
11
  context "call" do
@@ -4,14 +4,17 @@ describe Imap::Backup::Configuration::FolderChooser do
4
4
  include HighLineTestHelpers
5
5
 
6
6
  context "#run" do
7
- let(:connection) { double("Imap::Backup::Account::Connection", folders: remote_folders) }
7
+ let(:connection) do
8
+ double("Imap::Backup::Account::Connection", folders: remote_folders)
9
+ end
8
10
  let(:account) { {folders: []} }
9
11
  let(:remote_folders) { [] }
10
12
 
11
13
  subject { described_class.new(account) }
12
14
 
13
15
  before do
14
- allow(Imap::Backup::Account::Connection).to receive(:new).with(account).and_return(connection)
16
+ allow(Imap::Backup::Account::Connection).
17
+ to receive(:new).with(account) { connection }
15
18
  @input, @output = prepare_highline
16
19
  allow(subject).to receive(:system)
17
20
  allow(Imap::Backup.logger).to receive(:warn)
@@ -32,7 +35,8 @@ describe Imap::Backup::Configuration::FolderChooser do
32
35
  context "folder listing" do
33
36
  let(:account) { {folders: [{name: "my_folder"}]} }
34
37
  let(:remote_folders) do
35
- folder1 = double("folder", name: "my_folder") # this one is already backed up
38
+ # this one is already backed up:
39
+ folder1 = double("folder", name: "my_folder")
36
40
  folder2 = double("folder", name: "another_folder")
37
41
  [folder1, folder2]
38
42
  end
@@ -57,7 +61,7 @@ describe Imap::Backup::Configuration::FolderChooser do
57
61
  end
58
62
 
59
63
  specify "are added to the account" do
60
- expect(account[:folders]).to include({name: "another_folder"})
64
+ expect(account[:folders]).to include(name: "another_folder")
61
65
  end
62
66
 
63
67
  include_examples "it flags the account as modified"
@@ -71,7 +75,7 @@ describe Imap::Backup::Configuration::FolderChooser do
71
75
  end
72
76
 
73
77
  specify "are removed from the account" do
74
- expect(account[:folders]).to_not include({name: "my_folder"})
78
+ expect(account[:folders]).to_not include(name: "my_folder")
75
79
  end
76
80
 
77
81
  include_examples "it flags the account as modified"
@@ -82,28 +86,34 @@ describe Imap::Backup::Configuration::FolderChooser do
82
86
  let(:remote_folders) { nil }
83
87
 
84
88
  before do
85
- allow(Imap::Backup::Configuration::Setup.highline).to receive(:ask).and_return("q")
89
+ allow(Imap::Backup::Configuration::Setup.highline).
90
+ to receive(:ask).and_return("q")
86
91
  subject.run
87
92
  end
88
93
 
89
94
  it "asks to press a key" do
90
- expect(Imap::Backup::Configuration::Setup.highline).to have_received(:ask).with("Press a key ")
95
+ expect(Imap::Backup::Configuration::Setup.highline).
96
+ to have_received(:ask).with("Press a key ")
91
97
  end
92
98
  end
93
99
 
94
100
  context "with connection errors" do
95
101
  before do
96
- allow(Imap::Backup::Account::Connection).to receive(:new).with(account).and_raise("error")
97
- allow(Imap::Backup::Configuration::Setup.highline).to receive(:ask).and_return("q")
102
+ allow(Imap::Backup::Account::Connection).
103
+ to receive(:new).with(account).and_raise("error")
104
+ allow(Imap::Backup::Configuration::Setup.highline).
105
+ to receive(:ask).and_return("q")
98
106
  subject.run
99
107
  end
100
108
 
101
109
  it "prints an error message" do
102
- expect(Imap::Backup.logger).to have_received(:warn).with("Connection failed")
110
+ expect(Imap::Backup.logger).
111
+ to have_received(:warn).with("Connection failed")
103
112
  end
104
113
 
105
114
  it "asks to continue" do
106
- expect(Imap::Backup::Configuration::Setup.highline).to have_received(:ask).with("Press a key ")
115
+ expect(Imap::Backup::Configuration::Setup.highline).
116
+ to have_received(:ask).with("Press a key ")
107
117
  end
108
118
  end
109
119
  end
@@ -11,14 +11,21 @@ describe Imap::Backup::Configuration::List do
11
11
  double("Imap::Backup::Configuration::Store", accounts: accounts)
12
12
  end
13
13
  let(:exists) { true }
14
- let(:connection1) { double("Imap::Backup::Account::Connection", disconnect: nil) }
15
- let(:connection2) { double("Imap::Backup::Account::Connection", disconnect: nil) }
14
+ let(:connection1) do
15
+ double("Imap::Backup::Account::Connection", disconnect: nil)
16
+ end
17
+ let(:connection2) do
18
+ double("Imap::Backup::Account::Connection", disconnect: nil)
19
+ end
16
20
 
17
21
  before do
18
- allow(Imap::Backup::Configuration::Store).to receive(:new).and_return(store)
19
- allow(Imap::Backup::Configuration::Store).to receive(:exist?).and_return(exists)
20
- allow(Imap::Backup::Account::Connection).to receive(:new).with(accounts[0]).and_return(connection1)
21
- allow(Imap::Backup::Account::Connection).to receive(:new).with(accounts[1]).and_return(connection2)
22
+ allow(Imap::Backup::Configuration::Store).to receive(:new) { store }
23
+ allow(Imap::Backup::Configuration::Store).
24
+ to receive(:exist?) { exists }
25
+ allow(Imap::Backup::Account::Connection).
26
+ to receive(:new).with(accounts[0]) { connection1 }
27
+ allow(Imap::Backup::Account::Connection).
28
+ to receive(:new).with(accounts[1]) { connection2 }
22
29
  end
23
30
 
24
31
  subject { described_class.new }
@@ -29,7 +29,7 @@ describe Imap::Backup::Configuration::Setup do
29
29
  let(:modified) { false }
30
30
 
31
31
  before :each do
32
- allow(Imap::Backup::Configuration::Store).to receive(:new).and_return(store)
32
+ allow(Imap::Backup::Configuration::Store).to receive(:new) { store }
33
33
  allow(Imap::Backup).to receive(:setup_logging)
34
34
  @input, @output = prepare_highline
35
35
  allow(@input).to receive(:eof?).and_return(false)
@@ -100,8 +100,10 @@ describe Imap::Backup::Configuration::Setup do
100
100
 
101
101
  before do
102
102
  allow(@input).to receive(:gets).and_return("add\n", "exit\n")
103
- allow(Imap::Backup::Configuration::Asker).to receive(:email).with(no_args).and_return("new@example.com")
104
- allow(Imap::Backup::Configuration::Account).to receive(:new).with(store, blank_account, anything).and_return(account)
103
+ allow(Imap::Backup::Configuration::Asker).to receive(:email).
104
+ with(no_args).and_return("new@example.com")
105
+ allow(Imap::Backup::Configuration::Account).to receive(:new).
106
+ with(store, blank_account, anything).and_return(account)
105
107
 
106
108
  subject.run
107
109
  end
@@ -12,11 +12,15 @@ describe Imap::Backup::Configuration::Store do
12
12
  let(:configuration) { data.to_json }
13
13
 
14
14
  before do
15
- stub_const("Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY", directory)
16
- allow(File).to receive(:directory?).with(directory).and_return(directory_exists)
17
- allow(File).to receive(:exist?).with(file_path).and_return(file_exists)
18
- allow(Imap::Backup::Utils).to receive(:stat).with(directory).and_return(0700)
19
- allow(Imap::Backup::Utils).to receive(:stat).with(file_path).and_return(0600)
15
+ stub_const(
16
+ "Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY", directory
17
+ )
18
+ allow(File).to receive(:directory?).with(directory) { directory_exists }
19
+ allow(File).to receive(:exist?).with(file_path) { file_exists }
20
+ allow(Imap::Backup::Utils).
21
+ to receive(:stat).with(directory).and_return(0o700)
22
+ allow(Imap::Backup::Utils).
23
+ to receive(:stat).with(file_path).and_return(0o600)
20
24
  allow(Imap::Backup::Utils).to receive(:check_permissions).and_return(nil)
21
25
  allow(File).to receive(:read).with(file_path).and_return(configuration)
22
26
  end
@@ -151,7 +155,7 @@ describe Imap::Backup::Configuration::Store do
151
155
 
152
156
  context "when accounts are modified" do
153
157
  let(:accounts) { [{name: "foo", modified: true}] }
154
-
158
+
155
159
  before { subject.save }
156
160
 
157
161
  it "skips the 'modified' flag" do
@@ -184,7 +188,7 @@ describe Imap::Backup::Configuration::Store do
184
188
  before { subject.save }
185
189
 
186
190
  it "sets them to 0600" do
187
- expect(FileUtils).to have_received(:chmod).with(0600, file_path)
191
+ expect(FileUtils).to have_received(:chmod).with(0o600, file_path)
188
192
  end
189
193
  end
190
194
 
@@ -202,7 +206,8 @@ describe Imap::Backup::Configuration::Store do
202
206
  let(:file_exists) { true }
203
207
 
204
208
  before do
205
- allow(Imap::Backup::Utils).to receive(:check_permissions).with(file_path, 0600).and_raise("Error")
209
+ allow(Imap::Backup::Utils).to receive(:check_permissions).
210
+ with(file_path, 0o600).and_raise("Error")
206
211
  end
207
212
 
208
213
  it "fails" do
@@ -3,7 +3,9 @@ require "spec_helper"
3
3
  describe Imap::Backup::Downloader do
4
4
  describe "#run" do
5
5
  let(:message) { {"RFC822" => "blah"} }
6
- let(:folder) { double("Imap::Backup::Account::Folder", fetch: message, name: "folder") }
6
+ let(:folder) do
7
+ double("Imap::Backup::Account::Folder", fetch: message, name: "folder")
8
+ end
7
9
  let(:folder_uids) { ["111", "222", "333"] }
8
10
  let(:serializer) { double("Imap::Backup::Serializer", save: nil) }
9
11
  let(:serializer_uids) { ["222"] }
@@ -27,11 +27,28 @@ describe Email::Mboxrd::Message do
27
27
  let(:message_body) do
28
28
  double("Body", clone: cloned_message_body, force_encoding: nil)
29
29
  end
30
- let(:cloned_message_body) { "Foo\nBar\nFrom at the beginning of the line\n>>From quoted" }
30
+ let(:cloned_message_body) do
31
+ "Foo\nBar\nFrom at the beginning of the line\n>>From quoted"
32
+ end
31
33
 
32
34
  subject { described_class.new(message_body) }
33
35
 
34
- context "#to_s" do
36
+ describe ".from_serialized" do
37
+ let(:serialized_message) { "From foo@a.com\n#{imap_message}" }
38
+ let(:imap_message) { "Delivered-To: me@example.com\nFrom Me\n" }
39
+
40
+ before { @result = described_class.from_serialized(serialized_message) }
41
+
42
+ it "returns the message" do
43
+ expect(@result).to be_a(described_class)
44
+ end
45
+
46
+ it "removes one level of > before From" do
47
+ expect(@result.supplied_body).to eq(imap_message)
48
+ end
49
+ end
50
+
51
+ context "#to_serialized" do
35
52
  let(:mail) { double("Mail", from: [from], date: date) }
36
53
 
37
54
  before do
@@ -39,33 +56,34 @@ describe Email::Mboxrd::Message do
39
56
  end
40
57
 
41
58
  it "does not modify the message" do
42
- subject.to_s
59
+ subject.to_serialized
43
60
 
44
61
  expect(message_body).to_not have_received(:force_encoding).with("binary")
45
62
  end
46
63
 
47
64
  it "adds a 'From ' line at the start" do
48
- expect(subject.to_s).to start_with("From " + from + " " + date.asctime + "\n")
65
+ expected = "From #{from} #{date.asctime}\n"
66
+ expect(subject.to_serialized).to start_with(expected)
49
67
  end
50
68
 
51
69
  it "replaces existing 'From ' with '>From '" do
52
- expect(subject.to_s).to include("\n>From at the beginning")
70
+ expect(subject.to_serialized).to include("\n>From at the beginning")
53
71
  end
54
72
 
55
73
  it "appends > before '>+From '" do
56
- expect(subject.to_s).to include("\n>>>From quoted")
74
+ expect(subject.to_serialized).to include("\n>>>From quoted")
57
75
  end
58
76
 
59
77
  context "when date is missing" do
60
78
  let(:date) { nil }
61
79
 
62
80
  it "does no fail" do
63
- expect { subject.to_s }.to_not raise_error
81
+ expect { subject.to_serialized }.to_not raise_error
64
82
  end
65
83
  end
66
84
  end
67
85
 
68
- context '#from' do
86
+ context "#from" do
69
87
  before do
70
88
  # call original for these tests because we want to test the behaviour of
71
89
  # class-under-test given different behaviour of the Mail parser
@@ -75,7 +93,7 @@ describe Email::Mboxrd::Message do
75
93
  context "when original message 'from' is nil" do
76
94
  let(:message_body) { msg_no_from }
77
95
  it "'from' is empty string" do
78
- expect(subject.to_s).to start_with("From \n")
96
+ expect(subject.to_serialized).to start_with("From \n")
79
97
  end
80
98
  end
81
99
 
@@ -83,15 +101,16 @@ describe Email::Mboxrd::Message do
83
101
  let(:message_body) { msg_bad_from }
84
102
 
85
103
  it "'from' is empty string" do
86
- expect(subject.to_s).to start_with("From \n")
104
+ expect(subject.to_serialized).to start_with("From \n")
87
105
  end
88
106
  end
89
107
 
90
- context "when original message 'from' is nil and 'envelope from' is nil and 'return path' is available" do
108
+ context "when original message 'from' is nil and " \
109
+ "'envelope from' is nil and 'return path' is available" do
91
110
  let(:message_body) { msg_no_from_but_return_path }
92
111
 
93
112
  it "'return path' is used as 'from'" do
94
- expect(subject.to_s).to start_with("From " + from + " \n")
113
+ expect(subject.to_serialized).to start_with("From " + from + "\n")
95
114
  end
96
115
  end
97
116
 
@@ -99,7 +118,7 @@ describe Email::Mboxrd::Message do
99
118
  let(:message_body) { msg_no_from_but_sender }
100
119
 
101
120
  it "Sender is used as 'from'" do
102
- expect(subject.to_s).to start_with("From " + from + " \n")
121
+ expect(subject.to_serialized).to start_with("From " + from + "\n")
103
122
  end
104
123
  end
105
124
  end
@@ -3,7 +3,10 @@ require "spec_helper"
3
3
  describe Email::Provider do
4
4
  describe ".for_address" do
5
5
  context "known providers" do
6
- [["gmail.com", :gmail], ["fastmail.fm", :fastmail]].each do |domain, provider|
6
+ [
7
+ ["gmail.com", :gmail],
8
+ ["fastmail.fm", :fastmail]
9
+ ].each do |domain, provider|
7
10
  it "recognizes #{provider}" do
8
11
  address = "foo@#{domain}"
9
12
  expect(described_class.for_address(address).provider).to eq(provider)
@@ -13,7 +16,8 @@ describe Email::Provider do
13
16
 
14
17
  context "with unknown providers" do
15
18
  it "returns a default provider" do
16
- expect(described_class.for_address("foo@unknown.com").provider).to eq(:default)
19
+ result = described_class.for_address("foo@unknown.com").provider
20
+ expect(result).to eq(:default)
17
21
  end
18
22
  end
19
23
  end
@@ -22,7 +26,7 @@ describe Email::Provider do
22
26
 
23
27
  describe "#options" do
24
28
  it "returns options" do
25
- expect(subject.options).to eq(port: 993, ssl: true)
29
+ expect(subject.options).to be_a(Hash)
26
30
  end
27
31
  end
28
32
 
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Imap::Backup::Serializer::Base do
4
4
  context "#initialize" do
5
- let(:stat) { double("File::Stat", mode: 0345) }
5
+ let(:stat) { double("File::Stat", mode: 0o345) }
6
6
 
7
7
  before do
8
8
  allow(File).to receive(:exist?).with("/base/path").and_return(true)
@@ -10,9 +10,10 @@ describe Imap::Backup::Serializer::Base do
10
10
  end
11
11
 
12
12
  it "should fail if file permissions are to lax" do
13
+ message = "Permissions on '/base/path' should be 0700, not 0345"
13
14
  expect do
14
15
  described_class.new("/base/path", "my_folder")
15
- end.to raise_error(RuntimeError, "Permissions on '/base/path' should be 0700, not 0345")
16
+ end.to raise_error(RuntimeError, message)
16
17
  end
17
18
  end
18
19
  end