paperclip 2.8.0 → 3.0.2

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.

Files changed (94) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +9 -7
  3. data/Appraisals +6 -12
  4. data/Gemfile +2 -0
  5. data/NEWS +24 -0
  6. data/README.md +53 -21
  7. data/Rakefile +7 -2
  8. data/UPGRADING +14 -0
  9. data/features/basic_integration.feature +8 -8
  10. data/features/rake_tasks.feature +1 -1
  11. data/features/step_definitions/attachment_steps.rb +11 -2
  12. data/features/step_definitions/rails_steps.rb +17 -79
  13. data/features/support/env.rb +3 -0
  14. data/features/support/file_helpers.rb +24 -0
  15. data/features/support/rails.rb +3 -3
  16. data/gemfiles/{rails3_1.gemfile → 3.0.gemfile} +3 -1
  17. data/gemfiles/{rails2.gemfile → 3.1.gemfile} +3 -1
  18. data/gemfiles/{rails3.gemfile → 3.2.gemfile} +3 -1
  19. data/images.rake +21 -0
  20. data/lib/generators/paperclip/paperclip_generator.rb +1 -2
  21. data/lib/paperclip.rb +48 -319
  22. data/lib/paperclip/attachment.rb +33 -81
  23. data/lib/paperclip/attachment_options.rb +0 -1
  24. data/lib/paperclip/callbacks.rb +30 -0
  25. data/lib/paperclip/errors.rb +27 -0
  26. data/lib/paperclip/geometry.rb +6 -4
  27. data/lib/paperclip/glue.rb +15 -0
  28. data/lib/paperclip/helpers.rb +71 -0
  29. data/lib/paperclip/instance_methods.rb +35 -0
  30. data/lib/paperclip/interpolations.rb +2 -2
  31. data/lib/paperclip/io_adapters/attachment_adapter.rb +62 -0
  32. data/lib/paperclip/io_adapters/file_adapter.rb +81 -0
  33. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -0
  34. data/lib/paperclip/io_adapters/nil_adapter.rb +34 -0
  35. data/lib/paperclip/io_adapters/registry.rb +32 -0
  36. data/lib/paperclip/io_adapters/stringio_adapter.rb +64 -0
  37. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +63 -0
  38. data/lib/paperclip/locales/en.yml +17 -0
  39. data/lib/paperclip/logger.rb +21 -0
  40. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +1 -1
  41. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -2
  42. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +7 -7
  43. data/lib/paperclip/processor.rb +32 -17
  44. data/lib/paperclip/railtie.rb +10 -15
  45. data/lib/paperclip/storage/filesystem.rb +5 -14
  46. data/lib/paperclip/storage/fog.rb +2 -21
  47. data/lib/paperclip/storage/s3.rb +12 -29
  48. data/lib/paperclip/tempfile.rb +41 -0
  49. data/lib/paperclip/thumbnail.rb +2 -3
  50. data/lib/paperclip/validators.rb +45 -0
  51. data/lib/paperclip/validators/attachment_content_type_validator.rb +47 -0
  52. data/lib/paperclip/validators/attachment_presence_validator.rb +26 -0
  53. data/lib/paperclip/validators/attachment_size_validator.rb +102 -0
  54. data/lib/paperclip/version.rb +1 -1
  55. data/lib/tasks/paperclip.rake +3 -11
  56. data/paperclip.gemspec +15 -5
  57. data/test/adapter_registry_test.rb +32 -0
  58. data/test/attachment_adapter_test.rb +48 -0
  59. data/test/attachment_options_test.rb +0 -13
  60. data/test/attachment_test.rb +27 -55
  61. data/test/file_adapter_test.rb +43 -0
  62. data/test/generator_test.rb +78 -0
  63. data/test/geometry_test.rb +5 -5
  64. data/test/helper.rb +9 -11
  65. data/test/identity_adapter_test.rb +8 -0
  66. data/test/integration_test.rb +39 -94
  67. data/test/interpolations_test.rb +8 -1
  68. data/test/matchers/validate_attachment_size_matcher_test.rb +16 -2
  69. data/test/nil_adapter_test.rb +25 -0
  70. data/test/paperclip_test.rb +30 -189
  71. data/test/storage/filesystem_test.rb +0 -14
  72. data/test/storage/fog_test.rb +0 -14
  73. data/test/storage/s3_live_test.rb +22 -9
  74. data/test/storage/s3_test.rb +70 -34
  75. data/test/stringio_adapter_test.rb +42 -0
  76. data/test/style_test.rb +10 -16
  77. data/test/thumbnail_test.rb +16 -10
  78. data/test/uploaded_file_adapter_test.rb +98 -0
  79. data/test/validators/attachment_content_type_validator_test.rb +140 -0
  80. data/test/validators/attachment_presence_validator_test.rb +85 -0
  81. data/test/validators/attachment_size_validator_test.rb +207 -0
  82. data/test/validators_test.rb +25 -0
  83. metadata +152 -30
  84. data/gemfiles/rails3_2.gemfile +0 -9
  85. data/generators/paperclip/USAGE +0 -5
  86. data/generators/paperclip/paperclip_generator.rb +0 -27
  87. data/generators/paperclip/templates/paperclip_migration.rb.erb +0 -19
  88. data/init.rb +0 -4
  89. data/lib/paperclip/callback_compatibility.rb +0 -61
  90. data/lib/paperclip/iostream.rb +0 -45
  91. data/lib/paperclip/upfile.rb +0 -64
  92. data/rails/init.rb +0 -2
  93. data/test/iostream_test.rb +0 -71
  94. data/test/upfile_test.rb +0 -53
