saviour 0.2.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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +10 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +491 -0
- data/Rakefile +6 -0
- data/lib/saviour.rb +170 -0
- data/lib/saviour/base_uploader.rb +81 -0
- data/lib/saviour/config.rb +13 -0
- data/lib/saviour/file.rb +124 -0
- data/lib/saviour/local_storage.rb +72 -0
- data/lib/saviour/processors/digest.rb +16 -0
- data/lib/saviour/s3_storage.rb +77 -0
- data/lib/saviour/string_source.rb +15 -0
- data/lib/saviour/uploader/element.rb +19 -0
- data/lib/saviour/uploader/processors_runner.rb +88 -0
- data/lib/saviour/uploader/store_dir_extractor.rb +41 -0
- data/lib/saviour/url_source.rb +55 -0
- data/lib/saviour/version.rb +3 -0
- data/saviour.gemspec +26 -0
- data/spec/feature/access_to_model_and_mounted_as.rb +30 -0
- data/spec/feature/crud_workflows_spec.rb +138 -0
- data/spec/feature/persisted_path_spec.rb +35 -0
- data/spec/feature/reload_model_spec.rb +25 -0
- data/spec/feature/validations_spec.rb +172 -0
- data/spec/feature/versions_spec.rb +186 -0
- data/spec/models/base_uploader_spec.rb +396 -0
- data/spec/models/config_spec.rb +16 -0
- data/spec/models/file_spec.rb +210 -0
- data/spec/models/local_storage_spec.rb +154 -0
- data/spec/models/processors/digest_spec.rb +22 -0
- data/spec/models/s3_storage_spec.rb +170 -0
- data/spec/models/saviour_spec.rb +80 -0
- data/spec/models/url_source_spec.rb +76 -0
- data/spec/spec_helper.rb +93 -0
- data/spec/support/data/camaloon.jpg +0 -0
- data/spec/support/data/example.xml +21 -0
- data/spec/support/data/text.txt +1 -0
- data/spec/support/models.rb +3 -0
- data/spec/support/schema.rb +9 -0
- metadata +196 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour::Config do
|
4
|
+
after { Saviour::Config.storage = nil }
|
5
|
+
|
6
|
+
describe "#storage" do
|
7
|
+
it do
|
8
|
+
expect { Saviour::Config.storage }.to raise_error(RuntimeError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it do
|
12
|
+
Saviour::Config.storage = :test
|
13
|
+
expect(Saviour::Config.storage).to eq :test
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour::File do
|
4
|
+
let(:mocked_storage) {
|
5
|
+
Class.new {
|
6
|
+
def write(content, filename)
|
7
|
+
end
|
8
|
+
|
9
|
+
def read(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def exists?(path)
|
16
|
+
end
|
17
|
+
}.new
|
18
|
+
}
|
19
|
+
|
20
|
+
before { allow(Saviour::Config).to receive(:storage).and_return(mocked_storage) }
|
21
|
+
|
22
|
+
let(:uploader_klass) { Class.new(Saviour::BaseUploader) {
|
23
|
+
store_dir { "/store/dir" }
|
24
|
+
} }
|
25
|
+
|
26
|
+
let(:example_file) { double(read: "some file contents", path: "/my/path") }
|
27
|
+
|
28
|
+
describe "initialization" do
|
29
|
+
describe "derives persisted from the model" do
|
30
|
+
it do
|
31
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
32
|
+
expect(file).not_to be_persisted
|
33
|
+
end
|
34
|
+
|
35
|
+
it do
|
36
|
+
file = Saviour::File.new(uploader_klass, Test.create!, :file)
|
37
|
+
expect(file).not_to be_persisted
|
38
|
+
end
|
39
|
+
|
40
|
+
it do
|
41
|
+
file = Saviour::File.new(uploader_klass, Test.create!(file: "/mocked/path"), :file)
|
42
|
+
expect(file).to be_persisted
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "is not changed" do
|
47
|
+
it do
|
48
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
49
|
+
expect(file).not_to be_changed
|
50
|
+
end
|
51
|
+
|
52
|
+
it do
|
53
|
+
file = Saviour::File.new(uploader_klass, Test.create!, :file)
|
54
|
+
expect(file).not_to be_changed
|
55
|
+
end
|
56
|
+
|
57
|
+
it do
|
58
|
+
file = Saviour::File.new(uploader_klass, Test.create!(file: "/mocked/path"), :file)
|
59
|
+
expect(file).not_to be_changed
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#assign" do
|
65
|
+
it "returns the assigned object" do
|
66
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
67
|
+
expect(file.assign(example_file)).to eq example_file
|
68
|
+
end
|
69
|
+
|
70
|
+
it "allows to reset the internal source" do
|
71
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
72
|
+
file.assign(example_file)
|
73
|
+
expect(file.assign(nil)).to be_nil
|
74
|
+
end
|
75
|
+
|
76
|
+
it "shows error if assigned object do not respond to :read" do
|
77
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
78
|
+
expect { file.assign(6) }.to raise_error(RuntimeError)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#write" do
|
83
|
+
it "fails without source" do
|
84
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
85
|
+
expect { file.write }.to raise_error(RuntimeError)
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "filename used" do
|
89
|
+
it "is extracted from original_filename if possible" do
|
90
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
91
|
+
file.assign(double(read: "contents", original_filename: 'original.jpg', path: "/my/path/my_file.zip"))
|
92
|
+
uploader = double
|
93
|
+
allow(file).to receive(:uploader).and_return(uploader)
|
94
|
+
expect(uploader).to receive(:write).with("contents", "original.jpg")
|
95
|
+
file.write
|
96
|
+
end
|
97
|
+
|
98
|
+
it "is extracted from path if possible" do
|
99
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
100
|
+
file.assign(double(read: "contents", path: "/my/path/my_file.zip"))
|
101
|
+
uploader = double
|
102
|
+
allow(file).to receive(:uploader).and_return(uploader)
|
103
|
+
expect(uploader).to receive(:write).with("contents", "my_file.zip")
|
104
|
+
file.write
|
105
|
+
end
|
106
|
+
|
107
|
+
it "is random if cannot be guessed" do
|
108
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
109
|
+
file.assign(double(read: "contents"))
|
110
|
+
allow(SecureRandom).to receive(:hex).and_return("stubbed-random")
|
111
|
+
uploader = double
|
112
|
+
allow(file).to receive(:uploader).and_return(uploader)
|
113
|
+
expect(uploader).to receive(:write).with("contents", "stubbed-random")
|
114
|
+
file.write
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "returns the path" do
|
119
|
+
object = Test.new
|
120
|
+
file = Saviour::File.new(uploader_klass, object, :file)
|
121
|
+
file.assign(double(read: "contents", path: "/my/path/my_file.zip"))
|
122
|
+
uploader = double
|
123
|
+
allow(file).to receive(:uploader).and_return(uploader)
|
124
|
+
expect(uploader).to receive(:write).with("contents", "my_file.zip").and_return("/store/dir/my_file.zip")
|
125
|
+
expect(file.write).to eq "/store/dir/my_file.zip"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "#changed?" do
|
130
|
+
it "is cleared after removing the assignation" do
|
131
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
132
|
+
expect(file).not_to be_changed
|
133
|
+
file.assign(example_file)
|
134
|
+
expect(file).to be_changed
|
135
|
+
file.assign(nil)
|
136
|
+
expect(file).not_to be_changed
|
137
|
+
end
|
138
|
+
|
139
|
+
it "is cleared after persisting" do
|
140
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
141
|
+
file.assign(double(read: "contents", path: "/my/path/my_file.zip"))
|
142
|
+
expect(file).to be_changed
|
143
|
+
|
144
|
+
uploader = double
|
145
|
+
allow(file).to receive(:uploader).and_return(uploader)
|
146
|
+
expect(uploader).to receive(:write)
|
147
|
+
file.write
|
148
|
+
|
149
|
+
expect(file).not_to be_changed
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "#filename" do
|
154
|
+
it "returns the filename of the persisted file" do
|
155
|
+
file = Saviour::File.new(uploader_klass, Test.create!(file: "/mocked/path/file.rar"), :file)
|
156
|
+
expect(file.filename).to eq "file.rar"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#with_copy" do
|
161
|
+
it "provides a copy of the stored file" do
|
162
|
+
file = Saviour::File.new(uploader_klass, Test.create!(file: "/mocked/path/file.rar"), :file)
|
163
|
+
allow(file).to receive(:read).and_return("some contents")
|
164
|
+
|
165
|
+
file.with_copy do |tmpfile|
|
166
|
+
expect(tmpfile.read).to eq "some contents"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
it "deletes the copied file even on exception" do
|
171
|
+
file = Saviour::File.new(uploader_klass, Test.create!(file: "/mocked/path/file.rar"), :file)
|
172
|
+
allow(file).to receive(:read).and_return("some contents")
|
173
|
+
mocked_tmpfile = double(binmode: "", rewind: "", flush: "", write: "")
|
174
|
+
allow(Tempfile).to receive(:open).and_yield(mocked_tmpfile)
|
175
|
+
|
176
|
+
expect(mocked_tmpfile).to receive(:close)
|
177
|
+
expect(mocked_tmpfile).to receive(:delete)
|
178
|
+
|
179
|
+
test_exception = Class.new(Exception)
|
180
|
+
|
181
|
+
begin
|
182
|
+
file.with_copy {|_| raise(test_exception, "some exception within the block") }
|
183
|
+
rescue test_exception
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "#blank?" do
|
189
|
+
it "it's true when not yet assigned nor persisted" do
|
190
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
191
|
+
expect(file).to be_blank
|
192
|
+
end
|
193
|
+
|
194
|
+
it "it's true when not yet assigned but persisted" do
|
195
|
+
file = Saviour::File.new(uploader_klass, Test.create!, :file)
|
196
|
+
expect(file).to be_blank
|
197
|
+
end
|
198
|
+
|
199
|
+
it "it's false when not persisted but assigned" do
|
200
|
+
file = Saviour::File.new(uploader_klass, Test.new, :file)
|
201
|
+
file.assign example_file
|
202
|
+
expect(file).not_to be_blank
|
203
|
+
end
|
204
|
+
|
205
|
+
it "it's false when persisted and assigned" do
|
206
|
+
file = Saviour::File.new(uploader_klass, Test.create!(file: example_file), :file)
|
207
|
+
expect(file).not_to be_blank
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour::LocalStorage do
|
4
|
+
# operate only inside @tmpdir to not mess with test setup, Dir.mktmpdir
|
5
|
+
subject { Saviour::LocalStorage.new(local_prefix: @tmpdir) }
|
6
|
+
|
7
|
+
describe "#write" do
|
8
|
+
let(:filename) { "output.jpg" }
|
9
|
+
let(:destination_path) { File.join("/my/folder", filename) }
|
10
|
+
|
11
|
+
it "writting a new file" do
|
12
|
+
with_test_file("camaloon.jpg") do |file, _|
|
13
|
+
file_destination = File.join(@tmpdir, destination_path)
|
14
|
+
expect(File.file?(file_destination)).to be_falsey
|
15
|
+
|
16
|
+
contents = file.read
|
17
|
+
subject.write(contents, destination_path)
|
18
|
+
|
19
|
+
expect(File.file?(file_destination)).to be_truthy
|
20
|
+
expect(File.read(file_destination)).to eq contents
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "overwritting an existing file" do
|
25
|
+
context "with overwrite protection" do
|
26
|
+
it "raises an error" do
|
27
|
+
path = File.join(@tmpdir, destination_path)
|
28
|
+
|
29
|
+
FileUtils.mkdir_p(File.dirname(path))
|
30
|
+
File.write(path, "some dummy content")
|
31
|
+
expect(File.file?(path)).to be_truthy
|
32
|
+
|
33
|
+
with_test_file("camaloon.jpg") do |file, _|
|
34
|
+
contents = file.read
|
35
|
+
expect { subject.write(contents, destination_path) }.to raise_error(RuntimeError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "without overwrite protection" do
|
41
|
+
subject { Saviour::LocalStorage.new(local_prefix: @tmpdir, overwrite_protection: false) }
|
42
|
+
|
43
|
+
it do
|
44
|
+
path = File.join(@tmpdir, destination_path)
|
45
|
+
|
46
|
+
FileUtils.mkdir_p(File.dirname(path))
|
47
|
+
File.write(path, "some dummy content")
|
48
|
+
expect(File.file?(path)).to be_truthy
|
49
|
+
|
50
|
+
with_test_file("camaloon.jpg") do |file, _|
|
51
|
+
contents = file.read
|
52
|
+
subject.write(contents, destination_path)
|
53
|
+
|
54
|
+
expect(File.file?(path)).to be_truthy
|
55
|
+
expect(File.read(path)).to eq contents
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#read" do
|
63
|
+
it "reads an existing file" do
|
64
|
+
with_test_file("camaloon.jpg") do |file, _|
|
65
|
+
expect(subject.read(File.basename(file.path))).to eq file.read
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "fails if the file do not exists" do
|
70
|
+
expect { subject.read("nope.rar") }.to raise_error(RuntimeError)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#delete" do
|
75
|
+
it "deletes an existing file" do
|
76
|
+
with_test_file("camaloon.jpg") do |file, _|
|
77
|
+
expect(File.file?(file.path)).to be_truthy
|
78
|
+
|
79
|
+
subject.delete(File.basename(file.path))
|
80
|
+
expect(File.file?(file.path)).to be_falsey
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "fails if the file do not exists" do
|
85
|
+
expect { subject.delete("nope.rar") }.to raise_error(RuntimeError)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not leave an empty dir behind" do
|
89
|
+
with_test_file("camaloon.jpg") do |file, _|
|
90
|
+
final_path = File.join(@tmpdir, "some/folder/dest.jpg")
|
91
|
+
|
92
|
+
FileUtils.mkdir_p(File.dirname(final_path))
|
93
|
+
FileUtils.cp file.path, final_path
|
94
|
+
expect(File.file?(final_path)).to be_truthy
|
95
|
+
|
96
|
+
subject.delete("/some/folder/dest.jpg")
|
97
|
+
|
98
|
+
expect(File.file?(final_path)).to be_falsey
|
99
|
+
expect(File.directory?(File.join(@tmpdir, "some/folder"))).to be_falsey
|
100
|
+
expect(File.directory?(File.join(@tmpdir, "some"))).to be_falsey
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#exists?" do
|
106
|
+
it "with existing file" do
|
107
|
+
with_test_file("camaloon.jpg") do |file, _|
|
108
|
+
expect(subject.exists?(File.basename(file.path))).to be_truthy
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it "with no file" do
|
113
|
+
expect(subject.exists?("unexisting_file.zip")).to be_falsey
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#public_url" do
|
118
|
+
let(:destination_path) { "dest/file.jpeg" }
|
119
|
+
|
120
|
+
context do
|
121
|
+
subject { Saviour::LocalStorage.new(local_prefix: @tmpdir) }
|
122
|
+
|
123
|
+
it "fails if not provided the prefix" do
|
124
|
+
with_test_file("camaloon.jpg") do |file, _|
|
125
|
+
expect {
|
126
|
+
subject.public_url(File.basename(file.path))
|
127
|
+
}.to raise_error(RuntimeError)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context do
|
133
|
+
subject { Saviour::LocalStorage.new(local_prefix: @tmpdir, public_url_prefix: -> { "http://mywebsite.com/#{Time.now.hour}/uploads" }) }
|
134
|
+
|
135
|
+
it do
|
136
|
+
allow(Time).to receive(:now).and_return(Time.new(2015, 1, 1, 13, 2, 1))
|
137
|
+
|
138
|
+
with_test_file("camaloon.jpg") do |file, filename|
|
139
|
+
expect(subject.public_url(File.basename(file.path))).to eq "http://mywebsite.com/13/uploads/#{filename}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context do
|
145
|
+
subject { Saviour::LocalStorage.new(local_prefix: @tmpdir, public_url_prefix: "http://mywebsite.com/uploads") }
|
146
|
+
|
147
|
+
it do
|
148
|
+
with_test_file("camaloon.jpg") do |file, filename|
|
149
|
+
expect(subject.public_url(File.basename(file.path))).to eq "http://mywebsite.com/uploads/#{filename}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour::Processors::Digest do
|
4
|
+
describe "#digest_filename" do
|
5
|
+
subject {
|
6
|
+
Class.new { include Saviour::Processors::Digest }.new
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:filename) { "name.jpg" }
|
10
|
+
let(:contents) { "bynary contents for a file" }
|
11
|
+
|
12
|
+
it do
|
13
|
+
_, new_name = subject.digest_filename(contents, filename)
|
14
|
+
expect(new_name).to eq "name-ab54d187b7909ff4bba34777073d4654.jpg"
|
15
|
+
end
|
16
|
+
|
17
|
+
it do
|
18
|
+
_, new_name = subject.digest_filename(contents, filename, separator: '/')
|
19
|
+
expect(new_name).to eq "name/ab54d187b7909ff4bba34777073d4654.jpg"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour::S3Storage do
|
4
|
+
subject { Saviour::S3Storage.new(bucket: "fake-bucket", aws_access_key_id: "stub", aws_secret_access_key: "stub", public_url_prefix: "https://fake-bucket.s3.amazonaws.com") }
|
5
|
+
let!(:mocked_s3) { MockedS3Helper.new }
|
6
|
+
before { mocked_s3.start!(bucket_name: "fake-bucket") }
|
7
|
+
|
8
|
+
context do
|
9
|
+
it "fails when no keys are provided" do
|
10
|
+
expect {
|
11
|
+
Saviour::S3Storage.new(bucket: "fake-bucket")
|
12
|
+
}.to raise_error(ArgumentError)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "fails when the bucket doesn't exists" do
|
16
|
+
expect {
|
17
|
+
Saviour::S3Storage.new(bucket: "no-bucket", aws_access_key_id: "stub", aws_secret_access_key: "stub")
|
18
|
+
}.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#write" do
|
23
|
+
let(:destination_path) { "my/folder/file.jpeg" }
|
24
|
+
|
25
|
+
it "writting a new file" do
|
26
|
+
with_test_file("camaloon.jpg") do |file, _|
|
27
|
+
expect(mocked_s3.exists?(destination_path)).to be_falsey
|
28
|
+
|
29
|
+
contents = file.read
|
30
|
+
subject.write(contents, destination_path)
|
31
|
+
|
32
|
+
expect(mocked_s3.read(destination_path)).to eq contents
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "overwritting" do
|
37
|
+
context "without overwrite protection" do
|
38
|
+
subject {
|
39
|
+
Saviour::S3Storage.new(
|
40
|
+
bucket: "fake-bucket",
|
41
|
+
aws_access_key_id: "stub",
|
42
|
+
aws_secret_access_key: "stub",
|
43
|
+
public_url_prefix: "https://fake-bucket.s3.amazonaws.com",
|
44
|
+
overwrite_protection: false
|
45
|
+
)
|
46
|
+
}
|
47
|
+
|
48
|
+
it "overwrites the existing file" do
|
49
|
+
mocked_s3.write("some dummy contents", destination_path)
|
50
|
+
expect(mocked_s3.exists?(destination_path)).to be_truthy
|
51
|
+
|
52
|
+
with_test_file("camaloon.jpg") do |file, _|
|
53
|
+
contents = file.read
|
54
|
+
subject.write(contents, destination_path)
|
55
|
+
expect(mocked_s3.read(destination_path)).to eq contents
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with overwrite protection" do
|
61
|
+
it "raises an exception" do
|
62
|
+
mocked_s3.write("some dummy contents", destination_path)
|
63
|
+
expect(mocked_s3.exists?(destination_path)).to be_truthy
|
64
|
+
|
65
|
+
with_test_file("camaloon.jpg") do |file, _|
|
66
|
+
contents = file.read
|
67
|
+
expect { subject.write(contents, destination_path) }.to raise_error(RuntimeError)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "ignores leading slash" do
|
74
|
+
subject.write("trash contents", "/folder/file.out")
|
75
|
+
expect(subject.exists?("folder/file.out")).to be_truthy
|
76
|
+
expect(subject.exists?("/folder/file.out")).to be_truthy
|
77
|
+
expect(subject.exists?("////folder/file.out")).to be_truthy
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#read" do
|
82
|
+
let(:destination_path) { "dest/file.jpeg" }
|
83
|
+
|
84
|
+
it "reads an existing file" do
|
85
|
+
with_test_file("camaloon.jpg") do |file, _|
|
86
|
+
contents = file.read
|
87
|
+
|
88
|
+
mocked_s3.write(contents, destination_path)
|
89
|
+
expect(subject.read(destination_path)).to eq contents
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "fails if the file do not exists" do
|
94
|
+
expect { subject.read("nope.rar") }.to raise_error(RuntimeError)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#delete" do
|
99
|
+
let(:destination_path) { "dest/file.jpeg" }
|
100
|
+
|
101
|
+
it "deletes an existing file" do
|
102
|
+
with_test_file("camaloon.jpg") do |file, _|
|
103
|
+
contents = file.read
|
104
|
+
mocked_s3.write(contents, destination_path)
|
105
|
+
|
106
|
+
expect(mocked_s3.exists?(destination_path)).to be_truthy
|
107
|
+
subject.delete("/dest/file.jpeg")
|
108
|
+
expect(mocked_s3.exists?(destination_path)).to be_falsey
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it "fails if the file do not exists" do
|
113
|
+
expect { subject.delete("nope.rar") }.to raise_error(RuntimeError)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#exists?" do
|
118
|
+
let(:destination_path) { "dest/file.jpeg" }
|
119
|
+
|
120
|
+
it "with existing file" do
|
121
|
+
with_test_file("camaloon.jpg") do |file, _|
|
122
|
+
contents = file.read
|
123
|
+
mocked_s3.write(contents, destination_path)
|
124
|
+
expect(subject.exists?(destination_path)).to be_truthy
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "with no file" do
|
129
|
+
expect(subject.exists?("unexisting_file.zip")).to be_falsey
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#public_url" do
|
134
|
+
let(:destination_path) { "dest/file.jpeg" }
|
135
|
+
|
136
|
+
context do
|
137
|
+
subject { Saviour::S3Storage.new(bucket: "fake-bucket", aws_access_key_id: "stub", aws_secret_access_key: "stub") }
|
138
|
+
|
139
|
+
it "fails if not provided the prefix" do
|
140
|
+
with_test_file("camaloon.jpg") do |file, _|
|
141
|
+
contents = file.read
|
142
|
+
mocked_s3.write(contents, destination_path)
|
143
|
+
expect { subject.public_url(destination_path) }.to raise_error(RuntimeError)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context do
|
149
|
+
subject { Saviour::S3Storage.new(bucket: "fake-bucket", aws_access_key_id: "stub", aws_secret_access_key: "stub", public_url_prefix: -> { "https://#{Time.now.hour}.s3.amazonaws.com" }) }
|
150
|
+
|
151
|
+
it "allow to use a lambda for dynamic url prefixes" do
|
152
|
+
allow(Time).to receive(:now).and_return(Time.new(2015, 1, 1, 13, 2, 1))
|
153
|
+
|
154
|
+
with_test_file("camaloon.jpg") do |file, _|
|
155
|
+
contents = file.read
|
156
|
+
mocked_s3.write(contents, destination_path)
|
157
|
+
expect(subject.public_url(destination_path)).to eq "https://13.s3.amazonaws.com/dest/file.jpeg"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it do
|
163
|
+
with_test_file("camaloon.jpg") do |file, _|
|
164
|
+
contents = file.read
|
165
|
+
mocked_s3.write(contents, destination_path)
|
166
|
+
expect(subject.public_url(destination_path)).to eq "https://fake-bucket.s3.amazonaws.com/dest/file.jpeg"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|