imap-backup 1.0.9 → 1.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +1 -0
- data/Rakefile +0 -5
- data/imap-backup.gemspec +5 -5
- data/lib/email/mboxrd/message.rb +1 -1
- data/lib/imap/backup.rb +3 -1
- data/lib/imap/backup/account/connection.rb +9 -7
- data/lib/imap/backup/account/folder.rb +6 -4
- data/lib/imap/backup/configuration/account.rb +9 -7
- data/lib/imap/backup/configuration/asker.rb +7 -5
- data/lib/imap/backup/configuration/connection_tester.rb +5 -3
- data/lib/imap/backup/configuration/folder_chooser.rb +10 -8
- data/lib/imap/backup/configuration/list.rb +8 -6
- data/lib/imap/backup/configuration/setup.rb +7 -5
- data/lib/imap/backup/configuration/store.rb +7 -5
- data/lib/imap/backup/serializer/base.rb +2 -1
- data/lib/imap/backup/serializer/directory.rb +5 -3
- data/lib/imap/backup/serializer/mbox.rb +10 -5
- data/lib/imap/backup/utils.rb +23 -30
- data/lib/imap/backup/version.rb +7 -7
- data/spec/spec_helper.rb +10 -27
- data/spec/support/higline_test_helpers.rb +8 -0
- data/spec/support/silence_logging.rb +7 -0
- data/spec/unit/account/connection_spec.rb +1 -1
- data/spec/unit/account/folder_spec.rb +33 -52
- data/spec/unit/configuration/asker_spec.rb +46 -5
- data/spec/unit/configuration/folder_chooser_spec.rb +62 -102
- data/spec/unit/configuration/list_spec.rb +40 -48
- data/spec/unit/configuration/setup_spec.rb +41 -62
- data/spec/unit/configuration/store_spec.rb +107 -99
- data/spec/unit/downloader_spec.rb +8 -8
- data/spec/unit/email/mboxrd/message_spec.rb +9 -19
- data/spec/unit/serializer/base_spec.rb +7 -5
- data/spec/unit/serializer/directory_spec.rb +30 -38
- data/spec/unit/serializer/mbox_spec.rb +64 -58
- data/spec/unit/utils_spec.rb +67 -41
- metadata +107 -141
@@ -4,16 +4,16 @@ require 'spec_helper'
|
|
4
4
|
describe Imap::Backup::Downloader do
|
5
5
|
context 'with account and downloader' do
|
6
6
|
let(:local_path) { '/base/path' }
|
7
|
-
let(:stat) {
|
7
|
+
let(:stat) { double('File::Stat', :mode => 0700) }
|
8
8
|
let(:message) do
|
9
9
|
{
|
10
10
|
'RFC822' => 'the body',
|
11
11
|
'other' => 'xxx'
|
12
12
|
}
|
13
13
|
end
|
14
|
-
let(:folder) {
|
14
|
+
let(:folder) { double('Imap::Backup::Account::Folder', :fetch => message) }
|
15
15
|
let(:serializer) do
|
16
|
-
|
16
|
+
double(
|
17
17
|
'Imap::Backup::Serializer',
|
18
18
|
:prepare => nil,
|
19
19
|
:exist? => true,
|
@@ -22,9 +22,9 @@ describe Imap::Backup::Downloader do
|
|
22
22
|
)
|
23
23
|
end
|
24
24
|
|
25
|
-
before { File.
|
25
|
+
before { allow(File).to receive(:stat).with(local_path).and_return(stat) }
|
26
26
|
|
27
|
-
subject {
|
27
|
+
subject { described_class.new(folder, serializer) }
|
28
28
|
|
29
29
|
context '#run' do
|
30
30
|
context 'with folder' do
|
@@ -36,11 +36,11 @@ describe Imap::Backup::Downloader do
|
|
36
36
|
|
37
37
|
context 'with messages' do
|
38
38
|
before :each do
|
39
|
-
folder.
|
39
|
+
allow(folder).to receive(:uids).and_return(['123', '999', '1234'])
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should skip messages that are downloaded' do
|
43
|
-
File.
|
43
|
+
allow(File).to receive(:exist?).and_return(true)
|
44
44
|
|
45
45
|
serializer.should_not_receive(:fetch)
|
46
46
|
|
@@ -56,7 +56,7 @@ describe Imap::Backup::Downloader do
|
|
56
56
|
|
57
57
|
context 'to download' do
|
58
58
|
before :each do
|
59
|
-
serializer.
|
59
|
+
allow(serializer).to receive(:exist?) do |uid|
|
60
60
|
if uid == '123'
|
61
61
|
true
|
62
62
|
else
|
@@ -5,34 +5,24 @@ require 'spec_helper'
|
|
5
5
|
describe Email::Mboxrd::Message do
|
6
6
|
let(:from) { 'me@example.com' }
|
7
7
|
let(:date) { DateTime.new(2012, 12, 13, 18, 23, 45) }
|
8
|
-
let(:message_body)
|
9
|
-
|
8
|
+
let(:message_body) do
|
9
|
+
double('Body', :clone => cloned_message_body, :force_encoding => nil)
|
10
|
+
end
|
11
|
+
let(:cloned_message_body) { "Foo\nBar\nFrom at the beginning of the line\n>>From quoted" }
|
12
|
+
|
13
|
+
subject { described_class.new(message_body) }
|
10
14
|
|
11
15
|
context '#to_s' do
|
12
|
-
let(:mail)
|
13
|
-
mail = stub('Mail')
|
14
|
-
mail.stub(:from).and_return([from])
|
15
|
-
mail.stub(:date).and_return(date)
|
16
|
-
mail
|
17
|
-
end
|
16
|
+
let(:mail) { double('Mail', :from =>[from], :date => date) }
|
18
17
|
|
19
18
|
before do
|
20
|
-
Mail.
|
19
|
+
allow(Mail).to receive(:new).with(cloned_message_body).and_return(mail)
|
21
20
|
end
|
22
21
|
|
23
22
|
it 'does not modify the message' do
|
24
|
-
message_body2 = message_body.clone
|
25
|
-
|
26
|
-
message_body.should_receive(:clone).and_return(message_body2)
|
27
|
-
message_body.should_not_receive(:force_encoding).with('binary')
|
28
|
-
|
29
23
|
subject.to_s
|
30
|
-
end
|
31
24
|
|
32
|
-
|
33
|
-
Mail.should_receive(:new).with(message_body).and_return(mail)
|
34
|
-
|
35
|
-
subject.to_s
|
25
|
+
expect(message_body).to_not have_received(:force_encoding).with('binary')
|
36
26
|
end
|
37
27
|
|
38
28
|
it "adds a 'From ' line at the start" do
|
@@ -4,14 +4,16 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Imap::Backup::Serializer::Base do
|
6
6
|
context '#initialize' do
|
7
|
-
let(:stat) {
|
7
|
+
let(:stat) { double('File::Stat', :mode => 0345) }
|
8
8
|
|
9
|
-
|
10
|
-
File.
|
11
|
-
File.
|
9
|
+
before do
|
10
|
+
allow(File).to receive(:exist?).with('/base/path').and_return(true)
|
11
|
+
allow(File).to receive(:stat).with('/base/path').and_return(stat)
|
12
|
+
end
|
12
13
|
|
14
|
+
it 'should fail if file permissions are to lax' do
|
13
15
|
expect do
|
14
|
-
|
16
|
+
described_class.new('/base/path', 'my_folder')
|
15
17
|
end.to raise_error(RuntimeError, "Permissions on '/base/path' should be 0700, not 0345")
|
16
18
|
end
|
17
19
|
end
|
@@ -2,77 +2,69 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe Imap::Backup::Serializer::Directory do
|
5
|
-
let(:stat) {
|
5
|
+
let(:stat) { double('File::Stat', :mode => 0700) }
|
6
6
|
let(:files) { ['00000123.json', '000001.json'] }
|
7
|
+
let(:base) { '/base/path' }
|
8
|
+
let(:folder) { '/base/path/my_folder' }
|
9
|
+
let(:folder_exists) { true }
|
7
10
|
|
8
11
|
before do
|
9
|
-
|
10
|
-
FileUtils.
|
11
|
-
|
12
|
-
File.
|
12
|
+
allow(FileUtils).to receive(:mkdir_p)
|
13
|
+
allow(FileUtils).to receive(:chmod)
|
14
|
+
allow(File).to receive(:stat).with(base).and_return(stat)
|
15
|
+
allow(File).to receive(:exist?).with(base).and_return(true)
|
16
|
+
allow(File).to receive(:exist?).with(folder).and_return(folder_exists)
|
13
17
|
end
|
14
18
|
|
15
|
-
subject {
|
19
|
+
subject { described_class.new(base, 'my_folder') }
|
16
20
|
|
17
21
|
context '#uids' do
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
before do
|
23
|
+
allow(Dir).to receive(:open).with(folder).and_return(files)
|
24
|
+
end
|
21
25
|
|
26
|
+
it 'returns the backed-up uids' do
|
22
27
|
subject.uids.should == [1, 123]
|
23
28
|
end
|
24
29
|
|
25
|
-
|
26
|
-
|
30
|
+
context 'if the directory does not exist' do
|
31
|
+
let(:folder_exists) { false }
|
27
32
|
|
28
|
-
|
33
|
+
it 'returns an empty array' do
|
34
|
+
subject.uids.should == []
|
35
|
+
end
|
29
36
|
end
|
30
37
|
end
|
31
38
|
|
32
39
|
context '#exist?' do
|
33
|
-
it '
|
34
|
-
File.
|
40
|
+
it 'checks if the file exists' do
|
41
|
+
allow(File).to receive(:exist?).with(%r{/base/path/my_folder/0+123.json}).and_return(true)
|
35
42
|
|
36
43
|
subject.exist?(123).should be_true
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
40
47
|
context '#save' do
|
41
|
-
let(:message)
|
42
|
-
|
43
|
-
'RFC822' => 'the body',
|
44
|
-
'other' => 'xxx'
|
45
|
-
}
|
46
|
-
end
|
47
|
-
let(:file) { stub('File', :write => nil) }
|
48
|
+
let(:message) { {'RFC822' => 'the body', 'other' => 'xxx'} }
|
49
|
+
let(:file) { double('File', :write => nil) }
|
48
50
|
|
49
51
|
before do
|
50
|
-
File.
|
51
|
-
|
52
|
-
File.stub!(:open) do |&block|
|
52
|
+
allow(File).to receive(:exist?).with(%r{/base/path/my_folder/0+1234.json}).and_return(true)
|
53
|
+
allow(File).to receive(:open) do |&block|
|
53
54
|
block.call file
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
57
|
-
it '
|
58
|
-
File.should_receive(:open) do |&block|
|
59
|
-
block.call file
|
60
|
-
end
|
61
|
-
file.should_receive(:write).with(/the body/)
|
62
|
-
|
58
|
+
it 'saves messages' do
|
63
59
|
subject.save('1234', message)
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should JSON encode messages' do
|
67
|
-
message.should_receive(:to_json)
|
68
60
|
|
69
|
-
|
61
|
+
expect(file).to have_received(:write).with(message.to_json)
|
70
62
|
end
|
71
63
|
|
72
|
-
it '
|
73
|
-
FileUtils.should_receive(:chmod).with(0600, /0+1234.json$/)
|
74
|
-
|
64
|
+
it 'sets file permissions' do
|
75
65
|
subject.save(1234, message)
|
66
|
+
|
67
|
+
expect(FileUtils).to have_received(:chmod).with(0600, /0+1234.json$/)
|
76
68
|
end
|
77
69
|
end
|
78
70
|
end
|
@@ -3,109 +3,115 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Imap::Backup::Serializer::Mbox do
|
6
|
-
let(:stat) {
|
6
|
+
let(:stat) { double('File::Stat', :mode => 0700) }
|
7
|
+
let(:base_path) { '/base/path' }
|
7
8
|
let(:mbox_pathname) { '/base/path/my/folder.mbox' }
|
9
|
+
let(:mbox_exists) { true }
|
8
10
|
let(:imap_pathname) { '/base/path/my/folder.imap' }
|
11
|
+
let(:imap_exists) { true }
|
9
12
|
|
10
13
|
before do
|
11
|
-
|
12
|
-
File.
|
13
|
-
|
14
|
+
allow(Imap::Backup::Utils).to receive(:make_folder)
|
15
|
+
allow(File).to receive(:exist?).with(base_path).and_return(true)
|
16
|
+
allow(File).to receive(:stat).with(base_path).and_return(stat)
|
17
|
+
allow(File).to receive(:exist?).with(mbox_pathname).and_return(mbox_exists)
|
18
|
+
allow(File).to receive(:exist?).with(imap_pathname).and_return(imap_exists)
|
14
19
|
end
|
15
20
|
|
16
21
|
context '#initialize' do
|
17
|
-
before do
|
18
|
-
File.stub(:exist?).with(mbox_pathname).and_return(true)
|
19
|
-
File.stub(:exist?).with(imap_pathname).and_return(true)
|
20
|
-
end
|
21
|
-
|
22
22
|
it 'creates the containing directory' do
|
23
|
-
|
23
|
+
described_class.new(base_path, 'my/folder')
|
24
24
|
|
25
|
-
Imap::Backup::
|
25
|
+
expect(Imap::Backup::Utils).to have_received(:make_folder).with(base_path, 'my', 0700)
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'mbox and imap files' do
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
context "if mbox exists and imap doesn't" do
|
30
|
+
let(:imap_exists) { false }
|
31
|
+
|
32
|
+
it 'fails' do
|
33
|
+
expect {
|
34
|
+
described_class.new(base_path, 'my/folder')
|
35
|
+
}.to raise_error(RuntimeError, '.imap file missing')
|
36
|
+
end
|
34
37
|
end
|
35
38
|
|
36
|
-
|
37
|
-
|
39
|
+
context "if imap exists and mbox doesn't" do
|
40
|
+
let(:mbox_exists) { false }
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
it "fails if imap exists and mbox doesn't" do
|
45
|
-
File.stub(:exist?).with(mbox_pathname).and_return(false)
|
46
|
-
|
47
|
-
expect {
|
48
|
-
Imap::Backup::Serializer::Mbox.new('/base/path', 'my/folder')
|
49
|
-
}.to raise_error(RuntimeError, '.mbox file missing')
|
42
|
+
it 'fails' do
|
43
|
+
expect {
|
44
|
+
described_class.new(base_path, 'my/folder')
|
45
|
+
}.to raise_error(RuntimeError, '.mbox file missing')
|
46
|
+
end
|
50
47
|
end
|
51
48
|
end
|
52
49
|
end
|
53
50
|
|
54
51
|
context 'instance methods' do
|
52
|
+
let(:ids) { %w(1 123) }
|
53
|
+
|
55
54
|
before do
|
56
|
-
|
57
|
-
File.stub(:exist?).with(imap_pathname).and_return(true)
|
58
|
-
CSV.stub(:foreach) do |&block|
|
59
|
-
block.call ['1']
|
60
|
-
block.call ['123']
|
61
|
-
end
|
55
|
+
allow(CSV).to receive(:foreach) { |&b| ids.each { |id| b.call [id] } }
|
62
56
|
end
|
63
57
|
|
64
|
-
subject {
|
58
|
+
subject { described_class.new(base_path, 'my/folder') }
|
65
59
|
|
66
60
|
context '#uids' do
|
67
61
|
it 'returns the backed-up uids' do
|
68
|
-
|
69
|
-
File.should_receive(:exist?).with(imap_pathname).and_return(true)
|
70
|
-
|
71
|
-
expect(subject.uids).to eq(['1', '123'])
|
62
|
+
expect(subject.uids).to eq(ids)
|
72
63
|
end
|
73
64
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
File.should_receive(:exist?).with(mbox_pathname).and_return(false)
|
78
|
-
File.should_receive(:exist?).with(imap_pathname).and_return(false)
|
65
|
+
context 'if the mbox does not exist' do
|
66
|
+
let(:mbox_exists) { false }
|
67
|
+
let(:imap_exists) { false }
|
79
68
|
|
80
|
-
|
69
|
+
it 'returns an empty Array' do
|
70
|
+
expect(subject.uids).to eq([])
|
71
|
+
end
|
81
72
|
end
|
82
73
|
end
|
83
74
|
|
84
75
|
context '#save' do
|
85
76
|
let(:mbox_formatted_message) { 'message in mbox format' }
|
86
77
|
let(:message_uid) { '999' }
|
87
|
-
let(:message) {
|
88
|
-
let(:mbox_file) {
|
89
|
-
let(:imap_file) {
|
78
|
+
let(:message) { double('Email::Mboxrd::Message', :to_s => mbox_formatted_message) }
|
79
|
+
let(:mbox_file) { double('File - mbox', :write => nil, :close => nil) }
|
80
|
+
let(:imap_file) { double('File - imap', :write => nil, :close => nil) }
|
90
81
|
|
91
82
|
before do
|
92
|
-
Email::Mboxrd::Message.
|
93
|
-
File.
|
94
|
-
File.
|
95
|
-
mbox_file.stub(:write).with(mbox_formatted_message)
|
96
|
-
imap_file.stub(:write).with(message_uid + "\n")
|
83
|
+
allow(Email::Mboxrd::Message).to receive(:new).and_return(message)
|
84
|
+
allow(File).to receive(:open).with(mbox_pathname, 'ab').and_return(mbox_file)
|
85
|
+
allow(File).to receive(:open).with(imap_pathname, 'ab').and_return(imap_file)
|
97
86
|
end
|
98
87
|
|
99
88
|
it 'saves the message to the mbox' do
|
100
|
-
mbox_file.should_receive(:write).with(mbox_formatted_message)
|
101
|
-
|
102
89
|
subject.save(message_uid, "The\nemail\n")
|
90
|
+
|
91
|
+
expect(mbox_file).to have_received(:write).with(mbox_formatted_message)
|
103
92
|
end
|
104
93
|
|
105
94
|
it 'saves the uid to the imap file' do
|
106
|
-
imap_file.should_receive(:write).with(message_uid + "\n")
|
107
|
-
|
108
95
|
subject.save(message_uid, "The\nemail\n")
|
96
|
+
|
97
|
+
expect(imap_file).to have_received(:write).with(message_uid + "\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when the message causes parsing errors' do
|
101
|
+
before do
|
102
|
+
allow(message).to receive(:to_s).and_raise(ArgumentError)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'skips the message' do
|
106
|
+
subject.save(message_uid, "The\nemail\n")
|
107
|
+
expect(mbox_file).to_not have_received(:write)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'does not fail' do
|
111
|
+
expect do
|
112
|
+
subject.save(message_uid, "The\nemail\n")
|
113
|
+
end.to_not raise_error
|
114
|
+
end
|
109
115
|
end
|
110
116
|
end
|
111
117
|
end
|
data/spec/unit/utils_spec.rb
CHANGED
@@ -2,67 +2,93 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe Imap::Backup::Utils do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
let(:filename) { 'foobar' }
|
6
|
+
let(:stat) { double('File::Stat', :mode => mode) }
|
7
|
+
let(:mode) { 0777 }
|
8
|
+
let(:exists) { true }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(File).to receive(:stat).and_return(stat)
|
12
|
+
allow(File).to receive(:exist?).with(filename).and_return(exists)
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
+
context '.check_permissions' do
|
16
|
+
let(:requested) { 0345 }
|
17
|
+
|
18
|
+
context 'with existing files' do
|
19
|
+
[
|
20
|
+
[0100, 'less than the limit', true],
|
21
|
+
[0345, 'equal to the limit', true],
|
22
|
+
[0777, 'over the limit', false],
|
23
|
+
].each do |mode, description, success|
|
24
|
+
context "when permissions are #{description}" do
|
25
|
+
let(:mode) { mode }
|
26
|
+
|
27
|
+
if success
|
28
|
+
it 'succeeds' do
|
29
|
+
described_class.check_permissions(filename, requested)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
it 'fails' do
|
33
|
+
expect do
|
34
|
+
described_class.check_permissions(filename, requested)
|
35
|
+
end.to raise_error(RuntimeError, format("Permissions on '%s' should be 0%o, not 0%o", filename, requested, mode))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
15
40
|
end
|
16
41
|
|
17
|
-
|
18
|
-
|
19
|
-
|
42
|
+
context 'with non-existent files' do
|
43
|
+
let(:exists) { false }
|
44
|
+
let(:mode) { 0111 }
|
20
45
|
|
21
|
-
|
22
|
-
|
23
|
-
end
|
46
|
+
it 'succeeds' do
|
47
|
+
described_class.check_permissions(filename, requested)
|
48
|
+
end
|
24
49
|
end
|
50
|
+
end
|
25
51
|
|
26
|
-
|
27
|
-
|
28
|
-
|
52
|
+
context '.stat' do
|
53
|
+
context 'with existing files' do
|
54
|
+
let(:mode) { 02345 }
|
29
55
|
|
30
|
-
|
31
|
-
|
32
|
-
end
|
56
|
+
it 'is the last 9 bits of the file mode' do
|
57
|
+
expect(described_class.stat(filename)).to eq(0345)
|
58
|
+
end
|
33
59
|
end
|
34
60
|
|
35
|
-
|
36
|
-
|
37
|
-
File.stub!(:stat).and_return(stat)
|
61
|
+
context 'with non-existent files' do
|
62
|
+
let(:exists) { false }
|
38
63
|
|
39
|
-
|
40
|
-
|
41
|
-
end
|
64
|
+
it 'is nil' do
|
65
|
+
expect(described_class.stat(filename)).to be_nil
|
66
|
+
end
|
42
67
|
end
|
43
68
|
end
|
44
69
|
|
45
|
-
context '
|
46
|
-
|
47
|
-
FileUtils.
|
48
|
-
|
49
|
-
Imap::Backup::Utils.make_folder('aaa', '', 0222)
|
70
|
+
context '.make_folder' do
|
71
|
+
before do
|
72
|
+
allow(FileUtils).to receive(:mkdir_p)
|
73
|
+
allow(FileUtils).to receive(:chmod)
|
50
74
|
end
|
51
75
|
|
52
|
-
it '
|
53
|
-
|
54
|
-
|
55
|
-
FileUtils.should_receive(:mkdir_p).with('/base/path/new/folder')
|
76
|
+
it 'does nothing if an empty path is supplied' do
|
77
|
+
described_class.make_folder('aaa', '', 0222)
|
56
78
|
|
57
|
-
|
79
|
+
expect(FileUtils).to_not have_received(:mkdir_p)
|
58
80
|
end
|
59
81
|
|
60
|
-
it '
|
61
|
-
|
82
|
+
it 'creates the path' do
|
83
|
+
described_class.make_folder('/base/path', 'new/folder', 0222)
|
84
|
+
|
85
|
+
expect(FileUtils).to have_received(:mkdir_p).with('/base/path/new/folder')
|
86
|
+
end
|
62
87
|
|
63
|
-
|
88
|
+
it 'sets permissions on the path' do
|
89
|
+
described_class.make_folder('/base/path/new', 'folder', 0222)
|
64
90
|
|
65
|
-
|
91
|
+
expect(FileUtils).to have_received(:chmod).with(0222, '/base/path/new/folder')
|
66
92
|
end
|
67
93
|
end
|
68
94
|
end
|