cemeng-paperclip 2.3.6

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 (62) hide show
  1. data/LICENSE +26 -0
  2. data/README.rdoc +182 -0
  3. data/Rakefile +80 -0
  4. data/generators/paperclip/USAGE +5 -0
  5. data/generators/paperclip/paperclip_generator.rb +27 -0
  6. data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  7. data/init.rb +1 -0
  8. data/lib/generators/paperclip/USAGE +8 -0
  9. data/lib/generators/paperclip/paperclip_generator.rb +31 -0
  10. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  11. data/lib/paperclip.rb +402 -0
  12. data/lib/paperclip/attachment.rb +347 -0
  13. data/lib/paperclip/callback_compatability.rb +61 -0
  14. data/lib/paperclip/command_line.rb +80 -0
  15. data/lib/paperclip/geometry.rb +115 -0
  16. data/lib/paperclip/interpolations.rb +114 -0
  17. data/lib/paperclip/iostream.rb +45 -0
  18. data/lib/paperclip/matchers.rb +33 -0
  19. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  20. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +75 -0
  21. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  22. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  23. data/lib/paperclip/processor.rb +58 -0
  24. data/lib/paperclip/railtie.rb +25 -0
  25. data/lib/paperclip/storage.rb +3 -0
  26. data/lib/paperclip/storage/database.rb +204 -0
  27. data/lib/paperclip/storage/filesystem.rb +73 -0
  28. data/lib/paperclip/storage/s3.rb +192 -0
  29. data/lib/paperclip/style.rb +91 -0
  30. data/lib/paperclip/thumbnail.rb +79 -0
  31. data/lib/paperclip/upfile.rb +55 -0
  32. data/lib/paperclip/version.rb +3 -0
  33. data/lib/tasks/paperclip.rake +79 -0
  34. data/rails/init.rb +2 -0
  35. data/shoulda_macros/paperclip.rb +118 -0
  36. data/test/attachment_test.rb +804 -0
  37. data/test/command_line_test.rb +133 -0
  38. data/test/database.yml +4 -0
  39. data/test/database_storage_test.rb +267 -0
  40. data/test/fixtures/12k.png +0 -0
  41. data/test/fixtures/50x50.png +0 -0
  42. data/test/fixtures/5k.png +0 -0
  43. data/test/fixtures/bad.png +1 -0
  44. data/test/fixtures/s3.yml +8 -0
  45. data/test/fixtures/text.txt +0 -0
  46. data/test/fixtures/twopage.pdf +0 -0
  47. data/test/geometry_test.rb +177 -0
  48. data/test/helper.rb +146 -0
  49. data/test/integration_test.rb +482 -0
  50. data/test/interpolations_test.rb +127 -0
  51. data/test/iostream_test.rb +71 -0
  52. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  53. data/test/matchers/validate_attachment_content_type_matcher_test.rb +47 -0
  54. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  55. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  56. data/test/paperclip_test.rb +254 -0
  57. data/test/processor_test.rb +10 -0
  58. data/test/storage_test.rb +363 -0
  59. data/test/style_test.rb +141 -0
  60. data/test/thumbnail_test.rb +227 -0
  61. data/test/upfile_test.rb +36 -0
  62. metadata +186 -0