@@ -23,20 +23,6 @@ class FileSystemTest < Test::Unit::TestCase
23
23
  assert File.exists?(@dummy.avatar.path(:thumbnail))
24
24
  end
25
25
 
26
- should "clean up file objects" do
27
- File.stubs(:exist?).returns(true)
28
- Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
29
- Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
30
-
31
- @dummy.save!
32
- end
33
-
34
- should "always be rewound when returning from #to_file" do
35
- assert_equal 0, @dummy.avatar.to_file.pos
36
- @dummy.avatar.to_file.seek(10)
37
- assert_equal 0, @dummy.avatar.to_file.pos
38
- end
39
-
40
26
  context "with file that has space in file name" do
41
27
  setup do
42
28
  rebuild_model :styles => { :thumbnail => "25x25#" }
@@ -56,14 +56,6 @@ class FogTest < Test::Unit::TestCase
56
56
  assert_equal File.expand_path(File.join(File.dirname(__FILE__), "../../public/avatars/5k.png")),
57
57
  @dummy.avatar.path
58
58
  end
59
-
60
- should "clean up file objects" do
61
- File.stubs(:exist?).returns(true)
62
- Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
63
- Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
64
-
65
- @dummy.save!
66
- end
67
59
  end
68
60
 
69
61
  setup do
@@ -110,12 +102,6 @@ class FogTest < Test::Unit::TestCase
110
102
  directory.destroy
111
103
  end
112
104
 
113
- should "always be rewound when returning from #to_file" do
114
- assert_equal 0, @dummy.avatar.to_file.pos
115
- @dummy.avatar.to_file.seek(10)
116
- assert_equal 0, @dummy.avatar.to_file.pos
117
- end
118
-
119
105
  should "pass the content type to the Fog::Storage::AWS::Files instance" do
120
106
  Fog::Storage::AWS::Files.any_instance.expects(:create).with do |hash|
121
107
  hash[:content_type]
@@ -1,9 +1,31 @@
1
1
  require './test/helper'
2
2
  require 'aws'
3
3
 
4
+
4
5
  unless ENV["S3_BUCKET"].blank?
5
6
  class S3LiveTest < Test::Unit::TestCase
6
7
 
8
+ context "when assigning an S3 attachment directly to another model" do
9
+ setup do
10
+ rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
11
+ :storage => :s3,
12
+ :bucket => ENV["S3_BUCKET"],
13
+ :path => ":class/:attachment/:id/:style.:extension",
14
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "fixtures", "s3.yml"))
15
+
16
+ @dummy = Dummy.new
17
+ @attachment = Dummy.new.avatar
18
+ @file = File.new(fixture_file("5k.png"))
19
+ @attachment.assign(@file)
20
+ @attachment.save
21
+
22
+ @attachment2 = Dummy.new.avatar
23
+ @attachment2.assign(@file)
24
+ @attachment2.save
25
+ end
26
+ end
27
+
28
+
7
29
  context "Generating an expiring url on a nonexistant attachment" do
