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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/javascripts/refile.js +125 -0
  3. data/config/locales/en.yml +10 -0
  4. data/config/routes.rb +5 -0
  5. data/lib/refile.rb +510 -0
  6. data/lib/refile/app.rb +186 -0
  7. data/lib/refile/attacher.rb +190 -0
  8. data/lib/refile/attachment.rb +108 -0
  9. data/lib/refile/attachment/active_record.rb +133 -0
  10. data/lib/refile/attachment_definition.rb +83 -0
  11. data/lib/refile/backend/file_system.rb +120 -0
  12. data/lib/refile/backend/s3.rb +1 -0
  13. data/lib/refile/backend_macros.rb +45 -0
  14. data/lib/refile/custom_logger.rb +48 -0
  15. data/lib/refile/file.rb +102 -0
  16. data/lib/refile/file_double.rb +13 -0
  17. data/lib/refile/image_processing.rb +1 -0
  18. data/lib/refile/rails.rb +54 -0
  19. data/lib/refile/rails/attachment_helper.rb +121 -0
  20. data/lib/refile/random_hasher.rb +11 -0
  21. data/lib/refile/signature.rb +36 -0
  22. data/lib/refile/simple_form.rb +17 -0
  23. data/lib/refile/type.rb +28 -0
  24. data/lib/refile/version.rb +3 -0
  25. data/spec/refile/active_record_helper.rb +35 -0
  26. data/spec/refile/app_spec.rb +424 -0
  27. data/spec/refile/attachment/active_record_spec.rb +568 -0
  28. data/spec/refile/attachment_helper_spec.rb +78 -0
  29. data/spec/refile/attachment_spec.rb +589 -0
  30. data/spec/refile/backend/file_system_spec.rb +5 -0
  31. data/spec/refile/backend_examples.rb +228 -0
  32. data/spec/refile/backend_macros_spec.rb +83 -0
  33. data/spec/refile/custom_logger_spec.rb +21 -0
  34. data/spec/refile/features/direct_upload_spec.rb +63 -0
  35. data/spec/refile/features/multiple_upload_spec.rb +122 -0
  36. data/spec/refile/features/normal_upload_spec.rb +144 -0
  37. data/spec/refile/features/presigned_upload_spec.rb +31 -0
  38. data/spec/refile/features/simple_form_spec.rb +8 -0
  39. data/spec/refile/fixtures/hello.txt +1 -0
  40. data/spec/refile/fixtures/image.jpg +0 -0
  41. data/spec/refile/fixtures/large.txt +44 -0
  42. data/spec/refile/fixtures/monkey.txt +1 -0
  43. data/spec/refile/fixtures/world.txt +1 -0
  44. data/spec/refile/spec_helper.rb +72 -0
  45. data/spec/refile_spec.rb +355 -0
  46. 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