leifcr-refile 0.6.3
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/app/assets/javascripts/refile.js +125 -0
- data/config/locales/en.yml +10 -0
- data/config/routes.rb +5 -0
- data/lib/refile.rb +510 -0
- data/lib/refile/app.rb +186 -0
- data/lib/refile/attacher.rb +190 -0
- data/lib/refile/attachment.rb +108 -0
- data/lib/refile/attachment/active_record.rb +133 -0
- data/lib/refile/attachment_definition.rb +83 -0
- data/lib/refile/backend/file_system.rb +120 -0
- data/lib/refile/backend/s3.rb +1 -0
- data/lib/refile/backend_macros.rb +45 -0
- data/lib/refile/custom_logger.rb +48 -0
- data/lib/refile/file.rb +102 -0
- data/lib/refile/file_double.rb +13 -0
- data/lib/refile/image_processing.rb +1 -0
- data/lib/refile/rails.rb +54 -0
- data/lib/refile/rails/attachment_helper.rb +121 -0
- data/lib/refile/random_hasher.rb +11 -0
- data/lib/refile/signature.rb +36 -0
- data/lib/refile/simple_form.rb +17 -0
- data/lib/refile/type.rb +28 -0
- data/lib/refile/version.rb +3 -0
- data/spec/refile/active_record_helper.rb +35 -0
- data/spec/refile/app_spec.rb +424 -0
- data/spec/refile/attachment/active_record_spec.rb +568 -0
- data/spec/refile/attachment_helper_spec.rb +78 -0
- data/spec/refile/attachment_spec.rb +589 -0
- data/spec/refile/backend/file_system_spec.rb +5 -0
- data/spec/refile/backend_examples.rb +228 -0
- data/spec/refile/backend_macros_spec.rb +83 -0
- data/spec/refile/custom_logger_spec.rb +21 -0
- data/spec/refile/features/direct_upload_spec.rb +63 -0
- data/spec/refile/features/multiple_upload_spec.rb +122 -0
- data/spec/refile/features/normal_upload_spec.rb +144 -0
- data/spec/refile/features/presigned_upload_spec.rb +31 -0
- data/spec/refile/features/simple_form_spec.rb +8 -0
- data/spec/refile/fixtures/hello.txt +1 -0
- data/spec/refile/fixtures/image.jpg +0 -0
- data/spec/refile/fixtures/large.txt +44 -0
- data/spec/refile/fixtures/monkey.txt +1 -0
- data/spec/refile/fixtures/world.txt +1 -0
- data/spec/refile/spec_helper.rb +72 -0
- data/spec/refile_spec.rb +355 -0
- metadata +143 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
require "refile/rails/attachment_helper"
|
2
|
+
require "refile/active_record_helper"
|
3
|
+
require "refile/attachment/active_record"
|
4
|
+
require "action_view"
|
5
|
+
|
6
|
+
describe Refile::AttachmentHelper do
|
7
|
+
include Refile::AttachmentHelper
|
8
|
+
include ActionView::Helpers::AssetTagHelper
|
9
|
+
include ActionView::Helpers::FormHelper
|
10
|
+
|
11
|
+
let(:klass) do
|
12
|
+
Class.new(ActiveRecord::Base) do
|
13
|
+
self.table_name = :posts
|
14
|
+
|
15
|
+
def self.name
|
16
|
+
"Post"
|
17
|
+
end
|
18
|
+
|
19
|
+
attachment :document
|
20
|
+
end
|
21
|
+
end
|
22
|
+
let(:attachment_path) { "/attachments/00cc2633d08c6045485f1fae2cd6d4de20a5a159/store/xxx/document" }
|
23
|
+
|
24
|
+
before do
|
25
|
+
allow(Refile).to receive(:secret_key).and_return("xxxxxxxxxxx")
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#attachment_image_tag" do
|
29
|
+
let(:src) { attachment_image_tag(klass.new(document_id: "xxx"), :document)[/src="(\S+)"/, 1] }
|
30
|
+
|
31
|
+
it "builds with path" do
|
32
|
+
allow(Refile).to receive(:app_host).and_return(nil)
|
33
|
+
expect(src).to eq attachment_path
|
34
|
+
end
|
35
|
+
|
36
|
+
it "builds with host" do
|
37
|
+
expect(src).to eq "http://localhost:56120#{attachment_path}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#attachment_field" do
|
42
|
+
context "with index given" do
|
43
|
+
let(:html) { Capybara.string(attachment_field("post", :document, object: klass.new, index: 0)) }
|
44
|
+
|
45
|
+
it "generates file and hidden inputs with identical names" do
|
46
|
+
field_name = "post[0][document]"
|
47
|
+
expect(html).to have_field(field_name, type: "file")
|
48
|
+
expect(html).to have_selector(:css, "input[name='#{field_name}'][type=hidden]", visible: false, count: 1)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#attachment_cache_field" do
|
54
|
+
context "with index given" do
|
55
|
+
let(:html) { Capybara.string(attachment_cache_field("post", :document, object: klass.new, index: 0)) }
|
56
|
+
|
57
|
+
it "generates hidden input with given index" do
|
58
|
+
expect(html).to have_selector(:css, "input[name='post[0][document]'][type=hidden]", visible: false)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "with reference given" do
|
63
|
+
let(:html) { Capybara.string(attachment_cache_field("post", :document, object: klass.new, data: { reference: "xyz" })) }
|
64
|
+
|
65
|
+
it "generates hidden input with given reference" do
|
66
|
+
expect(html).to have_selector(:css, "input[data-reference=xyz]", visible: false)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "without reference given" do
|
71
|
+
let(:html) { Capybara.string(attachment_cache_field("post", :document, object: klass.new)) }
|
72
|
+
|
73
|
+
it "generates hidden input with a random reference" do
|
74
|
+
expect(html).to have_selector(:css, "input[data-reference]", visible: false)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,589 @@
|
|
1
|
+
describe Refile::Attachment do
|
2
|
+
let(:options) { {} }
|
3
|
+
let(:klass) do
|
4
|
+
opts = options
|
5
|
+
Class.new do
|
6
|
+
extend Refile::Attachment
|
7
|
+
|
8
|
+
attr_accessor :document_id, :document_filename, :document_size, :document_content_type
|
9
|
+
|
10
|
+
attachment :document, **opts
|
11
|
+
end
|
12
|
+
end
|
13
|
+
let(:instance) { klass.new }
|
14
|
+
|
15
|
+
describe ":name=" do
|
16
|
+
it "receives a file, caches it and sets the _id parameter" do
|
17
|
+
instance.document = Refile::FileDouble.new("hello", "foo.txt", content_type: "text/plain")
|
18
|
+
|
19
|
+
expect(instance.document.read).to eq("hello")
|
20
|
+
|
21
|
+
expect(instance.document_attacher.data[:filename]).to eq("foo.txt")
|
22
|
+
expect(instance.document_attacher.data[:size]).to eq(5)
|
23
|
+
expect(instance.document_attacher.data[:content_type]).to eq("text/plain")
|
24
|
+
|
25
|
+
expect(instance.document_filename).to eq("foo.txt")
|
26
|
+
expect(instance.document_size).to eq(5)
|
27
|
+
expect(instance.document_content_type).to eq("text/plain")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "receives serialized data and retrieves file from it" do
|
31
|
+
file = Refile.cache.upload(Refile::FileDouble.new("hello"))
|
32
|
+
instance.document = { id: file.id, filename: "foo.txt", content_type: "text/plain", size: 5 }.to_json
|
33
|
+
|
34
|
+
expect(instance.document.read).to eq("hello")
|
35
|
+
|
36
|
+
expect(instance.document_attacher.data[:filename]).to eq("foo.txt")
|
37
|
+
expect(instance.document_attacher.data[:size]).to eq(5)
|
38
|
+
expect(instance.document_attacher.data[:content_type]).to eq("text/plain")
|
39
|
+
|
40
|
+
expect(instance.document_filename).to eq("foo.txt")
|
41
|
+
expect(instance.document_size).to eq(5)
|
42
|
+
expect(instance.document_content_type).to eq("text/plain")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "receives parsed data and retrieves file from it" do
|
46
|
+
file = Refile.cache.upload(Refile::FileDouble.new("hello"))
|
47
|
+
instance.document = { id: file.id, filename: "foo.txt", content_type: "text/plain", size: 5 }
|
48
|
+
|
49
|
+
expect(instance.document.read).to eq("hello")
|
50
|
+
|
51
|
+
expect(instance.document_attacher.data[:filename]).to eq("foo.txt")
|
52
|
+
expect(instance.document_attacher.data[:size]).to eq(5)
|
53
|
+
expect(instance.document_attacher.data[:content_type]).to eq("text/plain")
|
54
|
+
|
55
|
+
expect(instance.document_filename).to eq("foo.txt")
|
56
|
+
expect(instance.document_size).to eq(5)
|
57
|
+
expect(instance.document_content_type).to eq("text/plain")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does nothing when assigned string lacks an id" do
|
61
|
+
instance.document = { size: 5 }.to_json
|
62
|
+
|
63
|
+
expect(instance.document).to be_nil
|
64
|
+
expect(instance.document_size).to be_nil
|
65
|
+
end
|
66
|
+
|
67
|
+
it "does nothing when assigned string is not valid JSON" do
|
68
|
+
instance.document = "size:f{oo}"
|
69
|
+
|
70
|
+
expect(instance.document).to be_nil
|
71
|
+
expect(instance.document_size).to be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it "accepts nil" do
|
75
|
+
instance.document = nil
|
76
|
+
expect(instance.document).to be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "removes a document when assigned nil" do
|
80
|
+
instance.document = Refile::FileDouble.new("hello", "foo.txt", content_type: "text/plain")
|
81
|
+
instance.document = nil
|
82
|
+
expect(instance.document).to be_nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe ":name" do
|
87
|
+
it "gets a file from the store" do
|
88
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
89
|
+
instance.document_id = file.id
|
90
|
+
|
91
|
+
expect(instance.document.id).to eq(file.id)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "complains when `id` attribute not readable" do
|
95
|
+
klass.class_eval do
|
96
|
+
undef :document_id
|
97
|
+
end
|
98
|
+
|
99
|
+
expect do
|
100
|
+
instance.document
|
101
|
+
end.to raise_error(NoMethodError)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe ":url" do
|
106
|
+
it "generates URL with extra options" do
|
107
|
+
allow(Refile).to receive(:token).and_return("token")
|
108
|
+
|
109
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
110
|
+
instance.document_id = file.id
|
111
|
+
|
112
|
+
expect(instance.document_url("fill", 800, 800)).to eq("http://localhost:56120/attachments/token/store/fill/800/800/#{file.id}/document")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "presigned_:name_url=" do
|
117
|
+
it "generates presigned URL" do
|
118
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
119
|
+
instance.document_id = file.id
|
120
|
+
|
121
|
+
allow(Refile.store).to receive_message_chain(:object, :presigned_url).with(file.id).with(:get, expires_in: 900).and_return("PRESIGNED_URL")
|
122
|
+
expect(instance.presigned_document_url).to eq("PRESIGNED_URL")
|
123
|
+
end
|
124
|
+
|
125
|
+
it "generates presigned URL with custom expiration" do
|
126
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
127
|
+
instance.document_id = file.id
|
128
|
+
|
129
|
+
allow(Refile.store).to receive_message_chain(:object, :presigned_url).with(file.id).with(:get, expires_in: 901).and_return("PRESIGNED_URL")
|
130
|
+
expect(instance.presigned_document_url(901)).to eq("PRESIGNED_URL")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "does nothing when id is nill" do
|
134
|
+
expect(instance.presigned_document_url).to be_nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "remote_:name_url=" do
|
139
|
+
it "does nothing when nil is assigned" do
|
140
|
+
instance.remote_document_url = nil
|
141
|
+
expect(instance.document).to be_nil
|
142
|
+
end
|
143
|
+
|
144
|
+
it "does nothing when empty string is assigned" do
|
145
|
+
instance.remote_document_url = nil
|
146
|
+
expect(instance.document).to be_nil
|
147
|
+
end
|
148
|
+
|
149
|
+
context "without redirects" do
|
150
|
+
before(:each) do
|
151
|
+
stub_request(:get, "http://www.example.com/some_file.txt").to_return(
|
152
|
+
status: 200,
|
153
|
+
body: "abc",
|
154
|
+
headers: { "Content-Length" => 3, "Content-Type" => "text/plain" }
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "downloads file, caches it and sets the _id parameter and metadata" do
|
159
|
+
instance.remote_document_url = "http://www.example.com/some_file.txt"
|
160
|
+
expect(instance.document.read).to eq("abc")
|
161
|
+
|
162
|
+
expect(instance.document_attacher.data[:filename]).to eq("some_file.txt")
|
163
|
+
expect(instance.document_attacher.data[:size]).to eq(3)
|
164
|
+
expect(instance.document_attacher.data[:content_type]).to eq("text/plain")
|
165
|
+
|
166
|
+
expect(instance.document_filename).to eq("some_file.txt")
|
167
|
+
expect(instance.document_size).to eq(3)
|
168
|
+
expect(instance.document_content_type).to eq("text/plain")
|
169
|
+
|
170
|
+
expect(Refile.cache.get(instance.document.id).read).to eq("abc")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "with redirects" do
|
175
|
+
before(:each) do
|
176
|
+
stub_request(:get, "http://www.example.com/1").to_return(status: 302, headers: { "Location" => "http://www.example.com/2" })
|
177
|
+
stub_request(:get, "http://www.example.com/2").to_return(status: 200, body: "woop", headers: { "Content-Length" => 4 })
|
178
|
+
stub_request(:get, "http://www.example.com/loop").to_return(status: 302, headers: { "Location" => "http://www.example.com/loop" })
|
179
|
+
end
|
180
|
+
|
181
|
+
it "follows redirects and fetches the file, caches it and sets the _id parameter" do
|
182
|
+
instance.remote_document_url = "http://www.example.com/1"
|
183
|
+
expect(instance.document.read).to eq("woop")
|
184
|
+
expect(Refile.cache.get(instance.document.id).read).to eq("woop")
|
185
|
+
end
|
186
|
+
|
187
|
+
context "when errors enabled" do
|
188
|
+
let(:options) { { raise_errors: true } }
|
189
|
+
it "handles redirect loops by trowing errors" do
|
190
|
+
expect do
|
191
|
+
instance.remote_document_url = "http://www.example.com/loop"
|
192
|
+
end.to raise_error(RestClient::Exception)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when errors disabled" do
|
197
|
+
let(:options) { { raise_errors: false } }
|
198
|
+
it "handles redirect loops by setting generic download error" do
|
199
|
+
expect do
|
200
|
+
instance.remote_document_url = "http://www.example.com/loop"
|
201
|
+
end.not_to raise_error
|
202
|
+
expect(instance.document_attacher.errors).to eq([:download_failed])
|
203
|
+
expect(instance.document).to be_nil
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe ":name_attacher.store!" do
|
210
|
+
it "puts a cached file into the store" do
|
211
|
+
instance.document = Refile::FileDouble.new("hello")
|
212
|
+
cache = instance.document
|
213
|
+
|
214
|
+
instance.document_attacher.store!
|
215
|
+
|
216
|
+
expect(Refile.store.get(instance.document_id).read).to eq("hello")
|
217
|
+
expect(Refile.store.get(instance.document.id).read).to eq("hello")
|
218
|
+
|
219
|
+
expect(instance.document.read).to eq("hello")
|
220
|
+
expect(instance.document_size).to eq(5)
|
221
|
+
expect(Refile.cache.get(cache.id).exists?).to be_falsy
|
222
|
+
end
|
223
|
+
|
224
|
+
it "complains when `id` attribute not writable" do
|
225
|
+
instance.document = Refile::FileDouble.new("hello")
|
226
|
+
|
227
|
+
klass.class_eval do
|
228
|
+
undef :document_id=
|
229
|
+
end
|
230
|
+
|
231
|
+
expect do
|
232
|
+
instance.document_attacher.store!
|
233
|
+
end.to raise_error(NoMethodError)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "does nothing when not cached" do
|
237
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
238
|
+
instance.document_id = file.id
|
239
|
+
|
240
|
+
instance.document_attacher.store!
|
241
|
+
|
242
|
+
expect(Refile.store.get(instance.document_id).read).to eq("hello")
|
243
|
+
expect(Refile.store.get(instance.document.id).read).to eq("hello")
|
244
|
+
end
|
245
|
+
|
246
|
+
it "overwrites previously stored file" do
|
247
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
248
|
+
instance.document_id = file.id
|
249
|
+
|
250
|
+
instance.document = Refile::FileDouble.new("world")
|
251
|
+
cache = instance.document
|
252
|
+
|
253
|
+
instance.document_attacher.store!
|
254
|
+
|
255
|
+
expect(Refile.store.get(instance.document_id).read).to eq("world")
|
256
|
+
expect(Refile.store.get(instance.document.id).read).to eq("world")
|
257
|
+
|
258
|
+
expect(instance.document.read).to eq("world")
|
259
|
+
expect(Refile.cache.get(cache.id).exists?).to be_falsy
|
260
|
+
expect(Refile.store.get(file.id).exists?).to be_falsy
|
261
|
+
end
|
262
|
+
|
263
|
+
it "removes an uploaded file when remove? returns true" do
|
264
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
265
|
+
instance.document_id = file.id
|
266
|
+
|
267
|
+
instance.document_attacher.remove = true
|
268
|
+
instance.document_attacher.store!
|
269
|
+
|
270
|
+
expect(instance.document_id).to be_nil
|
271
|
+
expect(Refile.store.exists?(file.id)).to be_falsy
|
272
|
+
end
|
273
|
+
|
274
|
+
it "removes metadata when remove? returns true" do
|
275
|
+
file = Refile.store.upload(Refile::FileDouble.new("hello"))
|
276
|
+
instance.document_id = file.id
|
277
|
+
instance.document_size = file.size
|
278
|
+
instance.document_filename = "foo"
|
279
|
+
instance.document_content_type = "bar"
|
280
|
+
|
281
|
+
instance.document_attacher.remove = true
|
282
|
+
instance.document_attacher.store!
|
283
|
+
|
284
|
+
expect(instance.document_id).to be_nil
|
285
|
+
expect(instance.document_size).to be_nil
|
286
|
+
expect(instance.document_filename).to be_nil
|
287
|
+
expect(instance.document_content_type).to be_nil
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
describe ":name_attacher.delete!" do
|
292
|
+
it "deletes a stored file" do
|
293
|
+
instance.document = Refile::FileDouble.new("hello")
|
294
|
+
instance.document_attacher.store!
|
295
|
+
file = instance.document
|
296
|
+
|
297
|
+
instance.document_attacher.delete!
|
298
|
+
|
299
|
+
expect(Refile.store.exists?(file.id)).to be_falsy
|
300
|
+
end
|
301
|
+
|
302
|
+
it "deletes a cached file" do
|
303
|
+
instance.document = Refile::FileDouble.new("hello")
|
304
|
+
file = instance.document
|
305
|
+
|
306
|
+
instance.document_attacher.delete!
|
307
|
+
|
308
|
+
expect(Refile.cache.exists?(file.id)).to be_falsy
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
describe ":name_attacher.remove?" do
|
313
|
+
it "should be true when the value is truthy" do
|
314
|
+
instance.document_attacher.remove = true
|
315
|
+
expect(instance.document_attacher.remove?).to be_truthy
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should be false when the value is falsey" do
|
319
|
+
instance.document_attacher.remove = false
|
320
|
+
expect(instance.document_attacher.remove?).to be_falsy
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should be false when the value is ''" do
|
324
|
+
instance.document_attacher.remove = ""
|
325
|
+
expect(instance.document_attacher.remove?).to be_falsy
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should be false when the value is '0'" do
|
329
|
+
instance.document_attacher.remove = "0"
|
330
|
+
expect(instance.document_attacher.remove?).to be_falsy
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should be false when the value is 'false'" do
|
334
|
+
instance.document_attacher.remove = "false"
|
335
|
+
expect(instance.document_attacher.remove?).to be_falsy
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe ":name_attacher.valid?" do
|
340
|
+
let(:options) { { type: :image, raise_errors: false } }
|
341
|
+
|
342
|
+
it "returns false if no file is attached" do
|
343
|
+
expect(instance.document_attacher.valid?).to be_falsy
|
344
|
+
end
|
345
|
+
|
346
|
+
it "returns true if valid file is attached" do
|
347
|
+
file = Refile::FileDouble.new("hello", content_type: "image/png")
|
348
|
+
|
349
|
+
instance.document = file
|
350
|
+
|
351
|
+
expect(instance.document_attacher.valid?).to be_truthy
|
352
|
+
end
|
353
|
+
|
354
|
+
it "returns false and sets errors if invalid file is attached" do
|
355
|
+
file = Refile::FileDouble.new("hello", content_type: "text/plain")
|
356
|
+
|
357
|
+
instance.document = file
|
358
|
+
|
359
|
+
expect(instance.document_attacher.valid?).to be_falsy
|
360
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_content_type, anything]]
|
361
|
+
end
|
362
|
+
|
363
|
+
it "returns false and sets errors if file with zero byte is uploaded" do
|
364
|
+
file = Refile::FileDouble.new("", "hello", content_type: "image/png")
|
365
|
+
instance.document = file
|
366
|
+
|
367
|
+
expect(instance.document_attacher.valid?).to be_falsy
|
368
|
+
expect(instance.document_attacher.errors).to eq([:zero_byte_detected])
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe ":name_attacher.extension" do
|
373
|
+
it "is nil when not inferrable" do
|
374
|
+
file = Refile::FileDouble.new("hello")
|
375
|
+
instance.document = file
|
376
|
+
expect(instance.document_attacher.extension).to be_nil
|
377
|
+
end
|
378
|
+
|
379
|
+
it "is inferred from the filename" do
|
380
|
+
file = Refile::FileDouble.new("hello", "hello.txt")
|
381
|
+
instance.document = file
|
382
|
+
expect(instance.document_attacher.extension).to eq("txt")
|
383
|
+
end
|
384
|
+
|
385
|
+
it "is inferred from the content type" do
|
386
|
+
file = Refile::FileDouble.new("hello", content_type: "image/png")
|
387
|
+
instance.document = file
|
388
|
+
expect(instance.document_attacher.extension).to eq("png")
|
389
|
+
end
|
390
|
+
|
391
|
+
it "returns nil with unknown content type" do
|
392
|
+
file = Refile::FileDouble.new("hello", content_type: "foo/doesnotexist")
|
393
|
+
instance.document = file
|
394
|
+
expect(instance.document_attacher.extension).to be_nil
|
395
|
+
end
|
396
|
+
|
397
|
+
it "is nil when filename has no extension" do
|
398
|
+
file = Refile::FileDouble.new("hello", "hello")
|
399
|
+
instance.document = file
|
400
|
+
expect(instance.document_attacher.extension).to be_nil
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
describe ":name_attacher.basename" do
|
405
|
+
it "is nil when not inferrable" do
|
406
|
+
file = Refile::FileDouble.new("hello")
|
407
|
+
instance.document = file
|
408
|
+
expect(instance.document_attacher.basename).to be_nil
|
409
|
+
end
|
410
|
+
|
411
|
+
it "is inferred from the filename" do
|
412
|
+
file = Refile::FileDouble.new("hello", "hello.txt")
|
413
|
+
instance.document = file
|
414
|
+
expect(instance.document_attacher.basename).to eq("hello")
|
415
|
+
end
|
416
|
+
|
417
|
+
it "returns filename if filename has no extension" do
|
418
|
+
file = Refile::FileDouble.new("hello", "hello")
|
419
|
+
instance.document = file
|
420
|
+
expect(instance.document_attacher.basename).to eq("hello")
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
describe ":name_attacher.error" do
|
425
|
+
let(:options) { { cache: :limited_cache, raise_errors: false } }
|
426
|
+
|
427
|
+
it "is blank when valid file uploaded" do
|
428
|
+
file = Refile::FileDouble.new("hello")
|
429
|
+
instance.document = file
|
430
|
+
|
431
|
+
expect(instance.document_attacher.errors).to be_empty
|
432
|
+
expect(Refile.cache.get(instance.document.id).exists?).to be_truthy
|
433
|
+
end
|
434
|
+
|
435
|
+
it "contains a list of errors when invalid file uploaded" do
|
436
|
+
file = Refile::FileDouble.new("a" * 120)
|
437
|
+
instance.document = file
|
438
|
+
|
439
|
+
expect(instance.document_attacher.errors).to eq([:too_large])
|
440
|
+
expect(instance.document).to be_nil
|
441
|
+
end
|
442
|
+
|
443
|
+
it "is reset when valid file uploaded" do
|
444
|
+
file = Refile::FileDouble.new("a" * 120)
|
445
|
+
instance.document = file
|
446
|
+
|
447
|
+
file = Refile::FileDouble.new("hello")
|
448
|
+
instance.document = file
|
449
|
+
|
450
|
+
expect(instance.document_attacher.errors).to be_empty
|
451
|
+
expect(Refile.cache.get(instance.document.id).exists?).to be_truthy
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
describe ":name_definition.accept" do
|
456
|
+
context "with `extension`" do
|
457
|
+
let(:options) { { extension: %w[jpg png] } }
|
458
|
+
|
459
|
+
it "returns an accept string" do
|
460
|
+
expect(instance.document_attachment_definition.accept).to eq(".jpg,.png")
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
context "with `content_type`" do
|
465
|
+
let(:options) { { content_type: %w[image/jpeg image/png], extension: "zip" } }
|
466
|
+
|
467
|
+
it "returns an accept string" do
|
468
|
+
expect(instance.document_attachment_definition.accept).to eq("image/jpeg,image/png")
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
describe "with option `raise_errors: true" do
|
474
|
+
let(:options) { { cache: :limited_cache, raise_errors: true } }
|
475
|
+
|
476
|
+
it "raises an error when invalid file assigned" do
|
477
|
+
file = Refile::FileDouble.new("a" * 120)
|
478
|
+
expect do
|
479
|
+
instance.document = file
|
480
|
+
end.to raise_error(Refile::Invalid)
|
481
|
+
|
482
|
+
expect(instance.document_attacher.errors).to eq([:too_large])
|
483
|
+
expect(instance.document).to be_nil
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
describe "with option `raise_errors: false" do
|
488
|
+
let(:options) { { cache: :limited_cache, raise_errors: false } }
|
489
|
+
|
490
|
+
it "does not raise an error when invalid file assigned" do
|
491
|
+
file = Refile::FileDouble.new("a" * 120)
|
492
|
+
instance.document = file
|
493
|
+
|
494
|
+
expect(instance.document_attacher.errors).to eq([:too_large])
|
495
|
+
expect(instance.document).to be_nil
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
describe "with option `extension`: %w[txt]`" do
|
500
|
+
let(:options) { { extension: "txt", raise_errors: false } }
|
501
|
+
|
502
|
+
it "allows file with correct extension to be uploaded" do
|
503
|
+
file = Refile::FileDouble.new("hello", "hello.txt")
|
504
|
+
instance.document = file
|
505
|
+
|
506
|
+
expect(instance.document_attacher.errors).to be_empty
|
507
|
+
expect(Refile.cache.get(instance.document.id).exists?).to be_truthy
|
508
|
+
end
|
509
|
+
|
510
|
+
it "sets error when file with other extension is uploaded" do
|
511
|
+
file = Refile::FileDouble.new("hello", "hello.php")
|
512
|
+
instance.document = file
|
513
|
+
|
514
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_extension, anything]]
|
515
|
+
expect(instance.document).to be_nil
|
516
|
+
end
|
517
|
+
|
518
|
+
it "sets error when file with no extension is uploaded" do
|
519
|
+
file = Refile::FileDouble.new("hello")
|
520
|
+
instance.document = file
|
521
|
+
|
522
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_extension, anything]]
|
523
|
+
expect(instance.document).to be_nil
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
describe "with option `content_type: %w[txt]`" do
|
528
|
+
let(:options) { { content_type: "text/plain", raise_errors: false } }
|
529
|
+
|
530
|
+
it "allows file with correct content type to be uploaded" do
|
531
|
+
file = Refile::FileDouble.new("hello", content_type: "text/plain")
|
532
|
+
instance.document = file
|
533
|
+
|
534
|
+
expect(instance.document_attacher.errors).to be_empty
|
535
|
+
expect(Refile.cache.get(instance.document.id).exists?).to be_truthy
|
536
|
+
end
|
537
|
+
|
538
|
+
it "sets error when file with other content type is uploaded" do
|
539
|
+
file = Refile::FileDouble.new("hello", content_type: "application/php")
|
540
|
+
instance.document = file
|
541
|
+
|
542
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_content_type, anything]]
|
543
|
+
expect(instance.document).to be_nil
|
544
|
+
end
|
545
|
+
|
546
|
+
it "sets error when file with no content type is uploaded" do
|
547
|
+
file = Refile::FileDouble.new("hello")
|
548
|
+
instance.document = file
|
549
|
+
|
550
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_content_type, anything]]
|
551
|
+
expect(instance.document).to be_nil
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
describe "with option `type: :image`" do
|
556
|
+
let(:options) { { type: :image, raise_errors: false } }
|
557
|
+
|
558
|
+
it "allows image to be uploaded" do
|
559
|
+
file = Refile::FileDouble.new("hello", content_type: "image/jpeg")
|
560
|
+
instance.document = file
|
561
|
+
|
562
|
+
expect(instance.document_attacher.errors).to be_empty
|
563
|
+
expect(Refile.cache.get(instance.document.id).exists?).to be_truthy
|
564
|
+
end
|
565
|
+
|
566
|
+
it "sets error when file with other content type is uploaded" do
|
567
|
+
file = Refile::FileDouble.new("hello", content_type: "application/php")
|
568
|
+
instance.document = file
|
569
|
+
|
570
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_content_type, anything]]
|
571
|
+
expect(instance.document).to be_nil
|
572
|
+
end
|
573
|
+
|
574
|
+
it "sets error when file with no content type is uploaded" do
|
575
|
+
file = Refile::FileDouble.new("hello")
|
576
|
+
instance.document = file
|
577
|
+
|
578
|
+
expect(instance.document_attacher.errors).to match_array [[:invalid_content_type, anything]]
|
579
|
+
expect(instance.document).to be_nil
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
it "includes the module with methods in an instrospectable way" do
|
584
|
+
expect { puts klass.ancestors }
|
585
|
+
.to output(/Refile::Attachment\(document\)/).to_stdout
|
586
|
+
expect { p klass.ancestors }
|
587
|
+
.to output(/Refile::Attachment\(document\)/).to_stdout
|
588
|
+
end
|
589
|
+
end
|