paperclip 3.0.3 → 3.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- checksums.yaml +15 -0
- data/.gitignore +2 -1
- data/.travis.yml +3 -0
- data/Appraisals +8 -3
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/NEWS +198 -35
- data/README.md +332 -113
- data/features/basic_integration.feature +24 -12
- data/features/migration.feature +94 -0
- data/features/rake_tasks.feature +2 -3
- data/features/step_definitions/attachment_steps.rb +28 -0
- data/features/step_definitions/rails_steps.rb +94 -8
- data/features/step_definitions/s3_steps.rb +1 -1
- data/features/step_definitions/web_steps.rb +3 -3
- data/features/support/fakeweb.rb +4 -1
- data/features/support/file_helpers.rb +10 -0
- data/features/support/rails.rb +18 -2
- data/gemfiles/3.0.gemfile +2 -2
- data/gemfiles/3.1.gemfile +2 -2
- data/gemfiles/3.2.gemfile +2 -2
- data/gemfiles/4.0.gemfile +11 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +4 -8
- data/lib/paperclip/attachment.rb +96 -43
- data/lib/paperclip/attachment_registry.rb +57 -0
- data/lib/paperclip/callbacks.rb +2 -2
- data/lib/paperclip/content_type_detector.rb +78 -0
- data/lib/paperclip/file_command_content_type_detector.rb +32 -0
- data/lib/paperclip/filename_cleaner.rb +16 -0
- data/lib/paperclip/geometry.rb +66 -30
- data/lib/paperclip/geometry_detector_factory.rb +41 -0
- data/lib/paperclip/geometry_parser_factory.rb +31 -0
- data/lib/paperclip/glue.rb +2 -8
- data/lib/paperclip/has_attached_file.rb +99 -0
- data/lib/paperclip/helpers.rb +12 -15
- data/lib/paperclip/interpolations/plural_cache.rb +17 -0
- data/lib/paperclip/interpolations.rb +15 -5
- data/lib/paperclip/io_adapters/abstract_adapter.rb +45 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +14 -49
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +27 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +18 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +8 -69
- data/lib/paperclip/io_adapters/identity_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/nil_adapter.rb +2 -2
- data/lib/paperclip/io_adapters/stringio_adapter.rb +16 -45
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +17 -40
- data/lib/paperclip/io_adapters/uri_adapter.rb +44 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +1 -5
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +36 -17
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +5 -1
- data/lib/paperclip/matchers.rb +3 -3
- data/lib/paperclip/missing_attachment_styles.rb +11 -16
- data/lib/paperclip/processor.rb +12 -0
- data/lib/paperclip/railtie.rb +5 -1
- data/lib/paperclip/schema.rb +59 -23
- data/lib/paperclip/storage/filesystem.rb +23 -5
- data/lib/paperclip/storage/fog.rb +64 -25
- data/lib/paperclip/storage/s3.rb +93 -52
- data/lib/paperclip/style.rb +2 -2
- data/lib/paperclip/tempfile_factory.rb +21 -0
- data/lib/paperclip/thumbnail.rb +18 -3
- data/lib/paperclip/validators/attachment_content_type_validator.rb +38 -10
- data/lib/paperclip/validators/attachment_presence_validator.rb +8 -8
- data/lib/paperclip/validators/attachment_size_validator.rb +12 -7
- data/lib/paperclip/validators.rb +21 -2
- data/lib/paperclip/version.rb +1 -1
- data/lib/paperclip.rb +15 -44
- data/lib/tasks/paperclip.rake +26 -7
- data/paperclip.gemspec +11 -7
- data/test/attachment_definitions_test.rb +12 -0
- data/test/attachment_processing_test.rb +83 -0
- data/test/attachment_registry_test.rb +77 -0
- data/test/attachment_test.rb +253 -44
- data/test/content_type_detector_test.rb +50 -0
- data/test/file_command_content_type_detector_test.rb +25 -0
- data/test/filename_cleaner_test.rb +14 -0
- data/test/fixtures/animated +0 -0
- data/test/fixtures/animated.unknown +0 -0
- data/test/fixtures/rotated.jpg +0 -0
- data/test/generator_test.rb +26 -24
- data/test/geometry_detector_test.rb +24 -0
- data/test/geometry_parser_test.rb +73 -0
- data/test/geometry_test.rb +55 -4
- data/test/has_attached_file_test.rb +125 -0
- data/test/helper.rb +38 -7
- data/test/integration_test.rb +105 -89
- data/test/interpolations_test.rb +12 -0
- data/test/io_adapters/abstract_adapter_test.rb +58 -0
- data/test/io_adapters/attachment_adapter_test.rb +120 -33
- data/test/io_adapters/data_uri_adapter_test.rb +60 -0
- data/test/io_adapters/empty_string_adapter_test.rb +17 -0
- data/test/io_adapters/file_adapter_test.rb +32 -1
- data/test/io_adapters/stringio_adapter_test.rb +29 -10
- data/test/io_adapters/uploaded_file_adapter_test.rb +53 -5
- data/test/io_adapters/uri_adapter_test.rb +102 -0
- data/test/matchers/validate_attachment_presence_matcher_test.rb +22 -0
- data/test/meta_class_test.rb +32 -0
- data/test/paperclip_missing_attachment_styles_test.rb +4 -8
- data/test/paperclip_test.rb +27 -51
- data/test/plural_cache_test.rb +36 -0
- data/test/processor_test.rb +16 -0
- data/test/rake_test.rb +103 -0
- data/test/schema_test.rb +179 -77
- data/test/storage/filesystem_test.rb +26 -3
- data/test/storage/fog_test.rb +181 -3
- data/test/storage/s3_test.rb +239 -4
- data/test/style_test.rb +18 -14
- data/test/tempfile_factory_test.rb +13 -0
- data/test/thumbnail_test.rb +96 -16
- data/test/validators/attachment_content_type_validator_test.rb +181 -55
- data/test/validators/attachment_size_validator_test.rb +10 -0
- data/test/validators_test.rb +8 -1
- metadata +126 -92
- data/Gemfile.lock +0 -157
- data/features/support/fixtures/.boot_config.rb.swo +0 -0
- data/images.rake +0 -21
- data/lib/.DS_Store +0 -0
- data/lib/paperclip/.DS_Store +0 -0
- data/lib/paperclip/attachment_options.rb +0 -9
- data/lib/paperclip/instance_methods.rb +0 -35
- data/test/attachment_options_test.rb +0 -27
data/test/storage/s3_test.rb
CHANGED
@@ -125,7 +125,70 @@ class S3Test < Test::Unit::TestCase
|
|
125
125
|
should "use the correct key" do
|
126
126
|
assert_equal "avatars/stringio.txt", @dummy.avatar.s3_object.key
|
127
127
|
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "s3_protocol" do
|
131
|
+
["http", :http, ""].each do |protocol|
|
132
|
+
context "as #{protocol.inspect}" do
|
133
|
+
setup do
|
134
|
+
rebuild_model :storage => :s3, :s3_protocol => protocol
|
135
|
+
|
136
|
+
@dummy = Dummy.new
|
137
|
+
end
|
138
|
+
|
139
|
+
should "return the s3_protocol in string" do
|
140
|
+
assert_equal protocol.to_s, @dummy.avatar.s3_protocol
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context ":s3_protocol => 'https'" do
|
147
|
+
setup do
|
148
|
+
rebuild_model :storage => :s3,
|
149
|
+
:s3_credentials => {},
|
150
|
+
:s3_protocol => 'https',
|
151
|
+
:bucket => "bucket",
|
152
|
+
:path => ":attachment/:basename.:extension"
|
153
|
+
@dummy = Dummy.new
|
154
|
+
@dummy.avatar = StringIO.new(".")
|
155
|
+
end
|
156
|
+
|
157
|
+
should "return a url based on an S3 path" do
|
158
|
+
assert_match %r{^https://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context ":s3_protocol => :https" do
|
163
|
+
setup do
|
164
|
+
rebuild_model :storage => :s3,
|
165
|
+
:s3_credentials => {},
|
166
|
+
:s3_protocol => :https,
|
167
|
+
:bucket => "bucket",
|
168
|
+
:path => ":attachment/:basename.:extension"
|
169
|
+
@dummy = Dummy.new
|
170
|
+
@dummy.avatar = StringIO.new(".")
|
171
|
+
end
|
128
172
|
|
173
|
+
should "return a url based on an S3 path" do
|
174
|
+
assert_match %r{^https://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context ":s3_protocol => ''" do
|
179
|
+
setup do
|
180
|
+
rebuild_model :storage => :s3,
|
181
|
+
:s3_credentials => {},
|
182
|
+
:s3_protocol => '',
|
183
|
+
:bucket => "bucket",
|
184
|
+
:path => ":attachment/:basename.:extension"
|
185
|
+
@dummy = Dummy.new
|
186
|
+
@dummy.avatar = StringIO.new(".")
|
187
|
+
end
|
188
|
+
|
189
|
+
should "return a url based on an S3 path" do
|
190
|
+
assert_match %r{^//s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
|
191
|
+
end
|
129
192
|
end
|
130
193
|
|
131
194
|
context "An attachment that uses S3 for storage and has the style in the path" do
|
@@ -175,6 +238,26 @@ class S3Test < Test::Unit::TestCase
|
|
175
238
|
end
|
176
239
|
end
|
177
240
|
|
241
|
+
context "dynamic s3_host_name" do
|
242
|
+
setup do
|
243
|
+
rebuild_model :storage => :s3,
|
244
|
+
:s3_credentials => {},
|
245
|
+
:bucket => "bucket",
|
246
|
+
:path => ":attachment/:basename.:extension",
|
247
|
+
:s3_host_name => lambda {|a| a.instance.value }
|
248
|
+
@dummy = Dummy.new
|
249
|
+
class << @dummy
|
250
|
+
attr_accessor :value
|
251
|
+
end
|
252
|
+
@dummy.avatar = StringIO.new(".")
|
253
|
+
end
|
254
|
+
|
255
|
+
should "use s3_host_name as a proc if available" do
|
256
|
+
@dummy.value = "s3.something.com"
|
257
|
+
assert_equal "http://s3.something.com/bucket/avatars/stringio.txt", @dummy.avatar.url(:original, :timestamp => false)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
178
261
|
context "An attachment that uses S3 for storage and has styles that return different file types" do
|
179
262
|
setup do
|
180
263
|
rebuild_model :styles => { :large => ['500x500#', :jpg] },
|
@@ -209,6 +292,45 @@ class S3Test < Test::Unit::TestCase
|
|
209
292
|
end
|
210
293
|
end
|
211
294
|
|
295
|
+
context "An attachment that uses S3 for storage and has a proc for styles" do
|
296
|
+
setup do
|
297
|
+
rebuild_model :styles => lambda { |attachment| attachment.instance.counter; {:thumbnail => { :geometry => "50x50#", :s3_headers => {'Cache-Control' => 'max-age=31557600'}} }},
|
298
|
+
:storage => :s3,
|
299
|
+
:bucket => "bucket",
|
300
|
+
:path => ":attachment/:style/:basename.:extension",
|
301
|
+
:s3_credentials => {
|
302
|
+
'access_key_id' => "12345",
|
303
|
+
'secret_access_key' => "54321"
|
304
|
+
}
|
305
|
+
|
306
|
+
@file = File.new(fixture_file('5k.png'), 'rb')
|
307
|
+
|
308
|
+
Dummy.class_eval do
|
309
|
+
def counter
|
310
|
+
@counter ||= 0
|
311
|
+
@counter += 1
|
312
|
+
@counter
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
@dummy = Dummy.new
|
317
|
+
@dummy.avatar = @file
|
318
|
+
|
319
|
+
object = stub
|
320
|
+
@dummy.avatar.stubs(:s3_object).with(:original).returns(object)
|
321
|
+
@dummy.avatar.stubs(:s3_object).with(:thumbnail).returns(object)
|
322
|
+
object.expects(:write).with(anything, :content_type => 'image/png', :acl => :public_read)
|
323
|
+
object.expects(:write).with(anything, :content_type => 'image/png', :acl => :public_read, :cache_control => 'max-age=31557600')
|
324
|
+
@dummy.save
|
325
|
+
end
|
326
|
+
|
327
|
+
teardown { @file.close }
|
328
|
+
|
329
|
+
should "succeed" do
|
330
|
+
assert_equal @dummy.counter, 7
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
212
334
|
context "An attachment that uses S3 for storage and has spaces in file name" do
|
213
335
|
setup do
|
214
336
|
rebuild_model :styles => { :large => ['500x500#', :jpg] },
|
@@ -244,8 +366,13 @@ class S3Test < Test::Unit::TestCase
|
|
244
366
|
'secret_access_key' => "54321"
|
245
367
|
}
|
246
368
|
|
247
|
-
|
248
|
-
|
369
|
+
stringio = StringIO.new(".")
|
370
|
+
class << stringio
|
371
|
+
def original_filename
|
372
|
+
"question?mark.png"
|
373
|
+
end
|
374
|
+
end
|
375
|
+
file = Paperclip.io_adapters.for(stringio)
|
249
376
|
@dummy = Dummy.new
|
250
377
|
@dummy.avatar = file
|
251
378
|
@dummy.save
|
@@ -412,6 +539,18 @@ class S3Test < Test::Unit::TestCase
|
|
412
539
|
end
|
413
540
|
end
|
414
541
|
|
542
|
+
context "#expiring_url" do
|
543
|
+
setup { @dummy = Dummy.new }
|
544
|
+
|
545
|
+
context "with no attachment" do
|
546
|
+
setup { assert(!@dummy.avatar.exists?) }
|
547
|
+
|
548
|
+
should "return the default URL" do
|
549
|
+
assert_equal(@dummy.avatar.url, @dummy.avatar.expiring_url)
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
415
554
|
context "Generating a url with an expiration for each style" do
|
416
555
|
setup do
|
417
556
|
rebuild_model :storage => :s3,
|
@@ -532,6 +671,21 @@ class S3Test < Test::Unit::TestCase
|
|
532
671
|
assert_match %r{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
|
533
672
|
end
|
534
673
|
|
674
|
+
should "be rewinded after flush_writes" do
|
675
|
+
@dummy.avatar.instance_eval "def after_flush_writes; end"
|
676
|
+
|
677
|
+
files = @dummy.avatar.queued_for_write.values.each(&:read)
|
678
|
+
@dummy.save
|
679
|
+
assert files.none?(&:eof?), "Expect all the files to be rewinded."
|
680
|
+
end
|
681
|
+
|
682
|
+
should "be removed after after_flush_writes" do
|
683
|
+
paths = @dummy.avatar.queued_for_write.values.map(&:path)
|
684
|
+
@dummy.save
|
685
|
+
assert paths.none?{ |path| File.exists?(path) },
|
686
|
+
"Expect all the files to be deleted."
|
687
|
+
end
|
688
|
+
|
535
689
|
context "and saved" do
|
536
690
|
setup do
|
537
691
|
object = stub
|
@@ -567,7 +721,7 @@ class S3Test < Test::Unit::TestCase
|
|
567
721
|
setup do
|
568
722
|
AWS::S3::S3Object.any_instance.stubs(:exists?).returns(true)
|
569
723
|
AWS::S3::S3Object.any_instance.stubs(:delete)
|
570
|
-
@dummy.
|
724
|
+
@dummy.destroy
|
571
725
|
end
|
572
726
|
|
573
727
|
should "succeed" do
|
@@ -617,6 +771,47 @@ class S3Test < Test::Unit::TestCase
|
|
617
771
|
end
|
618
772
|
end
|
619
773
|
|
774
|
+
context "An attachment with S3 storage and S3 credentials with a :credential_provider" do
|
775
|
+
setup do
|
776
|
+
class DummyCredentialProvider; end
|
777
|
+
|
778
|
+
rebuild_model :storage => :s3,
|
779
|
+
:bucket => "testing",
|
780
|
+
:s3_credentials => {
|
781
|
+
:credential_provider => DummyCredentialProvider.new
|
782
|
+
}
|
783
|
+
@dummy = Dummy.new
|
784
|
+
end
|
785
|
+
|
786
|
+
should "set the credential-provider" do
|
787
|
+
assert_kind_of DummyCredentialProvider, @dummy.avatar.s3_bucket.config.credential_provider
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
791
|
+
context "An attachment with S3 storage and S3 credentials in an unsupported manor" do
|
792
|
+
setup do
|
793
|
+
rebuild_model :storage => :s3, :bucket => "testing", :s3_credentials => ["unsupported"]
|
794
|
+
@dummy = Dummy.new
|
795
|
+
end
|
796
|
+
|
797
|
+
should "not accept the credentials" do
|
798
|
+
assert_raise(ArgumentError) do
|
799
|
+
@dummy.avatar.s3_credentials
|
800
|
+
end
|
801
|
+
end
|
802
|
+
end
|
803
|
+
|
804
|
+
context "An attachment with S3 storage and S3 credentials not supplied" do
|
805
|
+
setup do
|
806
|
+
rebuild_model :storage => :s3, :bucket => "testing"
|
807
|
+
@dummy = Dummy.new
|
808
|
+
end
|
809
|
+
|
810
|
+
should "not parse any credentials" do
|
811
|
+
assert_equal({}, @dummy.avatar.s3_credentials)
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
620
815
|
context "An attachment with S3 storage and specific s3 headers set" do
|
621
816
|
setup do
|
622
817
|
rebuild_model :storage => :s3,
|
@@ -773,6 +968,46 @@ class S3Test < Test::Unit::TestCase
|
|
773
968
|
end
|
774
969
|
end
|
775
970
|
|
971
|
+
context "Can disable AES256 encryption multiple ways" do
|
972
|
+
[nil, false, ''].each do |tech|
|
973
|
+
setup do
|
974
|
+
rebuild_model(
|
975
|
+
:storage => :s3,
|
976
|
+
:bucket => "testing",
|
977
|
+
:path => ":attachment/:style/:basename.:extension",
|
978
|
+
:s3_credentials => {
|
979
|
+
'access_key_id' => "12345",
|
980
|
+
'secret_access_key' => "54321"},
|
981
|
+
:s3_server_side_encryption => tech)
|
982
|
+
end
|
983
|
+
|
984
|
+
context "when assigned" do
|
985
|
+
setup do
|
986
|
+
@file = File.new(fixture_file('5k.png'), 'rb')
|
987
|
+
@dummy = Dummy.new
|
988
|
+
@dummy.avatar = @file
|
989
|
+
end
|
990
|
+
|
991
|
+
teardown { @file.close }
|
992
|
+
|
993
|
+
context "and saved" do
|
994
|
+
setup do
|
995
|
+
object = stub
|
996
|
+
@dummy.avatar.stubs(:s3_object).returns(object)
|
997
|
+
object.expects(:write).with(anything,
|
998
|
+
:content_type => "image/png",
|
999
|
+
:acl => :public_read)
|
1000
|
+
@dummy.save
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
should "succeed" do
|
1004
|
+
assert true
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
|
776
1011
|
context "An attachment with S3 storage and using AES256 encryption" do
|
777
1012
|
setup do
|
778
1013
|
rebuild_model :storage => :s3,
|
@@ -801,7 +1036,7 @@ class S3Test < Test::Unit::TestCase
|
|
801
1036
|
object.expects(:write).with(anything,
|
802
1037
|
:content_type => "image/png",
|
803
1038
|
:acl => :public_read,
|
804
|
-
:server_side_encryption =>
|
1039
|
+
:server_side_encryption => 'AES256')
|
805
1040
|
@dummy.save
|
806
1041
|
end
|
807
1042
|
|
data/test/style_test.rb
CHANGED
@@ -96,40 +96,44 @@ class StyleTest < Test::Unit::TestCase
|
|
96
96
|
end
|
97
97
|
|
98
98
|
context "An attachment with :convert_options" do
|
99
|
-
|
99
|
+
should "not have called extra_options_for(:thumb/:large) on initialization" do
|
100
100
|
@attachment = attachment :path => ":basename.:extension",
|
101
101
|
:styles => {:thumb => "100x100", :large => "400x400"},
|
102
102
|
:convert_options => {:all => "-do_stuff", :thumb => "-thumbnailize"}
|
103
|
-
@style = @attachment.styles[:thumb]
|
104
|
-
@file = StringIO.new("...")
|
105
|
-
@file.stubs(:original_filename).returns("file.jpg")
|
106
|
-
end
|
107
|
-
|
108
|
-
before_should "not have called extra_options_for(:thumb/:large) on initialization" do
|
109
103
|
@attachment.expects(:extra_options_for).never
|
104
|
+
@style = @attachment.styles[:thumb]
|
110
105
|
end
|
111
106
|
|
112
107
|
should "call extra_options_for(:thumb/:large) when convert options are requested" do
|
108
|
+
@attachment = attachment :path => ":basename.:extension",
|
109
|
+
:styles => {:thumb => "100x100", :large => "400x400"},
|
110
|
+
:convert_options => {:all => "-do_stuff", :thumb => "-thumbnailize"}
|
111
|
+
@style = @attachment.styles[:thumb]
|
112
|
+
@file = StringIO.new("...")
|
113
|
+
@file.stubs(:original_filename).returns("file.jpg")
|
114
|
+
|
113
115
|
@attachment.expects(:extra_options_for).with(:thumb)
|
114
116
|
@attachment.styles[:thumb].convert_options
|
115
117
|
end
|
116
118
|
end
|
117
119
|
|
118
120
|
context "An attachment with :source_file_options" do
|
119
|
-
|
121
|
+
should "not have called extra_source_file_options_for(:thumb/:large) on initialization" do
|
120
122
|
@attachment = attachment :path => ":basename.:extension",
|
121
123
|
:styles => {:thumb => "100x100", :large => "400x400"},
|
122
124
|
:source_file_options => {:all => "-density 400", :thumb => "-depth 8"}
|
123
|
-
@style = @attachment.styles[:thumb]
|
124
|
-
@file = StringIO.new("...")
|
125
|
-
@file.stubs(:original_filename).returns("file.jpg")
|
126
|
-
end
|
127
|
-
|
128
|
-
before_should "not have called extra_source_file_options_for(:thumb/:large) on initialization" do
|
129
125
|
@attachment.expects(:extra_source_file_options_for).never
|
126
|
+
@style = @attachment.styles[:thumb]
|
130
127
|
end
|
131
128
|
|
132
129
|
should "call extra_options_for(:thumb/:large) when convert options are requested" do
|
130
|
+
@attachment = attachment :path => ":basename.:extension",
|
131
|
+
:styles => {:thumb => "100x100", :large => "400x400"},
|
132
|
+
:source_file_options => {:all => "-density 400", :thumb => "-depth 8"}
|
133
|
+
@style = @attachment.styles[:thumb]
|
134
|
+
@file = StringIO.new("...")
|
135
|
+
@file.stubs(:original_filename).returns("file.jpg")
|
136
|
+
|
133
137
|
@attachment.expects(:extra_source_file_options_for).with(:thumb)
|
134
138
|
@attachment.styles[:thumb].source_file_options
|
135
139
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require './test/helper'
|
2
|
+
|
3
|
+
class Paperclip::TempfileFactoryTest < Test::Unit::TestCase
|
4
|
+
should "be able to generate a tempfile with the right name" do
|
5
|
+
file = subject.generate("omg.png")
|
6
|
+
end
|
7
|
+
should "be able to generate a tempfile with the right name with a tilde at the beginning" do
|
8
|
+
file = subject.generate("~omg.png")
|
9
|
+
end
|
10
|
+
should "be able to generate a tempfile with the right name with a tilde at the end" do
|
11
|
+
file = subject.generate("omg.png~")
|
12
|
+
end
|
13
|
+
end
|
data/test/thumbnail_test.rb
CHANGED
@@ -80,6 +80,8 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
80
80
|
should "let us know when a command isn't found versus a processing error" do
|
81
81
|
old_path = ENV['PATH']
|
82
82
|
begin
|
83
|
+
Cocaine::CommandLine.path = ''
|
84
|
+
Paperclip.options[:command_path] = ''
|
83
85
|
ENV['PATH'] = ''
|
84
86
|
assert_raises(Paperclip::Errors::CommandNotFoundError) do
|
85
87
|
silence_stream(STDERR) do
|
@@ -113,10 +115,9 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
113
115
|
end
|
114
116
|
|
115
117
|
should "send the right command to convert when sent #make" do
|
116
|
-
|
117
|
-
arg[0] == '
|
118
|
-
arg[1]
|
119
|
-
arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
|
118
|
+
@thumb.expects(:convert).with do |*arg|
|
119
|
+
arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' &&
|
120
|
+
arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
|
120
121
|
end
|
121
122
|
@thumb.make
|
122
123
|
end
|
@@ -127,6 +128,16 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
127
128
|
end
|
128
129
|
end
|
129
130
|
|
131
|
+
should 'properly crop a EXIF-rotated image' do
|
132
|
+
file = File.new(fixture_file('rotated.jpg'))
|
133
|
+
thumb = Paperclip::Thumbnail.new(file, :geometry => "50x50#")
|
134
|
+
|
135
|
+
output_file = thumb.make
|
136
|
+
|
137
|
+
command = Cocaine::CommandLine.new("identify", "-format %wx%h :file")
|
138
|
+
assert_equal "50x50", command.run(:file => output_file.path).strip
|
139
|
+
end
|
140
|
+
|
130
141
|
context "being thumbnailed with source file options set" do
|
131
142
|
setup do
|
132
143
|
@thumb = Paperclip::Thumbnail.new(@file,
|
@@ -139,10 +150,9 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
139
150
|
end
|
140
151
|
|
141
152
|
should "send the right command to convert when sent #make" do
|
142
|
-
|
143
|
-
arg[0] == '
|
144
|
-
arg[1]
|
145
|
-
arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
|
153
|
+
@thumb.expects(:convert).with do |*arg|
|
154
|
+
arg[0] == '-strip :source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' &&
|
155
|
+
arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
|
146
156
|
end
|
147
157
|
@thumb.make
|
148
158
|
end
|
@@ -181,10 +191,9 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
181
191
|
end
|
182
192
|
|
183
193
|
should "send the right command to convert when sent #make" do
|
184
|
-
|
185
|
-
arg[0] == '
|
186
|
-
arg[1]
|
187
|
-
arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
|
194
|
+
@thumb.expects(:convert).with do |*arg|
|
195
|
+
arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage -strip -depth 8 :dest' &&
|
196
|
+
arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
|
188
197
|
end
|
189
198
|
@thumb.make
|
190
199
|
end
|
@@ -212,6 +221,8 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
212
221
|
should "let us know when a command isn't found versus a processing error" do
|
213
222
|
old_path = ENV['PATH']
|
214
223
|
begin
|
224
|
+
Cocaine::CommandLine.path = ''
|
225
|
+
Paperclip.options[:command_path] = ''
|
215
226
|
ENV['PATH'] = ''
|
216
227
|
assert_raises(Paperclip::Errors::CommandNotFoundError) do
|
217
228
|
silence_stream(STDERR) do
|
@@ -237,6 +248,17 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
237
248
|
end
|
238
249
|
end
|
239
250
|
|
251
|
+
context "being thumbnailed with default animated option (true)" do
|
252
|
+
should "call identify to check for animated images when sent #make" do
|
253
|
+
thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x50#")
|
254
|
+
thumb.expects(:identify).at_least_once.with do |*arg|
|
255
|
+
arg[0] == '-format %m :file' &&
|
256
|
+
arg[1][:file] == "#{File.expand_path(thumb.file.path)}[0]"
|
257
|
+
end
|
258
|
+
thumb.make
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
240
262
|
context "passing a custom file geometry parser" do
|
241
263
|
teardown do
|
242
264
|
self.class.send(:remove_const, :GeoParser)
|
@@ -358,13 +380,19 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
358
380
|
|
359
381
|
should "create the 12 frames thumbnail when sent #make" do
|
360
382
|
dst = @thumb.make
|
361
|
-
cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
|
362
|
-
|
383
|
+
cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
|
384
|
+
frames = `#{cmd}`.chomp.split(',')
|
385
|
+
assert_equal 12, frames.size
|
386
|
+
assert_frame_dimensions (45..50), frames
|
363
387
|
end
|
364
388
|
|
365
389
|
should "use the -coalesce option" do
|
366
390
|
assert_equal @thumb.transformation_command.first, "-coalesce"
|
367
391
|
end
|
392
|
+
|
393
|
+
should "use the -layers 'optimize' option" do
|
394
|
+
assert_equal @thumb.transformation_command.last, '-layers "optimize"'
|
395
|
+
end
|
368
396
|
end
|
369
397
|
|
370
398
|
context "with omitted output format" do
|
@@ -374,13 +402,65 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
374
402
|
|
375
403
|
should "create the 12 frames thumbnail when sent #make" do
|
376
404
|
dst = @thumb.make
|
377
|
-
cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
|
378
|
-
|
405
|
+
cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
|
406
|
+
frames = `#{cmd}`.chomp.split(',')
|
407
|
+
assert_equal 12, frames.size
|
408
|
+
assert_frame_dimensions (45..50), frames
|
409
|
+
end
|
410
|
+
|
411
|
+
should "use the -coalesce option" do
|
412
|
+
assert_equal @thumb.transformation_command.first, "-coalesce"
|
413
|
+
end
|
414
|
+
|
415
|
+
should "use the -layers 'optimize' option" do
|
416
|
+
assert_equal @thumb.transformation_command.last, '-layers "optimize"'
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
context "with unidentified source format" do
|
421
|
+
setup do
|
422
|
+
@unidentified_file = File.new(fixture_file("animated.unknown"), 'rb')
|
423
|
+
@thumb = Paperclip::Thumbnail.new(@file, :geometry => "60x60")
|
424
|
+
end
|
425
|
+
|
426
|
+
should "create the 12 frames thumbnail when sent #make" do
|
427
|
+
dst = @thumb.make
|
428
|
+
cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
|
429
|
+
frames = `#{cmd}`.chomp.split(',')
|
430
|
+
assert_equal 12, frames.size
|
431
|
+
assert_frame_dimensions (55..60), frames
|
379
432
|
end
|
380
433
|
|
381
434
|
should "use the -coalesce option" do
|
382
435
|
assert_equal @thumb.transformation_command.first, "-coalesce"
|
383
436
|
end
|
437
|
+
|
438
|
+
should "use the -layers 'optimize' option" do
|
439
|
+
assert_equal @thumb.transformation_command.last, '-layers "optimize"'
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
context "with no source format" do
|
444
|
+
setup do
|
445
|
+
@unidentified_file = File.new(fixture_file("animated"), 'rb')
|
446
|
+
@thumb = Paperclip::Thumbnail.new(@file, :geometry => "70x70")
|
447
|
+
end
|
448
|
+
|
449
|
+
should "create the 12 frames thumbnail when sent #make" do
|
450
|
+
dst = @thumb.make
|
451
|
+
cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
|
452
|
+
frames = `#{cmd}`.chomp.split(',')
|
453
|
+
assert_equal 12, frames.size
|
454
|
+
assert_frame_dimensions (60..70), frames
|
455
|
+
end
|
456
|
+
|
457
|
+
should "use the -coalesce option" do
|
458
|
+
assert_equal @thumb.transformation_command.first, "-coalesce"
|
459
|
+
end
|
460
|
+
|
461
|
+
should "use the -layers 'optimize' option" do
|
462
|
+
assert_equal @thumb.transformation_command.last, '-layers "optimize"'
|
463
|
+
end
|
384
464
|
end
|
385
465
|
|
386
466
|
context "with animated option set to false" do
|