8
30
  setup do
9
31
  rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
@@ -46,10 +68,6 @@ unless ENV["S3_BUCKET"].blank?
46
68
  @dummy.destroy
47
69
  end
48
70
 
49
- should "still return a Tempfile when sent #to_file" do
50
- assert_equal Paperclip::Tempfile, @dummy.avatar.to_file.class
51
- end
52
-
53
71
  context "and saved" do
54
72
  setup do
55
73
  @dummy.save
@@ -58,11 +76,6 @@ unless ENV["S3_BUCKET"].blank?
58
76
  should "be on S3" do
59
77
  assert true
60
78
  end
61
-
62
- should "generate a tempfile with the right name" do
63
- file = @dummy.avatar.to_file
64
- assert_match /^original.*\.png$/, File.basename(file.path)
65
- end
66
79
  end
67
80
  end
68
81
  end
@@ -88,7 +88,6 @@ class S3Test < Test::Unit::TestCase
88
88
 
89
89
  setup do
90
90
  rebuild_model :storage => :s3,
91
- #:bucket => "testing", # intentionally left out
92
91
  :http_proxy => @proxy_settings,
93
92
  :s3_credentials => {:not => :important}
94
93
 
@@ -241,7 +240,7 @@ class S3Test < Test::Unit::TestCase
241
240
  'secret_access_key' => "54321"
242
241
  }
243
242
 
244
- file = StringIO.new(".")
243
+ file = Paperclip.io_adapters.for(StringIO.new("."))
245
244
  file.original_filename = "question?mark.png"
246
245
  @dummy = Dummy.new
247
246
  @dummy.avatar = file
@@ -336,24 +335,29 @@ class S3Test < Test::Unit::TestCase
336
335
  assert_match %r{^avatars/stringio\.txt}, @dummy.avatar.url
337
336
  end
338
337
 
339
- should "always be rewound when returning from #to_file" do
340
- assert_equal 0, @dummy.avatar.to_file.pos
341
- @dummy.avatar.to_file.seek(10)
342
- assert_equal 0, @dummy.avatar.to_file.pos
343
- end
344
- end
338
+ end
345
339
 
346
340
  context "Generating a secure url with an expiration" do
347
341
  setup do
348
- rebuild_model :storage => :s3,
349
- :s3_credentials => {
350
- :production => { :bucket => "prod_bucket" },
351
- :development => { :bucket => "dev_bucket" }
352
- },
353
- :s3_host_alias => "something.something.com",
354
- :s3_permissions => "private",
355
- :path => ":attachment/:basename.:extension",
356
- :url => ":s3_alias_url"
342
+ @build_model_with_options = lambda {|options|
343
+ base_options = {
344
+ :storage => :s3,
345
+ :s3_credentials => {
346
+ :production => { :bucket => "prod_bucket" },
347
+ :development => { :bucket => "dev_bucket" }
348
+ },
349
+ :s3_host_alias => "something.something.com",
350
+ :s3_permissions => "private",
351
+ :path => ":attachment/:basename.:extension",
352
+ :url => ":s3_alias_url"
353
+ }
354
+
355
+ rebuild_model base_options.merge(options)
356
+ }
357
+ end
358
+
359
+ should "use default options" do
360
+ @build_model_with_options[{}]
357
361
 
358
362
  rails_env("production")
359
363
 
@@ -367,8 +371,40 @@ class S3Test < Test::Unit::TestCase
367
371
  @dummy.avatar.expiring_url
368
372
  end
369
373
 
