file_validators 2.1.0 → 3.0.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 +5 -5
- data/.gitignore +2 -0
- data/.rubocop.yml +32 -0
- data/.tool-versions +1 -0
- data/.travis.yml +43 -7
- data/Appraisals +13 -13
- data/CHANGELOG.md +31 -0
- data/Gemfile +2 -0
- data/README.md +26 -18
- data/Rakefile +3 -1
- data/file_validators.gemspec +13 -7
- data/gemfiles/activemodel_3.2.gemfile +2 -1
- data/gemfiles/activemodel_4.0.gemfile +2 -1
- data/gemfiles/{activemodel_4.2.gemfile → activemodel_5.0.gemfile} +1 -1
- data/gemfiles/{activemodel_4.1.gemfile → activemodel_6.0.gemfile} +1 -1
- data/gemfiles/{activemodel_3.0.gemfile → activemodel_6.1.gemfile} +1 -1
- data/lib/file_validators.rb +6 -7
- data/lib/file_validators/error.rb +6 -0
- data/lib/file_validators/mime_type_analyzer.rb +106 -0
- data/lib/file_validators/validators/file_content_type_validator.rb +37 -33
- data/lib/file_validators/validators/file_size_validator.rb +62 -19
- data/lib/file_validators/version.rb +3 -1
- data/spec/integration/combined_validators_integration_spec.rb +3 -1
- data/spec/integration/file_content_type_validation_integration_spec.rb +117 -11
- data/spec/integration/file_size_validator_integration_spec.rb +100 -10
- data/spec/lib/file_validators/mime_type_analyzer_spec.rb +139 -0
- data/spec/lib/file_validators/validators/file_content_type_validator_spec.rb +90 -32
- data/spec/lib/file_validators/validators/file_size_validator_spec.rb +84 -30
- data/spec/spec_helper.rb +5 -0
- data/spec/support/fakeio.rb +17 -0
- data/spec/support/helpers.rb +7 -0
- data/spec/support/matchers/allow_content_type.rb +2 -0
- data/spec/support/matchers/allow_file_size.rb +2 -0
- metadata +86 -28
- data/CHANGELOG.mod +0 -6
- data/gemfiles/activemodel_3.1.gemfile +0 -8
- data/lib/file_validators/utils/content_type_detector.rb +0 -64
- data/lib/file_validators/utils/media_type_spoof_detector.rb +0 -46
- data/spec/lib/file_validators/utils/content_type_detector_spec.rb +0 -27
- data/spec/lib/file_validators/utils/media_type_spoof_detector_spec.rb +0 -31
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'rack/test/uploaded_file'
|
3
5
|
|
@@ -44,7 +46,7 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
44
46
|
before :all do
|
45
47
|
Person.class_eval do
|
46
48
|
Person.reset_callbacks(:validate)
|
47
|
-
validates :avatar, file_size: { in:
|
49
|
+
validates :avatar, file_size: { in: ->(_record) { 20.kilobytes..40.kilobytes } }
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -99,8 +101,8 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
99
101
|
before :all do
|
100
102
|
Person.class_eval do
|
101
103
|
Person.reset_callbacks(:validate)
|
102
|
-
validates :avatar, file_size: { greater_than:
|
103
|
-
less_than:
|
104
|
+
validates :avatar, file_size: { greater_than: ->(_record) { 20.kilobytes },
|
105
|
+
less_than: ->(_record) { 40.kilobytes } }
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
@@ -218,24 +220,35 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
218
220
|
subject { Person.new }
|
219
221
|
|
220
222
|
context 'when file size is less than the specified size' do
|
221
|
-
before
|
223
|
+
before do
|
224
|
+
subject.avatar = '{"filename":"img140910_88338.GIF","content_type":"image/gif","size":13150}'
|
225
|
+
end
|
226
|
+
|
222
227
|
it { is_expected.not_to be_valid }
|
223
228
|
end
|
224
229
|
|
225
230
|
context 'when file size within the specified size' do
|
226
|
-
before
|
231
|
+
before do
|
232
|
+
subject.avatar = '{"filename":"img140910_88338.GIF","content_type":"image/gif","size":33150}'
|
233
|
+
end
|
234
|
+
|
227
235
|
it { is_expected.to be_valid }
|
228
236
|
end
|
229
237
|
|
230
238
|
context 'empty json string' do
|
231
|
-
before { subject.avatar =
|
239
|
+
before { subject.avatar = '{}' }
|
232
240
|
it { is_expected.to be_valid }
|
233
241
|
end
|
234
242
|
|
235
|
-
context 'empty
|
236
|
-
before { subject.avatar =
|
243
|
+
context 'empty string' do
|
244
|
+
before { subject.avatar = '' }
|
237
245
|
it { is_expected.to be_valid }
|
238
246
|
end
|
247
|
+
|
248
|
+
context 'invalid json string' do
|
249
|
+
before { subject.avatar = '{filename":"img140910_88338.GIF","content_type":"image/gif","size":33150}' }
|
250
|
+
it { is_expected.not_to be_valid }
|
251
|
+
end
|
239
252
|
end
|
240
253
|
|
241
254
|
context 'image data as hash' do
|
@@ -249,12 +262,26 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
249
262
|
subject { Person.new }
|
250
263
|
|
251
264
|
context 'when file size is less than the specified size' do
|
252
|
-
before
|
265
|
+
before do
|
266
|
+
subject.avatar = {
|
267
|
+
'filename' => 'img140910_88338.GIF',
|
268
|
+
'content_type' => 'image/gif',
|
269
|
+
'size' => 13_150
|
270
|
+
}
|
271
|
+
end
|
272
|
+
|
253
273
|
it { is_expected.not_to be_valid }
|
254
274
|
end
|
255
275
|
|
256
276
|
context 'when file size within the specified size' do
|
257
|
-
before
|
277
|
+
before do
|
278
|
+
subject.avatar = {
|
279
|
+
'filename' => 'img140910_88338.GIF',
|
280
|
+
'content_type' => 'image/gif',
|
281
|
+
'size' => 33_150
|
282
|
+
}
|
283
|
+
end
|
284
|
+
|
258
285
|
it { is_expected.to be_valid }
|
259
286
|
end
|
260
287
|
|
@@ -263,4 +290,67 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
263
290
|
it { is_expected.to be_valid }
|
264
291
|
end
|
265
292
|
end
|
293
|
+
|
294
|
+
context 'image data as array' do
|
295
|
+
before :all do
|
296
|
+
Person.class_eval do
|
297
|
+
Person.reset_callbacks(:validate)
|
298
|
+
validates :avatar, file_size: { greater_than: 20.kilobytes }
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
subject { Person.new }
|
303
|
+
|
304
|
+
context 'when size of one file is less than the specified size' do
|
305
|
+
before do
|
306
|
+
subject.avatar = [
|
307
|
+
Rack::Test::UploadedFile.new(@cute_path),
|
308
|
+
Rack::Test::UploadedFile.new(@chubby_bubble_path)
|
309
|
+
]
|
310
|
+
end
|
311
|
+
it { is_expected.not_to be_valid }
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'when size of all files is within the specified size' do
|
315
|
+
before do
|
316
|
+
subject.avatar = [
|
317
|
+
Rack::Test::UploadedFile.new(@cute_path),
|
318
|
+
Rack::Test::UploadedFile.new(@cute_path)
|
319
|
+
]
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'is invalid and adds just one error' do
|
323
|
+
expect(subject).not_to be_valid
|
324
|
+
expect(subject.errors.count).to eq 1
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context 'when size of all files is less than the specified size' do
|
329
|
+
before do
|
330
|
+
subject.avatar = [
|
331
|
+
Rack::Test::UploadedFile.new(@chubby_bubble_path),
|
332
|
+
Rack::Test::UploadedFile.new(@chubby_bubble_path)
|
333
|
+
]
|
334
|
+
end
|
335
|
+
|
336
|
+
it { is_expected.to be_valid }
|
337
|
+
end
|
338
|
+
|
339
|
+
context 'one file' do
|
340
|
+
context 'when file size is out of range' do
|
341
|
+
before { subject.avatar = [Rack::Test::UploadedFile.new(@cute_path)] }
|
342
|
+
it { is_expected.not_to be_valid }
|
343
|
+
end
|
344
|
+
|
345
|
+
context 'when file size within range' do
|
346
|
+
before { subject.avatar = [Rack::Test::UploadedFile.new(@chubby_bubble_path)] }
|
347
|
+
it { is_expected.to be_valid }
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'empty array' do
|
352
|
+
before { subject.avatar = [] }
|
353
|
+
it { is_expected.to be_valid }
|
354
|
+
end
|
355
|
+
end
|
266
356
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'rack/test/uploaded_file'
|
5
|
+
|
6
|
+
describe FileValidators::MimeTypeAnalyzer do
|
7
|
+
it 'rises error when tool is invalid' do
|
8
|
+
expect { described_class.new(:invalid) }.to raise_error(FileValidators::Error)
|
9
|
+
end
|
10
|
+
|
11
|
+
before :all do
|
12
|
+
@cute_path = File.join(File.dirname(__FILE__), '../../fixtures/cute.jpg')
|
13
|
+
@spoofed_file_path = File.join(File.dirname(__FILE__), '../../fixtures/spoofed.jpg')
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:cute_image) { Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg') }
|
17
|
+
let(:spoofed_file) { Rack::Test::UploadedFile.new(@spoofed_file_path, 'image/jpeg') }
|
18
|
+
|
19
|
+
describe ':file analyzer' do
|
20
|
+
let(:analyzer) { described_class.new(:file) }
|
21
|
+
|
22
|
+
it 'determines MIME type from file contents' do
|
23
|
+
expect(analyzer.call(cute_image)).to eq('image/jpeg')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns text/plain for unidentified MIME types' do
|
27
|
+
expect(analyzer.call(fakeio('a' * 5 * 1024 * 1024))).to eq('text/plain')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'is able to determine MIME type for spoofed files' do
|
31
|
+
expect(analyzer.call(spoofed_file)).to eq('text/plain')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'is able to determine MIME type for non-files' do
|
35
|
+
expect(analyzer.call(fakeio(cute_image.read))).to eq('image/jpeg')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns nil for empty IOs' do
|
39
|
+
expect(analyzer.call(fakeio(''))).to eq(nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'raises error if file command is not found' do
|
43
|
+
allow(Open3).to receive(:popen3).and_raise(Errno::ENOENT)
|
44
|
+
expect { analyzer.call(fakeio) }.to raise_error(FileValidators::Error, 'file command-line tool is not installed')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe ':fastimage analyzer' do
|
49
|
+
let(:analyzer) { described_class.new(:fastimage) }
|
50
|
+
|
51
|
+
it 'extracts MIME type of any IO' do
|
52
|
+
expect(analyzer.call(cute_image)).to eq('image/jpeg')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns nil for unidentified MIME types' do
|
56
|
+
expect(analyzer.call(fakeio('😃'))).to eq nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns nil for empty IOs' do
|
60
|
+
expect(analyzer.call(fakeio(''))).to eq nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe ':mimemagic analyzer' do
|
65
|
+
let(:analyzer) { described_class.new(:mimemagic) }
|
66
|
+
|
67
|
+
it 'extracts MIME type of any IO' do
|
68
|
+
expect(analyzer.call(cute_image)).to eq('image/jpeg')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns nil for unidentified MIME types' do
|
72
|
+
expect(analyzer.call(fakeio('😃'))).to eq nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns nil for empty IOs' do
|
76
|
+
expect(analyzer.call(fakeio(''))).to eq nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
if RUBY_VERSION >= '2.2.0'
|
81
|
+
describe ':marcel analyzer' do
|
82
|
+
let(:analyzer) { described_class.new(:marcel) }
|
83
|
+
|
84
|
+
it 'extracts MIME type of any IO' do
|
85
|
+
expect(analyzer.call(cute_image)).to eq('image/jpeg')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'returns application/octet-stream for unidentified MIME types' do
|
89
|
+
expect(analyzer.call(fakeio('😃'))).to eq 'application/octet-stream'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns nil for empty IOs' do
|
93
|
+
expect(analyzer.call(fakeio(''))).to eq nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe ':mime_types analyzer' do
|
99
|
+
let(:analyzer) { described_class.new(:mime_types) }
|
100
|
+
|
101
|
+
it 'extract MIME type from the file extension' do
|
102
|
+
expect(analyzer.call(fakeio(filename: 'image.png'))).to eq('image/png')
|
103
|
+
expect(analyzer.call(cute_image)).to eq('image/jpeg')
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'extracts MIME type from file extension when IO is empty' do
|
107
|
+
expect(analyzer.call(fakeio('', filename: 'image.png'))).to eq('image/png')
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'returns nil on unknown extension' do
|
111
|
+
expect(analyzer.call(fakeio(filename: 'file.foo'))).to eq(nil)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'returns nil when input is not a file' do
|
115
|
+
expect(analyzer.call(fakeio)).to eq(nil)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe ':mini_mime analyzer' do
|
120
|
+
let(:analyzer) { described_class.new(:mini_mime) }
|
121
|
+
|
122
|
+
it 'extract MIME type from the file extension' do
|
123
|
+
expect(analyzer.call(fakeio(filename: 'image.png'))).to eq('image/png')
|
124
|
+
expect(analyzer.call(cute_image)).to eq('image/jpeg')
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'extracts MIME type from file extension when IO is empty' do
|
128
|
+
expect(analyzer.call(fakeio('', filename: 'image.png'))).to eq('image/png')
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'returns nil on unkown extension' do
|
132
|
+
expect(analyzer.call(fakeio(filename: 'file.foo'))).to eq(nil)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'returns nil when input is not a file' do
|
136
|
+
expect(analyzer.call(fakeio)).to eq(nil)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe ActiveModel::Validations::FileContentTypeValidator do
|
@@ -17,57 +19,85 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
17
19
|
before { build_validator allow: 'image/jpg' }
|
18
20
|
it { is_expected.to allow_file_content_type('image/jpg', @validator) }
|
19
21
|
end
|
20
|
-
|
22
|
+
|
21
23
|
context 'as an regexp' do
|
22
24
|
before { build_validator allow: /^image\/.*/ }
|
23
25
|
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
context 'as a list' do
|
27
29
|
before { build_validator allow: ['image/png', 'image/jpg', 'image/jpeg'] }
|
28
30
|
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
29
31
|
end
|
30
32
|
|
31
33
|
context 'as a proc' do
|
32
|
-
before { build_validator allow:
|
34
|
+
before { build_validator allow: ->(_record) { ['image/png', 'image/jpg', 'image/jpeg'] } }
|
33
35
|
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
34
36
|
end
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
context 'with a disallowed type' do
|
38
40
|
context 'as a string' do
|
39
41
|
before { build_validator allow: 'image/png' }
|
40
42
|
it { is_expected.not_to allow_file_content_type('image/jpeg', @validator) }
|
41
43
|
end
|
42
|
-
|
44
|
+
|
43
45
|
context 'as a regexp' do
|
44
46
|
before { build_validator allow: /^text\/.*/ }
|
45
47
|
it { is_expected.not_to allow_file_content_type('image/png', @validator) }
|
46
48
|
end
|
47
49
|
|
48
50
|
context 'as a proc' do
|
49
|
-
before { build_validator allow:
|
51
|
+
before { build_validator allow: ->(_record) { /^text\/.*/ } }
|
50
52
|
it { is_expected.not_to allow_file_content_type('image/png', @validator) }
|
51
53
|
end
|
52
|
-
|
54
|
+
|
53
55
|
context 'with :message option' do
|
54
56
|
context 'without interpolation' do
|
55
|
-
before
|
56
|
-
|
57
|
+
before do
|
58
|
+
build_validator allow: 'image/png',
|
59
|
+
message: 'should be a PNG image'
|
60
|
+
end
|
61
|
+
|
62
|
+
it do
|
63
|
+
is_expected.not_to allow_file_content_type(
|
64
|
+
'image/jpeg', @validator,
|
65
|
+
message: 'Avatar should be a PNG image'
|
66
|
+
)
|
67
|
+
end
|
57
68
|
end
|
58
|
-
|
69
|
+
|
59
70
|
context 'with interpolation' do
|
60
|
-
before
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
71
|
+
before do
|
72
|
+
build_validator allow: 'image/png',
|
73
|
+
message: 'should have content type %{types}'
|
74
|
+
end
|
75
|
+
|
76
|
+
it do
|
77
|
+
is_expected.not_to allow_file_content_type(
|
78
|
+
'image/jpeg', @validator,
|
79
|
+
message: 'Avatar should have content type image/png'
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
it do
|
84
|
+
is_expected.to allow_file_content_type(
|
85
|
+
'image/png', @validator,
|
86
|
+
message: 'Avatar should have content type image/png'
|
87
|
+
)
|
88
|
+
end
|
65
89
|
end
|
66
90
|
end
|
67
91
|
|
68
92
|
context 'default message' do
|
69
93
|
before { build_validator allow: 'image/png' }
|
70
|
-
|
94
|
+
|
95
|
+
it do
|
96
|
+
is_expected.not_to allow_file_content_type(
|
97
|
+
'image/jpeg', @validator,
|
98
|
+
message: 'Avatar file should be one of image/png'
|
99
|
+
)
|
100
|
+
end
|
71
101
|
end
|
72
102
|
end
|
73
103
|
end
|
@@ -78,23 +108,23 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
78
108
|
before { build_validator exclude: 'image/gif' }
|
79
109
|
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
80
110
|
end
|
81
|
-
|
111
|
+
|
82
112
|
context 'as an regexp' do
|
83
113
|
before { build_validator exclude: /^text\/.*/ }
|
84
114
|
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
85
115
|
end
|
86
|
-
|
116
|
+
|
87
117
|
context 'as a list' do
|
88
118
|
before { build_validator exclude: ['image/png', 'image/jpg', 'image/jpeg'] }
|
89
119
|
it { is_expected.to allow_file_content_type('image/gif', @validator) }
|
90
120
|
end
|
91
121
|
|
92
122
|
context 'as a proc' do
|
93
|
-
before { build_validator exclude:
|
123
|
+
before { build_validator exclude: ->(_record) { ['image/png', 'image/jpg', 'image/jpeg'] } }
|
94
124
|
it { is_expected.to allow_file_content_type('image/gif', @validator) }
|
95
125
|
end
|
96
126
|
end
|
97
|
-
|
127
|
+
|
98
128
|
context 'with a disallowed type' do
|
99
129
|
context 'as a string' do
|
100
130
|
before { build_validator exclude: 'image/gif' }
|
@@ -107,28 +137,56 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
107
137
|
end
|
108
138
|
|
109
139
|
context 'as an proc' do
|
110
|
-
before { build_validator exclude:
|
140
|
+
before { build_validator exclude: ->(_record) { /^text\/.*/ } }
|
111
141
|
it { is_expected.not_to allow_file_content_type('text/plain', @validator) }
|
112
142
|
end
|
113
|
-
|
143
|
+
|
114
144
|
context 'with :message option' do
|
115
145
|
context 'without interpolation' do
|
116
|
-
before
|
117
|
-
|
146
|
+
before do
|
147
|
+
build_validator exclude: 'image/png',
|
148
|
+
message: 'should not be a PNG image'
|
149
|
+
end
|
150
|
+
|
151
|
+
it do
|
152
|
+
is_expected.not_to allow_file_content_type(
|
153
|
+
'image/png', @validator,
|
154
|
+
message: 'Avatar should not be a PNG image'
|
155
|
+
)
|
156
|
+
end
|
118
157
|
end
|
119
|
-
|
158
|
+
|
120
159
|
context 'with interpolation' do
|
121
|
-
before
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
160
|
+
before do
|
161
|
+
build_validator exclude: 'image/png',
|
162
|
+
message: 'should not have content type %{types}'
|
163
|
+
end
|
164
|
+
|
165
|
+
it do
|
166
|
+
is_expected.not_to allow_file_content_type(
|
167
|
+
'image/png', @validator,
|
168
|
+
message: 'Avatar should not have content type image/png'
|
169
|
+
)
|
170
|
+
end
|
171
|
+
|
172
|
+
it do
|
173
|
+
is_expected.to allow_file_content_type(
|
174
|
+
'image/jpeg', @validator,
|
175
|
+
message: 'Avatar should not have content type image/jpeg'
|
176
|
+
)
|
177
|
+
end
|
126
178
|
end
|
127
179
|
end
|
128
180
|
|
129
181
|
context 'default message' do
|
130
182
|
before { build_validator exclude: 'image/png' }
|
131
|
-
|
183
|
+
|
184
|
+
it do
|
185
|
+
is_expected.not_to allow_file_content_type(
|
186
|
+
'image/png', @validator,
|
187
|
+
message: 'Avatar file cannot be image/png'
|
188
|
+
)
|
189
|
+
end
|
132
190
|
end
|
133
191
|
end
|
134
192
|
end
|
@@ -151,7 +209,7 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
151
209
|
expect { build_validator argument => 'image/jpg' }.not_to raise_error
|
152
210
|
expect { build_validator argument => ['image/jpg'] }.not_to raise_error
|
153
211
|
expect { build_validator argument => /^image\/.*/ }.not_to raise_error
|
154
|
-
expect { build_validator argument =>
|
212
|
+
expect { build_validator argument => ->(_record) { 'image/jpg' } }.not_to raise_error
|
155
213
|
end
|
156
214
|
|
157
215
|
it "raises argument error if :#{argument} is neither a string, array, regexp nor proc" do
|