@@ -0,0 +1,127 @@
1
+ require './test/helper'
2
+
3
+ class InterpolationsTest < Test::Unit::TestCase
4
+ should "return all methods but the infrastructure when sent #all" do
5
+ methods = Paperclip::Interpolations.all
6
+ assert ! methods.include?(:[])
7
+ assert ! methods.include?(:[]=)
8
+ assert ! methods.include?(:all)
9
+ methods.each do |m|
10
+ assert Paperclip::Interpolations.respond_to?(m)
11
+ end
12
+ end
13
+
14
+ should "return the Rails.root" do
15
+ assert_equal Rails.root, Paperclip::Interpolations.rails_root(:attachment, :style)
16
+ end
17
+
18
+ should "return the Rails.env" do
19
+ assert_equal Rails.env, Paperclip::Interpolations.rails_env(:attachment, :style)
20
+ end
21
+
22
+ should "return the class of the Interpolations module when called with no params" do
23
+ assert_equal Module, Paperclip::Interpolations.class
24
+ end
25
+
26
+ should "return the class of the instance" do
27
+ attachment = mock
28
+ attachment.expects(:instance).returns(attachment)
29
+ attachment.expects(:class).returns("Thing")
30
+ assert_equal "things", Paperclip::Interpolations.class(attachment, :style)
31
+ end
32
+
33
+ should "return the basename of the file" do
34
+ attachment = mock
35
+ attachment.expects(:original_filename).returns("one.jpg").times(2)
36
+ assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
37
+ end
38
+
39
+ should "return the extension of the file" do
40
+ attachment = mock
41
+ attachment.expects(:original_filename).returns("one.jpg")
42
+ attachment.expects(:styles).returns({})
43
+ assert_equal "jpg", Paperclip::Interpolations.extension(attachment, :style)
44
+ end
45
+
46
+ should "return the extension of the file as the format if defined in the style" do
47
+ attachment = mock
48
+ attachment.expects(:original_filename).never
49
+ attachment.expects(:styles).returns({:style => {:format => "png"}})
50
+ assert_equal "png", Paperclip::Interpolations.extension(attachment, :style)
51
+ end
52
+
53
+ should "return the id of the attachment" do
54
+ attachment = mock
55
+ attachment.expects(:id).returns(23)
56
+ attachment.expects(:instance).returns(attachment)
57
+ assert_equal 23, Paperclip::Interpolations.id(attachment, :style)
58
+ end
59
+
60
+ should "return the partitioned id of the attachment" do
61
+ attachment = mock
62
+ attachment.expects(:id).returns(23)
63
+ attachment.expects(:instance).returns(attachment)
64
+ assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
65
+ end
66
+
67
+ should "return the name of the attachment" do
68
+ attachment = mock
69
+ attachment.expects(:name).returns("file")
70
+ assert_equal "files", Paperclip::Interpolations.attachment(attachment, :style)
71
+ end
72
+
73
+ should "return the style" do
74
+ assert_equal :style, Paperclip::Interpolations.style(:attachment, :style)
75
+ end
76
+
77
+ should "return the default style" do
78
+ attachment = mock
79
+ attachment.expects(:default_style).returns(:default_style)
80
+ assert_equal :default_style, Paperclip::Interpolations.style(attachment, nil)
81
+ end
82
+
83
+ should "reinterpolate :url" do
84
+ attachment = mock
85
+ attachment.expects(:url).with(:style, false).returns("1234")
86
+ assert_equal "1234", Paperclip::Interpolations.url(attachment, :style)
87
+ end
88
+
89
+ should "raise if infinite loop detcted reinterpolating :url" do
90
+ attachment = Object.new
91
+ class << attachment
92
+ def url(*args)
93
+ Paperclip::Interpolations.url(self, :style)
94
+ end
95
+ end
96
+ assert_raises(Paperclip::InfiniteInterpolationError){ Paperclip::Interpolations.url(attachment, :style) }
97
+ end
98
+
99
+ should "return the filename as basename.extension" do
100
+ attachment = mock
101
+ attachment.expects(:styles).returns({})
102
+ attachment.expects(:original_filename).returns("one.jpg").times(3)
103
+ assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
104
+ end
105
+
106
+ should "return the filename as basename.extension when format supplied" do
107
+ attachment = mock
108
+ attachment.expects(:styles).returns({:style => {:format => :png}})
109
+ attachment.expects(:original_filename).returns("one.jpg").times(2)
110
+ assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
111
+ end
112
+
113
+ should "return the timestamp" do
114
+ now = Time.now
115
+ attachment = mock
116
+ attachment.expects(:instance_read).with(:updated_at).returns(now)
117
+ assert_equal now.to_s, Paperclip::Interpolations.timestamp(attachment, :style)
118
+ end
119
+
120
+ should "call all expected interpolations with the given arguments" do
121
+ Paperclip::Interpolations.expects(:id).with(:attachment, :style).returns(1234)
122
+ Paperclip::Interpolations.expects(:attachment).with(:attachment, :style).returns("attachments")
123
+ Paperclip::Interpolations.expects(:notreal).never
124
+ value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
125
+ assert_equal ":notreal/1234/attachments", value
126
+ end
127
+ end
@@ -0,0 +1,71 @@
1
+ require './test/helper'
2
+
3
+ class IOStreamTest < Test::Unit::TestCase
4
+ include IOStream
5
+ context "A file" do
6
+ setup do
7
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
8
+ end
9
+
10
+ teardown { @file.close }
11
+
12
+ context "that is sent #stream_to" do
13
+
14
+ context "and given a String" do
15
+ setup do
16
+ FileUtils.mkdir_p(File.join(ROOT, 'tmp'))
17
+ assert @result = stream_to(@file, File.join(ROOT, 'tmp', 'iostream.string.test'))
18
+ end
19
+
20
+ should "return a File" do
21
+ assert @result.is_a?(File)
22
+ end
23
+
24
+ should "contain the same data as the original file" do
25
+ @file.rewind; @result.rewind
26
+ assert_equal @file.read, @result.read
27
+ end
28
+ end
29
+
30
+ context "and given a Tempfile" do
31
+ setup do
32
+ tempfile = Tempfile.new('iostream.test')
33
+ tempfile.binmode
34
+ assert @result = stream_to(@file, tempfile)
35
+ end
36
+
37
+ should "return a Tempfile" do
38
+ assert @result.is_a?(Tempfile)
39
+ end
40
+
41
+ should "contain the same data as the original file" do
42
+ @file.rewind; @result.rewind
43
+ assert_equal @file.read, @result.read
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ context "that is converted #to_tempfile" do
50
+ setup do
51
+ assert @tempfile = to_tempfile(@file)
52
+ end
53
+
54
+ should "convert it to a Paperclip Tempfile" do
55
+ assert @tempfile.is_a?(Paperclip::Tempfile)
56
+ end
57
+
58
+ should "have the name be based on the original_filename" do
59
+ name = File.basename(@file.path)
60
+ extension = File.extname(name)
61
+ basename = File.basename(name, extension)
62
+ assert_match %r[^stream.*?#{Regexp.quote(extension)}], File.basename(@tempfile.path)
63
+ end
64
+
65
+ should "have the Tempfile contain the same data as the file" do
66
+ @file.rewind; @tempfile.rewind
67
+ assert_equal @file.read, @tempfile.read
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,24 @@
1
+ require './test/helper'
2
+
3
+ class HaveAttachedFileMatcherTest < Test::Unit::TestCase
4
+ context "have_attached_file" do
5
+ setup do
6
+ @dummy_class = reset_class "Dummy"
7
+ reset_table "dummies"
8
+ @matcher = self.class.have_attached_file(:avatar)
9
+ end
10
+
11
+ context "given a class with no attachment" do
12
+ should_reject_dummy_class
13
+ end
14
+
15
+ context "given a class with an attachment" do
16
+ setup do
17
+ modify_table("dummies"){|d| d.string :avatar_file_name }
18
+ @dummy_class.has_attached_file :avatar
19
+ end
20
+
21
+ should_accept_dummy_class
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ require './test/helper'
2
+
3
+ class ValidateAttachmentContentTypeMatcherTest < Test::Unit::TestCase
4
+ context "validate_attachment_content_type" do
5
+ setup do
6
+ reset_table("dummies") do |d|
7
+ d.string :title
8
+ d.string :avatar_file_name
9
+ d.string :avatar_content_type
10
+ end
11
+ @dummy_class = reset_class "Dummy"
12
+ @dummy_class.has_attached_file :avatar
13
+ @matcher = self.class.validate_attachment_content_type(:avatar).
14
+ allowing(%w(image/png image/jpeg)).
15
+ rejecting(%w(audio/mp3 application/octet-stream))
16
+ end
17
+
18
+ context "given a class with no validation" do
19
+ should_reject_dummy_class
20
+ end
21
+
22
+ context "given a class with a validation that doesn't match" do
23
+ setup do
24
+ @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{audio/.*}
25
+ end
26
+
27
+ should_reject_dummy_class
28
+ end
29
+
30
+ context "given a class with a matching validation" do
31
+ setup do
32
+ @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{image/.*}
33
+ end
34
+
35
+ should_accept_dummy_class
36
+ end
37
+
38
+ context "given a class with other validations but matching types" do
39
+ setup do
40
+ @dummy_class.validates_presence_of :title
41
+ @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{image/.*}
42
+ end
43
+
44
+ should_accept_dummy_class
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,26 @@
1
+ require './test/helper'
2
+
3
+ class ValidateAttachmentPresenceMatcherTest < Test::Unit::TestCase
4
+ context "validate_attachment_presence" do
5
+ setup do
6
+ reset_table("dummies") do |d|
7
+ d.string :avatar_file_name
8
+ end
9
+ @dummy_class = reset_class "Dummy"
10
+ @dummy_class.has_attached_file :avatar
11
+ @matcher = self.class.validate_attachment_presence(:avatar)
12
+ end
13
+
14
+ context "given a class with no validation" do
15
+ should_reject_dummy_class
16
+ end
17
+
18
+ context "given a class with a matching validation" do
19
+ setup do
20
+ @dummy_class.validates_attachment_presence :avatar
21
+ end
22
+
23
+ should_accept_dummy_class
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ require './test/helper'
2
+
3
+ class ValidateAttachmentSizeMatcherTest < Test::Unit::TestCase
4
+ context "validate_attachment_size" do
5
+ setup do
6
+ reset_table("dummies") do |d|
7
+ d.string :avatar_file_name
8
+ d.integer :avatar_file_size
9
+ end
10
+ @dummy_class = reset_class "Dummy"
11
+ @dummy_class.has_attached_file :avatar
12
+ end
13
+
14
+ context "of limited size" do
15
+ setup{ @matcher = self.class.validate_attachment_size(:avatar).in(256..1024) }
16
+
17
+ context "given a class with no validation" do
18
+ should_reject_dummy_class
19
+ end
20
+
21
+ context "given a class with a validation that's too high" do
22
+ setup { @dummy_class.validates_attachment_size :avatar, :in => 256..2048 }
23
+ should_reject_dummy_class
24
+ end
25
+
26
+ context "given a class with a validation that's too low" do
27
+ setup { @dummy_class.validates_attachment_size :avatar, :in => 0..1024 }
28
+ should_reject_dummy_class
29
+ end
30
+
31
+ context "given a class with a validation that matches" do
32
+ setup { @dummy_class.validates_attachment_size :avatar, :in => 256..1024 }
33
+ should_accept_dummy_class
34
+ end
35
+ end
36
+
37
+ context "validates_attachment_size with infinite range" do
38
+ setup{ @matcher = self.class.validate_attachment_size(:avatar) }
39
+
40
+ context "given a class with an upper limit" do
41
+ setup { @dummy_class.validates_attachment_size :avatar, :less_than => 1 }
42
+ should_accept_dummy_class
43
+ end
44
+
45
+ context "given a class with no upper limit" do
46
+ setup { @dummy_class.validates_attachment_size :avatar, :greater_than => 1 }
47
+ should_accept_dummy_class
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,254 @@
1
+ require './test/helper'
2
+
3
+ class PaperclipTest < Test::Unit::TestCase
4
+ context "Calling Paperclip.run" do
5
+ setup do
6
+ Paperclip.options[:image_magick_path] = nil
7
+ Paperclip.options[:command_path] = nil
8
+ Paperclip::CommandLine.stubs(:'`')
9
+ end
10
+
11
+ should "execute the right command with :image_magick_path" do
12
+ Paperclip.options[:image_magick_path] = "/usr/bin"
13
+ Paperclip.expects(:log).with(includes('[DEPRECATION]'))
14
+ Paperclip.expects(:log).with(regexp_matches(%r{/usr/bin/convert ['"]one.jpg['"] ['"]two.jpg['"]}))
15
+ Paperclip::CommandLine.expects(:"`").with(regexp_matches(%r{/usr/bin/convert ['"]one.jpg['"] ['"]two.jpg['"]}))
16
+ Paperclip.run("convert", ":one :two", :one => "one.jpg", :two => "two.jpg")
17
+ end
18
+
19
+ should "execute the right command with :command_path" do
20
+ Paperclip.options[:command_path] = "/usr/bin"
21
+ Paperclip::CommandLine.expects(:"`").with(regexp_matches(%r{/usr/bin/convert ['"]one.jpg['"] ['"]two.jpg['"]}))
22
+ Paperclip.run("convert", ":one :two", :one => "one.jpg", :two => "two.jpg")
23
+ end
24
+
25
+ should "execute the right command with no path" do
26
+ Paperclip::CommandLine.expects(:"`").with(regexp_matches(%r{convert ['"]one.jpg['"] ['"]two.jpg['"]}))
27
+ Paperclip.run("convert", ":one :two", :one => "one.jpg", :two => "two.jpg")
28
+ end
29
+
30
+ should "tell you the command isn't there if the shell returns 127" do
31
+ with_exitstatus_returning(127) do
32
+ assert_raises(Paperclip::CommandNotFoundError) do
33
+ Paperclip.run("command")
34
+ end
35
+ end
36
+ end
37
+
38
+ should "tell you the command isn't there if an ENOENT is raised" do
39
+ assert_raises(Paperclip::CommandNotFoundError) do
40
+ Paperclip::CommandLine.stubs(:"`").raises(Errno::ENOENT)
41
+ Paperclip.run("command")
42
+ end
43
+ end
44
+ end
45
+
46
+ should "raise when sent #processor and the name of a class that exists but isn't a subclass of Processor" do
47
+ assert_raises(Paperclip::PaperclipError){ Paperclip.processor(:attachment) }
48
+ end
49
+
50
+ should "raise when sent #processor and the name of a class that doesn't exist" do
51
+ assert_raises(NameError){ Paperclip.processor(:boogey_man) }
52
+ end
53
+
54
+ should "return a class when sent #processor and the name of a class under Paperclip" do
55
+ assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
56
+ end
57
+
58
+ context "An ActiveRecord model with an 'avatar' attachment" do
59
+ setup do
60
+ rebuild_model :path => "tmp/:class/omg/:style.:extension"
61
+ @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
62
+ end
63
+
64
+ teardown { @file.close }
65
+
66
+ should "not error when trying to also create a 'blah' attachment" do
67
+ assert_nothing_raised do
68
+ Dummy.class_eval do
69
+ has_attached_file :blah
70
+ end
71
+ end
72
+ end
73
+
74
+ context "that is attr_protected" do
75
+ setup do
76
+ Dummy.class_eval do
77
+ attr_protected :avatar
78
+ end
79
+ @dummy = Dummy.new
80
+ end
81
+
82
+ should "not assign the avatar on mass-set" do
83
+ @dummy.attributes = { :other => "I'm set!",
84
+ :avatar => @file }
85
+
86
+ assert_equal "I'm set!", @dummy.other
87
+ assert ! @dummy.avatar?
88
+ end
89
+
90
+ should "still allow assigment on normal set" do
91
+ @dummy.other = "I'm set!"
92
+ @dummy.avatar = @file
93
+
94
+ assert_equal "I'm set!", @dummy.other
95
+ assert @dummy.avatar?
96
+ end
97
+ end
98
+
99
+ context "with a subclass" do
100
+ setup do
101
+ class ::SubDummy < Dummy; end
102
+ end
103
+
104
+ should "be able to use the attachment from the subclass" do
105
+ assert_nothing_raised do
106
+ @subdummy = SubDummy.create(:avatar => @file)
107
+ end
108
+ end
109
+
110
+ should "be able to see the attachment definition from the subclass's class" do
111
+ assert_equal "tmp/:class/omg/:style.:extension",
112
+ SubDummy.attachment_definitions[:avatar][:path]
113
+ end
114
+
115
+ teardown do
116
+ Object.send(:remove_const, "SubDummy") rescue nil
117
+ end
118
+ end
119
+
120
+ should "have an #avatar method" do
121
+ assert Dummy.new.respond_to?(:avatar)
122
+ end
123
+
124
+ should "have an #avatar= method" do
125
+ assert Dummy.new.respond_to?(:avatar=)
126
+ end
127
+
128
+ context "that is valid" do
129
+ setup do
130
+ @dummy = Dummy.new
131
+ @dummy.avatar = @file
132
+ end
133
+
134
+ should "be valid" do
135
+ assert @dummy.valid?
136
+ end
137
+ end
138
+
139
+ context "a validation with an if guard clause" do
140
+ setup do
141
+ Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
142
+ @dummy = Dummy.new
143
+ @dummy.stubs(:avatar_file_name).returns(nil)
144
+ end
145
+
146
+ should "attempt validation if the guard returns true" do
147
+ @dummy.expects(:foo).returns(true)
148
+ assert ! @dummy.valid?
149
+ end
150
+
151
+ should "not attempt validation if the guard returns false" do
152
+ @dummy.expects(:foo).returns(false)
153
+ assert @dummy.valid?
154
+ end
155
+ end
156
+
157
+ context "a validation with an unless guard clause" do
158
+ setup do
159
+ Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
160
+ @dummy = Dummy.new
161
+ @dummy.stubs(:avatar_file_name).returns(nil)
162
+ end
163
+
164
+ should "attempt validation if the guard returns true" do
165
+ @dummy.expects(:foo).returns(false)
166
+ assert ! @dummy.valid?
167
+ end
168
+
169
+ should "not attempt validation if the guard returns false" do
170
+ @dummy.expects(:foo).returns(true)
171
+ assert @dummy.valid?
172
+ end
173
+ end
174
+
175
+ should "not have Attachment in the ActiveRecord::Base namespace" do
176
+ assert_raises(NameError) do
177
+ ActiveRecord::Base::Attachment
178
+ end
179
+ end
180
+
181
+ def self.should_validate validation, options, valid_file, invalid_file
182
+ context "with #{validation} validation and #{options.inspect} options" do
183
+ setup do
184
+ rebuild_class
185
+ Dummy.send(:"validates_attachment_#{validation}", :avatar, options)
186
+ @dummy = Dummy.new
187
+ end
188
+ context "and assigning nil" do
189
+ setup do
190
+ @dummy.avatar = nil
191
+ @dummy.valid?
192
+ end
193
+ if validation == :presence
194
+ should "have an error on the attachment" do
195
+ assert @dummy.errors[:avatar_file_name]
196
+ end
197
+ else
198
+ should "not have an error on the attachment" do
199
+ assert @dummy.errors.blank?, @dummy.errors.full_messages.join(", ")
200
+ end
201
+ end
202
+ end
203
+ context "and assigned a valid file" do
204
+ setup do
205
+ @dummy.avatar = valid_file
206
+ @dummy.valid?
207
+ end
208
+ should "not have an error when assigned a valid file" do
209
+ assert_equal 0, @dummy.errors.length, @dummy.errors.full_messages.join(", ")
210
+ end
211
+ end
212
+ context "and assigned an invalid file" do
213
+ setup do
214
+ @dummy.avatar = invalid_file
215
+ @dummy.valid?
216
+ end
217
+ should "have an error when assigned a valid file" do
218
+ assert @dummy.errors.length > 0
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ [[:presence, {}, "5k.png", nil],
225
+ [:size, {:in => 1..10240}, "5k.png", "12k.png"],
226
+ [:size, {:less_than => 10240}, "5k.png", "12k.png"],
227
+ [:size, {:greater_than => 8096}, "12k.png", "5k.png"],
228
+ [:content_type, {:content_type => "image/png"}, "5k.png", "text.txt"],
229
+ [:content_type, {:content_type => "text/plain"}, "text.txt", "5k.png"],
230
+ [:content_type, {:content_type => %r{image/.*}}, "5k.png", "text.txt"]].each do |args|
231
+ validation, options, valid_file, invalid_file = args
232
+ valid_file &&= File.open(File.join(FIXTURES_DIR, valid_file), "rb")
233
+ invalid_file &&= File.open(File.join(FIXTURES_DIR, invalid_file), "rb")
234
+
235
+ should_validate validation, options, valid_file, invalid_file
236
+ end
237
+
238
+ context "with size validation and less_than 10240 option" do
239
+ context "and assigned an invalid file" do
240
+ setup do
241
+ Dummy.send(:"validates_attachment_size", :avatar, :less_than => 10240)
242
+ @dummy = Dummy.new
243
+ @dummy.avatar &&= File.open(File.join(FIXTURES_DIR, "12k.png"), "rb")
244
+ @dummy.valid?
245
+ end
246
+
247
+ should "have a file size min/max error message" do
248
+ assert [@dummy.errors[:avatar_file_size]].flatten.any?{|error| error =~ %r/between 0 and 10240 bytes/ }
249
+ end
250
+ end
251
+ end
252
+
253
+ end
254
+ end