370
- should "should succeed" do
371
- assert true
374
+ should "allow overriding s3_url_options" do
375
+ @build_model_with_options[:s3_url_options => { :response_content_disposition => "inline" }]
376
+
377
+ rails_env("production")
378
+
379
+ @dummy = Dummy.new
380
+ @dummy.avatar = StringIO.new(".")
381
+
382
+ object = stub
383
+ @dummy.avatar.stubs(:s3_object).returns(object)
384
+ object.expects(:url_for).with(:read, :expires => 3600, :secure => true, :response_content_disposition => "inline")
385
+
386
+ @dummy.avatar.expiring_url
387
+ end
388
+
389
+ should "allow overriding s3_object options with a proc" do
390
+ @build_model_with_options[:s3_url_options => lambda {|attachment| { :response_content_type => attachment.avatar_content_type } }]
391
+
392
+ rails_env("production")
393
+
394
+ @dummy = Dummy.new
395
+
396
+ @file = StringIO.new(".")
397
+ @file.stubs(:original_filename).returns("5k.png\n\n")
398
+ @file.stubs(:content_type).returns("image/png\n\n")
399
+ @file.stubs(:to_tempfile).returns(@file)
400
+
401
+ @dummy.avatar = @file
402
+
403
+ object = stub
404
+ @dummy.avatar.stubs(:s3_object).returns(object)
405
+ object.expects(:url_for).with(:read, :expires => 3600, :secure => true, :response_content_type => "image/png")
406
+
407
+ @dummy.avatar.expiring_url
372
408
  end
373
409
  end
374
410
 
@@ -507,14 +543,6 @@ class S3Test < Test::Unit::TestCase
507
543
  end
508
544
  end
509
545
 
510
- should "delete tempfiles" do
511
- File.stubs(:exist?).returns(true)
512
- Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
513
- Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
514
-
515
- @dummy.save!
516
- end
517
-
518
546
  context "and saved without a bucket" do
519
547
  setup do
520
548
  AWS::S3::BucketCollection.any_instance.expects(:create).with("testing")
@@ -570,6 +598,21 @@ class S3Test < Test::Unit::TestCase
570
598
  end
571
599
  end
572
600
 
601
+ context "An attachment with S3 storage and S3 credentials defined as a Proc" do
602
+ setup do
603
+ rebuild_model :storage => :s3,
604
+ :bucket => {:not => :important},
605
+ :s3_credentials => lambda { |attachment|
606
+ Hash['access_key_id' => "access#{attachment.instance.other}", 'secret_access_key' => "secret#{attachment.instance.other}"]
607
+ }
608
+ end
609
+
610
+ should "get the right credentials" do
611
+ assert "access1234", Dummy.new(:other => '1234').avatar.s3_credentials[:access_key_id]
612
+ assert "secret1234", Dummy.new(:other => '1234').avatar.s3_credentials[:secret_access_key]
613
+ end
614
+ end
615
+
573
616
  context "An attachment with S3 storage and specific s3 headers set" do
574
617
  setup do
575
618
  rebuild_model :storage => :s3,
@@ -1002,13 +1045,6 @@ class S3Test < Test::Unit::TestCase
1002
1045
 
1003
1046
  context "and saved" do
1004
1047
  setup do
1005
- [:thumb, :original].each do |style|
1006
- object = stub
1007
- @dummy.avatar.stubs(:s3_object).with(style).returns(object)
1008
- object.expects(:write).with(anything,
1009
- :content_type => "image/png",
1010
- :acl => style == :thumb ? :public_read : :private)
1011
- end
1012
1048
  @dummy.save
1013
1049
  end
1014
1050
 
@@ -0,0 +1,42 @@
1
+ require './test/helper'
2
+
3
+ class StringioFileProxyTest < Test::Unit::TestCase
4
+ context "a new instance" do
5
+ setup do
6
+ @contents = "abc123"
7
+ @stringio = StringIO.new(@contents)
8
+ @subject = Paperclip.io_adapters.for(@stringio)
9
+ end
10
+
11
+ should "return a file name" do
12
+ assert_equal "stringio.txt", @subject.original_filename
13
+ end
14
+
15
+ should "allow us to set a name" do
16
+ @subject.original_filename = "data.txt"
17
+ assert_equal "data.txt", @subject.original_filename
18
+ end
19
+
20
+ should "return a content type" do
21
+ assert_equal "text/plain", @subject.content_type
22
+ end
23
+
24
+ should "allow us to set a content type" do
25
+ @subject.content_type = "image/jpg"
26
+ assert_equal "image/jpg", @subject.content_type
27
+ end
28
+
29
+ should "return the size of the data" do
30
+ assert_equal 6, @subject.size
31
+ end
32
+
33
+ should "generate an MD5 hash of the contents" do
34
+ assert_equal Digest::MD5.hexdigest(@contents), @subject.fingerprint
35
+ end
36
+
37
+ should "return the data contained in the StringIO" do
38
+ assert_equal "abc123", @subject.read
39
+ end
40
+
41
+ end
42
+ end
@@ -96,46 +96,40 @@ class StyleTest < Test::Unit::TestCase
96
96
  end
