joshpuetz-paperclip 2.3.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.
- data/LICENSE +26 -0
- data/README.rdoc +174 -0
- data/Rakefile +99 -0
- data/generators/paperclip/USAGE +5 -0
- data/generators/paperclip/paperclip_generator.rb +27 -0
- data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
- data/init.rb +1 -0
- data/lib/paperclip/attachment.rb +414 -0
- data/lib/paperclip/callback_compatability.rb +33 -0
- data/lib/paperclip/geometry.rb +115 -0
- data/lib/paperclip/interpolations.rb +105 -0
- data/lib/paperclip/iostream.rb +58 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +49 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +66 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +48 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +83 -0
- data/lib/paperclip/matchers.rb +4 -0
- data/lib/paperclip/processor.rb +49 -0
- data/lib/paperclip/storage.rb +236 -0
- data/lib/paperclip/thumbnail.rb +70 -0
- data/lib/paperclip/upfile.rb +48 -0
- data/lib/paperclip.rb +350 -0
- data/shoulda_macros/paperclip.rb +68 -0
- data/tasks/paperclip_tasks.rake +79 -0
- data/test/attachment_test.rb +767 -0
- data/test/database.yml +4 -0
- data/test/fixtures/12k.png +0 -0
- data/test/fixtures/50x50.png +0 -0
- data/test/fixtures/5k.png +0 -0
- data/test/fixtures/bad.png +1 -0
- data/test/fixtures/s3.yml +4 -0
- data/test/fixtures/text.txt +0 -0
- data/test/fixtures/twopage.pdf +0 -0
- data/test/geometry_test.rb +177 -0
- data/test/helper.rb +99 -0
- data/test/integration_test.rb +481 -0
- data/test/interpolations_test.rb +120 -0
- data/test/iostream_test.rb +71 -0
- data/test/matchers/have_attached_file_matcher_test.rb +21 -0
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +30 -0
- data/test/matchers/validate_attachment_presence_matcher_test.rb +21 -0
- data/test/matchers/validate_attachment_size_matcher_test.rb +50 -0
- data/test/paperclip_test.rb +291 -0
- data/test/processor_test.rb +10 -0
- data/test/storage_test.rb +282 -0
- data/test/thumbnail_test.rb +177 -0
- metadata +125 -0
@@ -0,0 +1,481 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class IntegrationTest < Test::Unit::TestCase
|
4
|
+
context "Many models at once" do
|
5
|
+
setup do
|
6
|
+
rebuild_model
|
7
|
+
@file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
|
8
|
+
300.times do |i|
|
9
|
+
Dummy.create! :avatar => @file
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
should "not exceed the open file limit" do
|
14
|
+
assert_nothing_raised do
|
15
|
+
dummies = Dummy.find(:all)
|
16
|
+
dummies.each { |dummy| dummy.avatar }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "An attachment" do
|
22
|
+
setup do
|
23
|
+
rebuild_model :styles => { :thumb => "50x50#" }
|
24
|
+
@dummy = Dummy.new
|
25
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
26
|
+
"fixtures",
|
27
|
+
"5k.png"), 'rb')
|
28
|
+
@dummy.avatar = @file
|
29
|
+
assert @dummy.save
|
30
|
+
end
|
31
|
+
|
32
|
+
teardown { @file.close }
|
33
|
+
|
34
|
+
should "create its thumbnails properly" do
|
35
|
+
assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
|
36
|
+
end
|
37
|
+
|
38
|
+
context "redefining its attachment styles" do
|
39
|
+
setup do
|
40
|
+
Dummy.class_eval do
|
41
|
+
has_attached_file :avatar, :styles => { :thumb => "150x25#" }
|
42
|
+
has_attached_file :avatar, :styles => { :thumb => "150x25#", :dynamic => lambda { |a| '50x50#' } }
|
43
|
+
end
|
44
|
+
@d2 = Dummy.find(@dummy.id)
|
45
|
+
@d2.avatar.reprocess!
|
46
|
+
@d2.save
|
47
|
+
end
|
48
|
+
|
49
|
+
should "create its thumbnails properly" do
|
50
|
+
assert_match /\b150x25\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
|
51
|
+
assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:dynamic)}"`
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "A model that modifies its original" do
|
57
|
+
setup do
|
58
|
+
rebuild_model :styles => { :original => "2x2#" }
|
59
|
+
@dummy = Dummy.new
|
60
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
61
|
+
"fixtures",
|
62
|
+
"5k.png"), 'rb')
|
63
|
+
@dummy.avatar = @file
|
64
|
+
end
|
65
|
+
|
66
|
+
should "report the file size of the processed file and not the original" do
|
67
|
+
assert_not_equal @file.size, @dummy.avatar.size
|
68
|
+
end
|
69
|
+
|
70
|
+
teardown { @file.close }
|
71
|
+
end
|
72
|
+
|
73
|
+
context "A model with attachments scoped under an id" do
|
74
|
+
setup do
|
75
|
+
rebuild_model :styles => { :large => "100x100",
|
76
|
+
:medium => "50x50" },
|
77
|
+
:path => ":rails_root/tmp/:id/:attachments/:style.:extension"
|
78
|
+
@dummy = Dummy.new
|
79
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
80
|
+
"fixtures",
|
81
|
+
"5k.png"), 'rb')
|
82
|
+
@dummy.avatar = @file
|
83
|
+
end
|
84
|
+
|
85
|
+
teardown { @file.close }
|
86
|
+
|
87
|
+
context "when saved" do
|
88
|
+
setup do
|
89
|
+
@dummy.save
|
90
|
+
@saved_path = @dummy.avatar.path(:large)
|
91
|
+
end
|
92
|
+
|
93
|
+
should "have a large file in the right place" do
|
94
|
+
assert File.exists?(@dummy.avatar.path(:large))
|
95
|
+
end
|
96
|
+
|
97
|
+
context "and deleted" do
|
98
|
+
setup do
|
99
|
+
@dummy.avatar.clear
|
100
|
+
@dummy.save
|
101
|
+
end
|
102
|
+
|
103
|
+
should "not have a large file in the right place anymore" do
|
104
|
+
assert ! File.exists?(@saved_path)
|
105
|
+
end
|
106
|
+
|
107
|
+
should "not have its next two parent directories" do
|
108
|
+
assert ! File.exists?(File.dirname(@saved_path))
|
109
|
+
assert ! File.exists?(File.dirname(File.dirname(@saved_path)))
|
110
|
+
end
|
111
|
+
|
112
|
+
before_should "not die if an unexpected SystemCallError happens" do
|
113
|
+
FileUtils.stubs(:rmdir).raises(Errno::EPIPE)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "A model with no attachment validation" do
|
120
|
+
setup do
|
121
|
+
rebuild_model :styles => { :large => "300x300>",
|
122
|
+
:medium => "100x100",
|
123
|
+
:thumb => ["32x32#", :gif] },
|
124
|
+
:default_style => :medium,
|
125
|
+
:url => "/:attachment/:class/:style/:id/:basename.:extension",
|
126
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
127
|
+
@dummy = Dummy.new
|
128
|
+
end
|
129
|
+
|
130
|
+
should "have its definition return false when asked about whiny_thumbnails" do
|
131
|
+
assert ! Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when validates_attachment_thumbnails is called" do
|
135
|
+
setup do
|
136
|
+
Dummy.validates_attachment_thumbnails :avatar
|
137
|
+
end
|
138
|
+
|
139
|
+
should "have its definition return true when asked about whiny_thumbnails" do
|
140
|
+
assert_equal true, Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "redefined to have attachment validations" do
|
145
|
+
setup do
|
146
|
+
rebuild_model :styles => { :large => "300x300>",
|
147
|
+
:medium => "100x100",
|
148
|
+
:thumb => ["32x32#", :gif] },
|
149
|
+
:whiny_thumbnails => true,
|
150
|
+
:default_style => :medium,
|
151
|
+
:url => "/:attachment/:class/:style/:id/:basename.:extension",
|
152
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
153
|
+
end
|
154
|
+
|
155
|
+
should "have its definition return true when asked about whiny_thumbnails" do
|
156
|
+
assert_equal true, Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "A model with no convert_options setting" do
|
162
|
+
setup do
|
163
|
+
rebuild_model :styles => { :large => "300x300>",
|
164
|
+
:medium => "100x100",
|
165
|
+
:thumb => ["32x32#", :gif] },
|
166
|
+
:default_style => :medium,
|
167
|
+
:url => "/:attachment/:class/:style/:id/:basename.:extension",
|
168
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
169
|
+
@dummy = Dummy.new
|
170
|
+
end
|
171
|
+
|
172
|
+
should "have its definition return nil when asked about convert_options" do
|
173
|
+
assert ! Dummy.attachment_definitions[:avatar][:convert_options]
|
174
|
+
end
|
175
|
+
|
176
|
+
context "redefined to have convert_options setting" do
|
177
|
+
setup do
|
178
|
+
rebuild_model :styles => { :large => "300x300>",
|
179
|
+
:medium => "100x100",
|
180
|
+
:thumb => ["32x32#", :gif] },
|
181
|
+
:convert_options => "-strip -depth 8",
|
182
|
+
:default_style => :medium,
|
183
|
+
:url => "/:attachment/:class/:style/:id/:basename.:extension",
|
184
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
185
|
+
end
|
186
|
+
|
187
|
+
should "have its definition return convert_options value when asked about convert_options" do
|
188
|
+
assert_equal "-strip -depth 8", Dummy.attachment_definitions[:avatar][:convert_options]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "A model with a filesystem attachment" do
|
194
|
+
setup do
|
195
|
+
rebuild_model :styles => { :large => "300x300>",
|
196
|
+
:medium => "100x100",
|
197
|
+
:thumb => ["32x32#", :gif] },
|
198
|
+
:whiny_thumbnails => true,
|
199
|
+
:default_style => :medium,
|
200
|
+
:url => "/:attachment/:class/:style/:id/:basename.:extension",
|
201
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
202
|
+
@dummy = Dummy.new
|
203
|
+
@file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
|
204
|
+
@bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"), 'rb')
|
205
|
+
|
206
|
+
assert @dummy.avatar = @file
|
207
|
+
assert @dummy.valid?
|
208
|
+
assert @dummy.save
|
209
|
+
end
|
210
|
+
|
211
|
+
should "write and delete its files" do
|
212
|
+
[["434x66", :original],
|
213
|
+
["300x46", :large],
|
214
|
+
["100x15", :medium],
|
215
|
+
["32x32", :thumb]].each do |geo, style|
|
216
|
+
cmd = %Q[identify -format "%wx%h" "#{@dummy.avatar.path(style)}"]
|
217
|
+
assert_equal geo, `#{cmd}`.chomp, cmd
|
218
|
+
end
|
219
|
+
|
220
|
+
saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.path(s) }
|
221
|
+
|
222
|
+
@d2 = Dummy.find(@dummy.id)
|
223
|
+
assert_equal "100x15", `identify -format "%wx%h" "#{@d2.avatar.path}"`.chomp
|
224
|
+
assert_equal "434x66", `identify -format "%wx%h" "#{@d2.avatar.path(:original)}"`.chomp
|
225
|
+
assert_equal "300x46", `identify -format "%wx%h" "#{@d2.avatar.path(:large)}"`.chomp
|
226
|
+
assert_equal "100x15", `identify -format "%wx%h" "#{@d2.avatar.path(:medium)}"`.chomp
|
227
|
+
assert_equal "32x32", `identify -format "%wx%h" "#{@d2.avatar.path(:thumb)}"`.chomp
|
228
|
+
|
229
|
+
@dummy.avatar = "not a valid file but not nil"
|
230
|
+
assert_equal File.basename(@file.path), @dummy.avatar_file_name
|
231
|
+
assert @dummy.valid?
|
232
|
+
assert @dummy.save
|
233
|
+
|
234
|
+
saved_paths.each do |p|
|
235
|
+
assert File.exists?(p)
|
236
|
+
end
|
237
|
+
|
238
|
+
@dummy.avatar.clear
|
239
|
+
assert_nil @dummy.avatar_file_name
|
240
|
+
assert @dummy.valid?
|
241
|
+
assert @dummy.save
|
242
|
+
|
243
|
+
saved_paths.each do |p|
|
244
|
+
assert ! File.exists?(p)
|
245
|
+
end
|
246
|
+
|
247
|
+
@d2 = Dummy.find(@dummy.id)
|
248
|
+
assert_nil @d2.avatar_file_name
|
249
|
+
end
|
250
|
+
|
251
|
+
should "work exactly the same when new as when reloaded" do
|
252
|
+
@d2 = Dummy.find(@dummy.id)
|
253
|
+
|
254
|
+
assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
|
255
|
+
[:thumb, :medium, :large, :original].each do |style|
|
256
|
+
assert_equal @dummy.avatar.path(style), @d2.avatar.path(style)
|
257
|
+
end
|
258
|
+
|
259
|
+
saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.path(s) }
|
260
|
+
|
261
|
+
@d2.avatar.clear
|
262
|
+
assert @d2.save
|
263
|
+
|
264
|
+
saved_paths.each do |p|
|
265
|
+
assert ! File.exists?(p)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
should "know the difference between good files, bad files, and not files" do
|
270
|
+
expected = @dummy.avatar.to_file
|
271
|
+
@dummy.avatar = "not a file"
|
272
|
+
assert @dummy.valid?
|
273
|
+
assert_equal expected.path, @dummy.avatar.path
|
274
|
+
expected.close
|
275
|
+
|
276
|
+
@dummy.avatar = @bad_file
|
277
|
+
assert ! @dummy.valid?
|
278
|
+
end
|
279
|
+
|
280
|
+
should "know the difference between good files, bad files, and not files when validating" do
|
281
|
+
Dummy.validates_attachment_presence :avatar
|
282
|
+
@d2 = Dummy.find(@dummy.id)
|
283
|
+
@d2.avatar = @file
|
284
|
+
assert @d2.valid?, @d2.errors.full_messages.inspect
|
285
|
+
@d2.avatar = @bad_file
|
286
|
+
assert ! @d2.valid?
|
287
|
+
end
|
288
|
+
|
289
|
+
should "be able to reload without saving and not have the file disappear" do
|
290
|
+
@dummy.avatar = @file
|
291
|
+
assert @dummy.save
|
292
|
+
@dummy.avatar.clear
|
293
|
+
assert_nil @dummy.avatar_file_name
|
294
|
+
@dummy.reload
|
295
|
+
assert_equal "5k.png", @dummy.avatar_file_name
|
296
|
+
end
|
297
|
+
|
298
|
+
context "that is assigned its file from another Paperclip attachment" do
|
299
|
+
setup do
|
300
|
+
@dummy2 = Dummy.new
|
301
|
+
@file2 = File.new(File.join(FIXTURES_DIR, "12k.png"), 'rb')
|
302
|
+
assert @dummy2.avatar = @file2
|
303
|
+
@dummy2.save
|
304
|
+
end
|
305
|
+
|
306
|
+
should "work when assigned a file" do
|
307
|
+
assert_not_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
|
308
|
+
`identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
|
309
|
+
|
310
|
+
assert @dummy.avatar = @dummy2.avatar
|
311
|
+
@dummy.save
|
312
|
+
assert_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
|
313
|
+
`identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
|
319
|
+
context "A model with an attachments association and a Paperclip attachment" do
|
320
|
+
setup do
|
321
|
+
Dummy.class_eval do
|
322
|
+
has_many :attachments, :class_name => 'Dummy'
|
323
|
+
end
|
324
|
+
|
325
|
+
@dummy = Dummy.new
|
326
|
+
@dummy.avatar = File.new(File.join(File.dirname(__FILE__),
|
327
|
+
"fixtures",
|
328
|
+
"5k.png"), 'rb')
|
329
|
+
end
|
330
|
+
|
331
|
+
should "should not error when saving" do
|
332
|
+
assert_nothing_raised do
|
333
|
+
@dummy.save!
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
if ENV['S3_TEST_BUCKET']
|
339
|
+
def s3_files_for attachment
|
340
|
+
[:thumb, :medium, :large, :original].inject({}) do |files, style|
|
341
|
+
data = `curl "#{attachment.url(style)}" 2>/dev/null`.chomp
|
342
|
+
t = Tempfile.new("paperclip-test")
|
343
|
+
t.binmode
|
344
|
+
t.write(data)
|
345
|
+
t.rewind
|
346
|
+
files[style] = t
|
347
|
+
files
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def s3_headers_for attachment, style
|
352
|
+
`curl --head "#{attachment.url(style)}" 2>/dev/null`.split("\n").inject({}) do |h,head|
|
353
|
+
split_head = head.chomp.split(/\s*:\s*/, 2)
|
354
|
+
h[split_head.first.downcase] = split_head.last unless split_head.empty?
|
355
|
+
h
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context "A model with an S3 attachment" do
|
360
|
+
setup do
|
361
|
+
rebuild_model :styles => { :large => "300x300>",
|
362
|
+
:medium => "100x100",
|
363
|
+
:thumb => ["32x32#", :gif] },
|
364
|
+
:storage => :s3,
|
365
|
+
:whiny_thumbnails => true,
|
366
|
+
# :s3_options => {:logger => Logger.new(StringIO.new)},
|
367
|
+
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml")),
|
368
|
+
:default_style => :medium,
|
369
|
+
:bucket => ENV['S3_TEST_BUCKET'],
|
370
|
+
:path => ":class/:attachment/:id/:style/:basename.:extension"
|
371
|
+
@dummy = Dummy.new
|
372
|
+
@file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
|
373
|
+
@bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"), 'rb')
|
374
|
+
|
375
|
+
assert @dummy.avatar = @file
|
376
|
+
assert @dummy.valid?
|
377
|
+
assert @dummy.save
|
378
|
+
|
379
|
+
@files_on_s3 = s3_files_for @dummy.avatar
|
380
|
+
end
|
381
|
+
|
382
|
+
should "write and delete its files" do
|
383
|
+
[["434x66", :original],
|
384
|
+
["300x46", :large],
|
385
|
+
["100x15", :medium],
|
386
|
+
["32x32", :thumb]].each do |geo, style|
|
387
|
+
cmd = %Q[identify -format "%wx%h" "#{@files_on_s3[style].path}"]
|
388
|
+
assert_equal geo, `#{cmd}`.chomp, cmd
|
389
|
+
end
|
390
|
+
|
391
|
+
@d2 = Dummy.find(@dummy.id)
|
392
|
+
@d2_files = s3_files_for @d2.avatar
|
393
|
+
[["434x66", :original],
|
394
|
+
["300x46", :large],
|
395
|
+
["100x15", :medium],
|
396
|
+
["32x32", :thumb]].each do |geo, style|
|
397
|
+
cmd = %Q[identify -format "%wx%h" "#{@d2_files[style].path}"]
|
398
|
+
assert_equal geo, `#{cmd}`.chomp, cmd
|
399
|
+
end
|
400
|
+
|
401
|
+
@dummy.avatar = "not a valid file but not nil"
|
402
|
+
assert_equal File.basename(@file.path), @dummy.avatar_file_name
|
403
|
+
assert @dummy.valid?
|
404
|
+
assert @dummy.save
|
405
|
+
|
406
|
+
saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
|
407
|
+
|
408
|
+
saved_keys.each do |key|
|
409
|
+
assert key.exists?
|
410
|
+
end
|
411
|
+
|
412
|
+
@dummy.avatar.clear
|
413
|
+
assert_nil @dummy.avatar_file_name
|
414
|
+
assert @dummy.valid?
|
415
|
+
assert @dummy.save
|
416
|
+
|
417
|
+
saved_keys.each do |key|
|
418
|
+
assert ! key.exists?
|
419
|
+
end
|
420
|
+
|
421
|
+
@d2 = Dummy.find(@dummy.id)
|
422
|
+
assert_nil @d2.avatar_file_name
|
423
|
+
end
|
424
|
+
|
425
|
+
should "work exactly the same when new as when reloaded" do
|
426
|
+
@d2 = Dummy.find(@dummy.id)
|
427
|
+
|
428
|
+
assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
|
429
|
+
[:thumb, :medium, :large, :original].each do |style|
|
430
|
+
assert_equal @dummy.avatar.to_file(style).to_s, @d2.avatar.to_file(style).to_s
|
431
|
+
end
|
432
|
+
|
433
|
+
saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
|
434
|
+
|
435
|
+
@d2.avatar.clear
|
436
|
+
assert @d2.save
|
437
|
+
|
438
|
+
saved_keys.each do |key|
|
439
|
+
assert ! key.exists?
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
should "know the difference between good files, bad files, not files, and nil" do
|
444
|
+
expected = @dummy.avatar.to_file
|
445
|
+
@dummy.avatar = "not a file"
|
446
|
+
assert @dummy.valid?
|
447
|
+
assert_equal expected.full_name, @dummy.avatar.to_file.full_name
|
448
|
+
|
449
|
+
@dummy.avatar = @bad_file
|
450
|
+
assert ! @dummy.valid?
|
451
|
+
@dummy.avatar = nil
|
452
|
+
assert @dummy.valid?
|
453
|
+
|
454
|
+
Dummy.validates_attachment_presence :avatar
|
455
|
+
@d2 = Dummy.find(@dummy.id)
|
456
|
+
@d2.avatar = @file
|
457
|
+
assert @d2.valid?
|
458
|
+
@d2.avatar = @bad_file
|
459
|
+
assert ! @d2.valid?
|
460
|
+
@d2.avatar = nil
|
461
|
+
assert ! @d2.valid?
|
462
|
+
end
|
463
|
+
|
464
|
+
should "be able to reload without saving and not have the file disappear" do
|
465
|
+
@dummy.avatar = @file
|
466
|
+
assert @dummy.save
|
467
|
+
@dummy.avatar = nil
|
468
|
+
assert_nil @dummy.avatar_file_name
|
469
|
+
@dummy.reload
|
470
|
+
assert_equal "5k.png", @dummy.avatar_file_name
|
471
|
+
end
|
472
|
+
|
473
|
+
should "have the right content type" do
|
474
|
+
headers = s3_headers_for(@dummy.avatar, :original)
|
475
|
+
p headers
|
476
|
+
assert_equal 'image/png', headers['content-type']
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
@@ -0,0 +1,120 @@
|
|
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 instance" do
|
23
|
+
attachment = mock
|
24
|
+
attachment.expects(:instance).returns(attachment)
|
25
|
+
attachment.expects(:class).returns("Thing")
|
26
|
+
assert_equal "things", Paperclip::Interpolations.class(attachment, :style)
|
27
|
+
end
|
28
|
+
|
29
|
+
should "return the basename of the file" do
|
30
|
+
attachment = mock
|
31
|
+
attachment.expects(:original_filename).returns("one.jpg").times(2)
|
32
|
+
assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
|
33
|
+
end
|
34
|
+
|
35
|
+
should "return the extension of the file" do
|
36
|
+
attachment = mock
|
37
|
+
attachment.expects(:original_filename).returns("one.jpg")
|
38
|
+
attachment.expects(:styles).returns({})
|
39
|
+
assert_equal "jpg", Paperclip::Interpolations.extension(attachment, :style)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "return the extension of the file as the format if defined in the style" do
|
43
|
+
attachment = mock
|
44
|
+
attachment.expects(:original_filename).never
|
45
|
+
attachment.expects(:styles).returns({:style => {:format => "png"}})
|
46
|
+
assert_equal "png", Paperclip::Interpolations.extension(attachment, :style)
|
47
|
+
end
|
48
|
+
|
49
|
+
should "return the id of the attachment" do
|
50
|
+
attachment = mock
|
51
|
+
attachment.expects(:id).returns(23)
|
52
|
+
attachment.expects(:instance).returns(attachment)
|
53
|
+
assert_equal 23, Paperclip::Interpolations.id(attachment, :style)
|
54
|
+
end
|
55
|
+
|
56
|
+
should "return the partitioned id of the attachment" do
|
57
|
+
attachment = mock
|
58
|
+
attachment.expects(:id).returns(23)
|
59
|
+
attachment.expects(:instance).returns(attachment)
|
60
|
+
assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
|
61
|
+
end
|
62
|
+
|
63
|
+
should "return the name of the attachment" do
|
64
|
+
attachment = mock
|
65
|
+
attachment.expects(:name).returns("file")
|
66
|
+
assert_equal "files", Paperclip::Interpolations.attachment(attachment, :style)
|
67
|
+
end
|
68
|
+
|
69
|
+
should "return the style" do
|
70
|
+
assert_equal :style, Paperclip::Interpolations.style(:attachment, :style)
|
71
|
+
end
|
72
|
+
|
73
|
+
should "return the default style" do
|
74
|
+
attachment = mock
|
75
|
+
attachment.expects(:default_style).returns(:default_style)
|
76
|
+
assert_equal :default_style, Paperclip::Interpolations.style(attachment, nil)
|
77
|
+
end
|
78
|
+
|
79
|
+
should "reinterpolate :url" do
|
80
|
+
attachment = mock
|
81
|
+
attachment.expects(:options).returns({:url => ":id"})
|
82
|
+
attachment.expects(:url).with(:style, false).returns("1234")
|
83
|
+
assert_equal "1234", Paperclip::Interpolations.url(attachment, :style)
|
84
|
+
end
|
85
|
+
|
86
|
+
should "raise if infinite loop detcted reinterpolating :url" do
|
87
|
+
attachment = mock
|
88
|
+
attachment.expects(:options).returns({:url => ":url"})
|
89
|
+
assert_raises(Paperclip::InfiniteInterpolationError){ Paperclip::Interpolations.url(attachment, :style) }
|
90
|
+
end
|
91
|
+
|
92
|
+
should "return the filename as basename.extension" do
|
93
|
+
attachment = mock
|
94
|
+
attachment.expects(:styles).returns({})
|
95
|
+
attachment.expects(:original_filename).returns("one.jpg").times(3)
|
96
|
+
assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
|
97
|
+
end
|
98
|
+
|
99
|
+
should "return the filename as basename.extension when format supplied" do
|
100
|
+
attachment = mock
|
101
|
+
attachment.expects(:styles).returns({:style => {:format => :png}})
|
102
|
+
attachment.expects(:original_filename).returns("one.jpg").times(2)
|
103
|
+
assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
|
104
|
+
end
|
105
|
+
|
106
|
+
should "return the timestamp" do
|
107
|
+
now = Time.now
|
108
|
+
attachment = mock
|
109
|
+
attachment.expects(:instance_read).with(:updated_at).returns(now)
|
110
|
+
assert_equal now.to_s, Paperclip::Interpolations.timestamp(attachment, :style)
|
111
|
+
end
|
112
|
+
|
113
|
+
should "call all expected interpolations with the given arguments" do
|
114
|
+
Paperclip::Interpolations.expects(:id).with(:attachment, :style).returns(1234)
|
115
|
+
Paperclip::Interpolations.expects(:attachment).with(:attachment, :style).returns("attachments")
|
116
|
+
Paperclip::Interpolations.expects(:notreal).never
|
117
|
+
value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
|
118
|
+
assert_equal ":notreal/1234/attachments", value
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class IOStreamTest < Test::Unit::TestCase
|
4
|
+
context "IOStream" do
|
5
|
+
should "be included in IO, File, Tempfile, and StringIO" do
|
6
|
+
[IO, File, Tempfile, StringIO].each do |klass|
|
7
|
+
assert klass.included_modules.include?(IOStream), "Not in #{klass}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "A file" do
|
13
|
+
setup do
|
14
|
+
@file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
teardown { @file.close }
|
18
|
+
|
19
|
+
context "that is sent #stream_to" do
|
20
|
+
|
21
|
+
context "and given a String" do
|
22
|
+
setup do
|
23
|
+
FileUtils.mkdir_p(File.join(ROOT, 'tmp'))
|
24
|
+
assert @result = @file.stream_to(File.join(ROOT, 'tmp', 'iostream.string.test'))
|
25
|
+
end
|
26
|
+
|
27
|
+
should "return a File" do
|
28
|
+
assert @result.is_a?(File)
|
29
|
+
end
|
30
|
+
|
31
|
+
should "contain the same data as the original file" do
|
32
|
+
@file.rewind; @result.rewind
|
33
|
+
assert_equal @file.read, @result.read
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "and given a Tempfile" do
|
38
|
+
setup do
|
39
|
+
tempfile = Tempfile.new('iostream.test')
|
40
|
+
tempfile.binmode
|
41
|
+
assert @result = @file.stream_to(tempfile)
|
42
|
+
end
|
43
|
+
|
44
|
+
should "return a Tempfile" do
|
45
|
+
assert @result.is_a?(Tempfile)
|
46
|
+
end
|
47
|
+
|
48
|
+
should "contain the same data as the original file" do
|
49
|
+
@file.rewind; @result.rewind
|
50
|
+
assert_equal @file.read, @result.read
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context "that is sent #to_tempfile" do
|
57
|
+
setup do
|
58
|
+
assert @tempfile = @file.to_tempfile
|
59
|
+
end
|
60
|
+
|
61
|
+
should "convert it to a Tempfile" do
|
62
|
+
assert @tempfile.is_a?(Tempfile)
|
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,21 @@
|
|
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
|
+
should "reject a class with no attachment" do
|
12
|
+
assert_rejects @matcher, @dummy_class
|
13
|
+
end
|
14
|
+
|
15
|
+
should "accept a class with an attachment" do
|
16
|
+
modify_table("dummies"){|d| d.string :avatar_file_name }
|
17
|
+
@dummy_class.has_attached_file :avatar
|
18
|
+
assert_accepts @matcher, @dummy_class
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|