97
97
 
98
98
  context "An attachment with :convert_options" do
99
- should "not have called extra_options_for(:thumb/:large) on initialization" do
99
+ setup 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
- @attachment.expects(:extra_options_for).never
104
103
  @style = @attachment.styles[:thumb]
105
104
  @file = StringIO.new("...")
106
105
  @file.stubs(:original_filename).returns("file.jpg")
107
106
  end
108
107
 
108
+ before_should "not have called extra_options_for(:thumb/:large) on initialization" do
109
+ @attachment.expects(:extra_options_for).never
110
+ end
111
+
109
112
  should "call extra_options_for(:thumb/:large) when convert options are requested" do
110
- @attachment = attachment :path => ":basename.:extension",
111
- :styles => {:thumb => "100x100", :large => "400x400"},
112
- :convert_options => {:all => "-do_stuff", :thumb => "-thumbnailize"}
113
- @style = @attachment.styles[:thumb]
114
- @file = StringIO.new("...")
115
- @file.stubs(:original_filename).returns("file.jpg")
116
113
  @attachment.expects(:extra_options_for).with(:thumb)
117
114
  @attachment.styles[:thumb].convert_options
118
115
  end
119
116
  end
120
117
 
121
118
  context "An attachment with :source_file_options" do
122
- should "not have called extra_source_file_options_for(:thumb/:large) on initialization" do
119
+ setup do
123
120
  @attachment = attachment :path => ":basename.:extension",
124
121
  :styles => {:thumb => "100x100", :large => "400x400"},
125
122
  :source_file_options => {:all => "-density 400", :thumb => "-depth 8"}
126
- @attachment.expects(:extra_source_file_options_for).never
127
123
  @style = @attachment.styles[:thumb]
128
124
  @file = StringIO.new("...")
129
125
  @file.stubs(:original_filename).returns("file.jpg")
130
126
  end
131
127
 
128
+ before_should "not have called extra_source_file_options_for(:thumb/:large) on initialization" do
129
+ @attachment.expects(:extra_source_file_options_for).never
130
+ end
131
+
132
132
  should "call extra_options_for(:thumb/:large) when convert options are requested" do
133
- @attachment = attachment :path => ":basename.:extension",
134
- :styles => {:thumb => "100x100", :large => "400x400"},
135
- :source_file_options => {:all => "-density 400", :thumb => "-depth 8"}
136
- @style = @attachment.styles[:thumb]
137
- @file = StringIO.new("...")
138
- @file.stubs(:original_filename).returns("file.jpg")
139
133
  @attachment.expects(:extra_source_file_options_for).with(:thumb)
140
134
  @attachment.styles[:thumb].source_file_options
141
135
  end
@@ -77,10 +77,10 @@ class ThumbnailTest < Test::Unit::TestCase
77
77
  old_path = ENV['PATH']
78
78
  begin
79
79
  ENV['PATH'] = ''
80
- Cocaine::CommandLine.path = ''
81
- Paperclip.options[:command_path] = ''
82
- assert_raises(Paperclip::CommandNotFoundError) do
83
- @thumb.make
80
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
81
+ silence_stream(STDERR) do
82
+ @thumb.make
83
+ end
84
84
  end
85
85
  ensure
86
86
  ENV['PATH'] = old_path
@@ -156,8 +156,10 @@ class ThumbnailTest < Test::Unit::TestCase
156
156
  end
157
157
 
158
158
  should "error when trying to create the thumbnail" do
159
- assert_raises(Paperclip::PaperclipError) do
160
- @thumb.make
159
+ assert_raises(Paperclip::Error) do
160
+ silence_stream(STDERR) do
161
+ @thumb.make
162
+ end
161
163
  end
162
164
  end
163
165
  end
@@ -196,8 +198,10 @@ class ThumbnailTest < Test::Unit::TestCase
196
198
  end
197
199
 
198
200
  should "error when trying to create the thumbnail" do
199
- assert_raises(Paperclip::PaperclipError) do
200
- @thumb.make
201
+ assert_raises(Paperclip::Error) do
202
+ silence_stream(STDERR) do
203
+ @thumb.make
204
+ end
201
205
  end
202
206
  end
203
207
 
@@ -205,8 +209,10 @@ class ThumbnailTest < Test::Unit::TestCase
205
209
  old_path = ENV['PATH']
206
210
  begin
207
211
  ENV['PATH'] = ''
208
- assert_raises(Paperclip::CommandNotFoundError) do
209
- @thumb.make
212
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
213
+ silence_stream(STDERR) do
214
+ @thumb.make
215
+ end
210
216
  end
211
217
  ensure
212
218
  ENV['PATH'] = old_path
@@ -0,0 +1,98 @@
1
+ require './test/helper'
2
+
3
+ class UploadedFileAdapterTest < Test::Unit::TestCase
4
+ context "a new instance" do
5
+ context "with UploadedFile responding to #tempfile" do
6
+ setup do
7
+ class UploadedFile < OpenStruct; end
8
+ tempfile = File.new(fixture_file("5k.png"))
9
+ tempfile.binmode
10
+
11
+ @file = UploadedFile.new(
12
+ :original_filename => "5k.png",
13
+ :content_type => "image/png",
14
+ :head => "",
15
+ :tempfile => tempfile
16
+ )
17
+ @subject = Paperclip.io_adapters.for(@file)
18
+ end
19
+
20
+ should "get the right filename" do
21
+ assert_equal "5k.png", @subject.original_filename
22
+ end
23
+
24
+ should "force binmode on tempfile" do
25
+ assert @subject.instance_variable_get("@tempfile").binmode?
26
+ end
27
+
28
+ should "get the content type" do
29
+ assert_equal "image/png", @subject.content_type
30
+ end
31
+
32
+ should "get the file's size" do
33
+ assert_equal 4456, @subject.size
34
+ end
35
+
36
+ should "return false for a call to nil?" do
37
+ assert ! @subject.nil?
38
+ end
39
+
40
+ should "generate a MD5 hash of the contents" do
41
+ expected = Digest::MD5.file(@file.tempfile.path).to_s
42
+ assert_equal expected, @subject.fingerprint
43
+ end
44
+
45
+ should "read the contents of the file" do
46
+ expected = @file.tempfile.read
47
+ assert expected.length > 0
48
+ assert_equal expected, @subject.read
49
+ end
50
+ end
51
+
52
+ context "with UploadFile responding to #path" do
53
+ setup do
54
+ class UploadedFile < OpenStruct; end
55
+ @file = UploadedFile.new(
56
+ :original_filename => "5k.png",
57
+ :content_type => "image/png",
58
+ :head => "",
59
+ :path => fixture_file("5k.png")
60
+ )
61
+ @subject = Paperclip.io_adapters.for(@file)
62
+ end
63
+
64
+ should "get the right filename" do
65
+ assert_equal "5k.png", @subject.original_filename
66
+ end
67
+
68
+ should "force binmode on tempfile" do
69
+ assert @subject.instance_variable_get("@tempfile").binmode?
70
+ end
71
+
72
+ should "get the content type" do
73
+ assert_equal "image/png", @subject.content_type
74
+ end
75
+
76
+ should "get the file's size" do
77
+ assert_equal 4456, @subject.size
78
+ end
79
+
80
+ should "return false for a call to nil?" do
81
+ assert ! @subject.nil?
82
+ end
83
+
84
+ should "generate a MD5 hash of the contents" do
85
+ expected = Digest::MD5.file(@file.path).to_s
86
+ assert_equal expected, @subject.fingerprint
87
+ end
88
+
89
+ should "read the contents of the file" do
90
+ expected_file = File.new(@file.path)
91
+ expected_file.binmode
92
+ expected = expected_file.read
93
+ assert expected.length > 0
94
+ assert_equal expected, @subject.read
95
+ end
96
+ end
97
+ end
98
+ end