lostboy-paperclip 2.2.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/LICENSE +26 -0
  2. data/README.rdoc +172 -0
  3. data/Rakefile +77 -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/paperclip/attachment.rb +398 -0
  9. data/lib/paperclip/callback_compatability.rb +33 -0
  10. data/lib/paperclip/geometry.rb +115 -0
  11. data/lib/paperclip/iostream.rb +58 -0
  12. data/lib/paperclip/matchers/have_attached_file_matcher.rb +49 -0
  13. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +66 -0
  14. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +48 -0
  15. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +83 -0
  16. data/lib/paperclip/matchers.rb +4 -0
  17. data/lib/paperclip/processor.rb +48 -0
  18. data/lib/paperclip/storage.rb +241 -0
  19. data/lib/paperclip/thumbnail.rb +70 -0
  20. data/lib/paperclip/upfile.rb +48 -0
  21. data/lib/paperclip.rb +318 -0
  22. data/shoulda_macros/paperclip.rb +68 -0
  23. data/tasks/paperclip_tasks.rake +79 -0
  24. data/test/attachment_test.rb +723 -0
  25. data/test/database.yml +4 -0
  26. data/test/fixtures/12k.png +0 -0
  27. data/test/fixtures/50x50.png +0 -0
  28. data/test/fixtures/5k.png +0 -0
  29. data/test/fixtures/bad.png +1 -0
  30. data/test/fixtures/text.txt +0 -0
  31. data/test/fixtures/twopage.pdf +0 -0
  32. data/test/geometry_test.rb +168 -0
  33. data/test/helper.rb +82 -0
  34. data/test/integration_test.rb +495 -0
  35. data/test/iostream_test.rb +71 -0
  36. data/test/matchers/have_attached_file_matcher_test.rb +21 -0
  37. data/test/matchers/validate_attachment_content_type_matcher_test.rb +30 -0
  38. data/test/matchers/validate_attachment_presence_matcher_test.rb +21 -0
  39. data/test/matchers/validate_attachment_size_matcher_test.rb +50 -0
  40. data/test/paperclip_test.rb +237 -0
  41. data/test/processor_test.rb +10 -0
  42. data/test/storage_test.rb +277 -0
  43. data/test/thumbnail_test.rb +177 -0
  44. metadata +133 -0
@@ -0,0 +1,723 @@
1
+ require 'test/helper'
2
+
3
+ class Dummy
4
+ # This is a dummy class
5
+ end
6
+
7
+ class AttachmentTest < Test::Unit::TestCase
8
+ context "Attachment default_options" do
9
+ setup do
10
+ rebuild_model
11
+ @old_default_options = Paperclip::Attachment.default_options.dup
12
+ @new_default_options = @old_default_options.merge({
13
+ :path => "argle/bargle",
14
+ :url => "fooferon",
15
+ :default_url => "not here.png"
16
+ })
17
+ end
18
+
19
+ teardown do
20
+ Paperclip::Attachment.default_options.merge! @old_default_options
21
+ end
22
+
23
+ should "be overrideable" do
24
+ Paperclip::Attachment.default_options.merge!(@new_default_options)
25
+ @new_default_options.keys.each do |key|
26
+ assert_equal @new_default_options[key],
27
+ Paperclip::Attachment.default_options[key]
28
+ end
29
+ end
30
+
31
+ context "without an Attachment" do
32
+ setup do
33
+ @dummy = Dummy.new
34
+ end
35
+
36
+ should "return false when asked exists?" do
37
+ assert !@dummy.avatar.exists?
38
+ end
39
+ end
40
+
41
+ context "on an Attachment" do
42
+ setup do
43
+ @dummy = Dummy.new
44
+ @attachment = @dummy.avatar
45
+ end
46
+
47
+ Paperclip::Attachment.default_options.keys.each do |key|
48
+ should "be the default_options for #{key}" do
49
+ assert_equal @old_default_options[key],
50
+ @attachment.instance_variable_get("@#{key}"),
51
+ key
52
+ end
53
+ end
54
+
55
+ context "when redefined" do
56
+ setup do
57
+ Paperclip::Attachment.default_options.merge!(@new_default_options)
58
+ @dummy = Dummy.new
59
+ @attachment = @dummy.avatar
60
+ end
61
+
62
+ Paperclip::Attachment.default_options.keys.each do |key|
63
+ should "be the new default_options for #{key}" do
64
+ assert_equal @new_default_options[key],
65
+ @attachment.instance_variable_get("@#{key}"),
66
+ key
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ context "An attachment with similarly named interpolations" do
74
+ setup do
75
+ rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
76
+ @dummy = Dummy.new
77
+ @dummy.stubs(:id).returns(1024)
78
+ @file = File.new(File.join(File.dirname(__FILE__),
79
+ "fixtures",
80
+ "5k.png"), 'rb')
81
+ @dummy.avatar = @file
82
+ end
83
+
84
+ teardown { @file.close }
85
+
86
+ should "make sure that they are interpolated correctly" do
87
+ assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
88
+ end
89
+ end
90
+
91
+ context "An attachment with a :rails_env interpolation" do
92
+ setup do
93
+ @rails_env = "blah"
94
+ @id = 1024
95
+ rebuild_model :path => ":rails_env/:id.png"
96
+ @dummy = Dummy.new
97
+ @dummy.stubs(:id).returns(@id)
98
+ @file = StringIO.new(".")
99
+ @dummy.avatar = @file
100
+ end
101
+
102
+ should "return the proper path" do
103
+ temporary_rails_env(@rails_env) {
104
+ assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
105
+ }
106
+ end
107
+ end
108
+
109
+ context "An attachment with :convert_options" do
110
+ setup do
111
+ rebuild_model :styles => {
112
+ :thumb => "100x100",
113
+ :large => "400x400"
114
+ },
115
+ :convert_options => {
116
+ :all => "-do_stuff",
117
+ :thumb => "-thumbnailize"
118
+ }
119
+ @dummy = Dummy.new
120
+ @dummy.avatar
121
+ end
122
+
123
+ should "report the correct options when sent #extra_options_for(:thumb)" do
124
+ assert_equal "-thumbnailize -do_stuff", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
125
+ end
126
+
127
+ should "report the correct options when sent #extra_options_for(:large)" do
128
+ assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
129
+ end
130
+
131
+ before_should "call extra_options_for(:thumb/:large)" do
132
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
133
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
134
+ end
135
+ end
136
+
137
+ context "An attachment with :convert_options that is a proc" do
138
+ setup do
139
+ rebuild_model :styles => {
140
+ :thumb => "100x100",
141
+ :large => "400x400"
142
+ },
143
+ :convert_options => {
144
+ :all => lambda{|i| i.all },
145
+ :thumb => lambda{|i| i.thumb }
146
+ }
147
+ Dummy.class_eval do
148
+ def all; "-all"; end
149
+ def thumb; "-thumb"; end
150
+ end
151
+ @dummy = Dummy.new
152
+ @dummy.avatar
153
+ end
154
+
155
+ should "report the correct options when sent #extra_options_for(:thumb)" do
156
+ assert_equal "-thumb -all", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
157
+ end
158
+
159
+ should "report the correct options when sent #extra_options_for(:large)" do
160
+ assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
161
+ end
162
+
163
+ before_should "call extra_options_for(:thumb/:large)" do
164
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
165
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
166
+ end
167
+ end
168
+
169
+ context "An attachment with :path that is a proc" do
170
+ setup do
171
+ rebuild_model :path => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
172
+
173
+ @file = File.new(File.join(File.dirname(__FILE__),
174
+ "fixtures",
175
+ "5k.png"), 'rb')
176
+ @dummyA = Dummy.new(:other => 'a')
177
+ @dummyA.avatar = @file
178
+ @dummyB = Dummy.new(:other => 'b')
179
+ @dummyB.avatar = @file
180
+ end
181
+
182
+ teardown { @file.close }
183
+
184
+ should "return correct path" do
185
+ assert_equal "path/a.png", @dummyA.avatar.path
186
+ assert_equal "path/b.png", @dummyB.avatar.path
187
+ end
188
+ end
189
+
190
+ context "An attachment with :styles that is a proc" do
191
+ setup do
192
+ rebuild_model :styles => lambda{ |attachment| {:thumb => "50x50#", :large => "400x400"} }
193
+
194
+ @attachment = Dummy.new.avatar
195
+ end
196
+
197
+ should "have the correct geometry" do
198
+ assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
199
+ end
200
+ end
201
+
202
+ context "An attachment with :url that is a proc" do
203
+ setup do
204
+ rebuild_model :url => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
205
+
206
+ @file = File.new(File.join(File.dirname(__FILE__),
207
+ "fixtures",
208
+ "5k.png"), 'rb')
209
+ @dummyA = Dummy.new(:other => 'a')
210
+ @dummyA.avatar = @file
211
+ @dummyB = Dummy.new(:other => 'b')
212
+ @dummyB.avatar = @file
213
+ end
214
+
215
+ teardown { @file.close }
216
+
217
+ should "return correct url" do
218
+ assert_equal "path/a.png", @dummyA.avatar.url(:original, false)
219
+ assert_equal "path/b.png", @dummyB.avatar.url(:original, false)
220
+ end
221
+ end
222
+
223
+ geometry_specs = [
224
+ [ lambda{|z| "50x50#" }, :png ],
225
+ lambda{|z| "50x50#" },
226
+ { :geometry => lambda{|z| "50x50#" } }
227
+ ]
228
+ geometry_specs.each do |geometry_spec|
229
+ context "An attachment geometry like #{geometry_spec}" do
230
+ setup do
231
+ rebuild_model :styles => { :normal => geometry_spec }
232
+ @attachment = Dummy.new.avatar
233
+ end
234
+
235
+ should "not run the procs immediately" do
236
+ assert_kind_of Proc, @attachment.styles[:normal][:geometry]
237
+ end
238
+
239
+ context "when assigned" do
240
+ setup do
241
+ @file = StringIO.new(".")
242
+ @attachment.assign(@file)
243
+ end
244
+
245
+ should "have the correct geometry" do
246
+ assert_equal "50x50#", @attachment.styles[:normal][:geometry]
247
+ end
248
+ end
249
+ end
250
+ end
251
+
252
+ context "An attachment with both 'normal' and hash-style styles" do
253
+ setup do
254
+ rebuild_model :styles => {
255
+ :normal => ["50x50#", :png],
256
+ :hash => { :geometry => "50x50#", :format => :png }
257
+ }
258
+ @dummy = Dummy.new
259
+ @attachment = @dummy.avatar
260
+ end
261
+
262
+ [:processors, :whiny, :convert_options, :geometry, :format].each do |field|
263
+ should "have the same #{field} field" do
264
+ assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
265
+ end
266
+ end
267
+ end
268
+
269
+ context "An attachment with :processors that is a proc" do
270
+ setup do
271
+ rebuild_model :styles => { :normal => '' }, :processors => lambda { |a| [ :test ] }
272
+ @attachment = Dummy.new.avatar
273
+ end
274
+
275
+ should "not run the proc immediately" do
276
+ assert_kind_of Proc, @attachment.styles[:normal][:processors]
277
+ end
278
+
279
+ context "when assigned" do
280
+ setup do
281
+ @attachment.assign(StringIO.new("."))
282
+ end
283
+
284
+ should "have the correct processors" do
285
+ assert_equal [ :test ], @attachment.styles[:normal][:processors]
286
+ end
287
+ end
288
+ end
289
+
290
+ context "An attachment with erroring processor" do
291
+ setup do
292
+ rebuild_model :processor => [:thumbnail], :styles => { :small => '' }, :whiny_thumbnails => true
293
+ @dummy = Dummy.new
294
+ Paperclip::Thumbnail.expects(:make).raises(Paperclip::PaperclipError, "cannot be processed.")
295
+ @file = StringIO.new("...")
296
+ @file.stubs(:to_tempfile).returns(@file)
297
+ @dummy.avatar = @file
298
+ end
299
+
300
+ should "correctly forward processing error message to the instance" do
301
+ @dummy.valid?
302
+ assert_contains @dummy.errors.full_messages, "Avatar cannot be processed."
303
+ end
304
+ end
305
+
306
+ context "An attachment with multiple processors" do
307
+ setup do
308
+ class Paperclip::Test < Paperclip::Processor; end
309
+ @style_params = { :once => {:one => 1, :two => 2} }
310
+ rebuild_model :processors => [:thumbnail, :test], :styles => @style_params
311
+ @dummy = Dummy.new
312
+ @file = StringIO.new("...")
313
+ @file.stubs(:to_tempfile).returns(@file)
314
+ Paperclip::Test.stubs(:make).returns(@file)
315
+ Paperclip::Thumbnail.stubs(:make).returns(@file)
316
+ end
317
+
318
+ context "when assigned" do
319
+ setup { @dummy.avatar = @file }
320
+
321
+ before_should "call #make on all specified processors" do
322
+ expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => nil, :convert_options => ""})
323
+ Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
324
+ Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
325
+ end
326
+
327
+ before_should "call #make with attachment passed as third argument" do
328
+ expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => nil, :convert_options => ""})
329
+ Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
330
+ end
331
+ end
332
+ end
333
+
334
+ context "An attachment with no processors defined" do
335
+ setup do
336
+ rebuild_model :processors => [], :styles => {:something => 1}
337
+ @dummy = Dummy.new
338
+ @file = StringIO.new("...")
339
+ end
340
+ should "raise when assigned to" do
341
+ assert_raises(RuntimeError){ @dummy.avatar = @file }
342
+ end
343
+ end
344
+
345
+ context "Assigning an attachment with post_process hooks" do
346
+ setup do
347
+ rebuild_model :styles => { :something => "100x100#" }
348
+ Dummy.class_eval do
349
+ before_avatar_post_process :do_before_avatar
350
+ after_avatar_post_process :do_after_avatar
351
+ before_post_process :do_before_all
352
+ after_post_process :do_after_all
353
+ def do_before_avatar; end
354
+ def do_after_avatar; end
355
+ def do_before_all; end
356
+ def do_after_all; end
357
+ end
358
+ @file = StringIO.new(".")
359
+ @file.stubs(:to_tempfile).returns(@file)
360
+ @dummy = Dummy.new
361
+ Paperclip::Thumbnail.stubs(:make).returns(@file)
362
+ @attachment = @dummy.avatar
363
+ end
364
+
365
+ should "call the defined callbacks when assigned" do
366
+ @dummy.expects(:do_before_avatar).with()
367
+ @dummy.expects(:do_after_avatar).with()
368
+ @dummy.expects(:do_before_all).with()
369
+ @dummy.expects(:do_after_all).with()
370
+ Paperclip::Thumbnail.expects(:make).returns(@file)
371
+ @dummy.avatar = @file
372
+ end
373
+
374
+ should "not cancel the processing if a before_post_process returns nil" do
375
+ @dummy.expects(:do_before_avatar).with().returns(nil)
376
+ @dummy.expects(:do_after_avatar).with()
377
+ @dummy.expects(:do_before_all).with().returns(nil)
378
+ @dummy.expects(:do_after_all).with()
379
+ Paperclip::Thumbnail.expects(:make).returns(@file)
380
+ @dummy.avatar = @file
381
+ end
382
+
383
+ should "cancel the processing if a before_post_process returns false" do
384
+ @dummy.expects(:do_before_avatar).never
385
+ @dummy.expects(:do_after_avatar).never
386
+ @dummy.expects(:do_before_all).with().returns(false)
387
+ @dummy.expects(:do_after_all).never
388
+ Paperclip::Thumbnail.expects(:make).never
389
+ @dummy.avatar = @file
390
+ end
391
+
392
+ should "cancel the processing if a before_avatar_post_process returns false" do
393
+ @dummy.expects(:do_before_avatar).with().returns(false)
394
+ @dummy.expects(:do_after_avatar).never
395
+ @dummy.expects(:do_before_all).with().returns(true)
396
+ @dummy.expects(:do_after_all).never
397
+ Paperclip::Thumbnail.expects(:make).never
398
+ @dummy.avatar = @file
399
+ end
400
+ end
401
+
402
+ context "Assigning an attachment" do
403
+ setup do
404
+ rebuild_model :styles => { :something => "100x100#" }
405
+ @file = StringIO.new(".")
406
+ @file.expects(:original_filename).returns("5k.png\n\n")
407
+ @file.expects(:content_type).returns("image/png\n\n")
408
+ @file.stubs(:to_tempfile).returns(@file)
409
+ @dummy = Dummy.new
410
+ Paperclip::Thumbnail.expects(:make).returns(@file)
411
+ @dummy.expects(:run_callbacks).with(:before_avatar_post_process, {:original => @file})
412
+ @dummy.expects(:run_callbacks).with(:before_post_process, {:original => @file})
413
+ @dummy.expects(:run_callbacks).with(:after_avatar_post_process, {:original => @file, :something => @file})
414
+ @dummy.expects(:run_callbacks).with(:after_post_process, {:original => @file, :something => @file})
415
+ @attachment = @dummy.avatar
416
+ @dummy.avatar = @file
417
+ end
418
+
419
+ should "strip whitespace from original_filename field" do
420
+ assert_equal "5k.png", @dummy.avatar.original_filename
421
+ end
422
+
423
+ should "strip whitespace from content_type field" do
424
+ assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
425
+ end
426
+ end
427
+
428
+ context "Attachment with strange letters" do
429
+ setup do
430
+ rebuild_model
431
+
432
+ @not_file = mock
433
+ @tempfile = mock
434
+ @not_file.stubs(:nil?).returns(false)
435
+ @not_file.expects(:size).returns(10)
436
+ @tempfile.expects(:size).returns(10)
437
+ @not_file.expects(:to_tempfile).returns(@tempfile)
438
+ @not_file.expects(:original_filename).returns("sheep_say_bæ.png\r\n")
439
+ @not_file.expects(:content_type).returns("image/png\r\n")
440
+
441
+ @dummy = Dummy.new
442
+ @attachment = @dummy.avatar
443
+ @attachment.expects(:valid_assignment?).with(@not_file).returns(true)
444
+ @attachment.expects(:queue_existing_for_delete)
445
+ @attachment.expects(:post_process)
446
+ @attachment.expects(:valid?).returns(true)
447
+ @attachment.expects(:validate)
448
+ @dummy.avatar = @not_file
449
+ end
450
+
451
+ should "remove strange letters and replace with underscore (_)" do
452
+ assert_equal "sheep_say_b_.png", @dummy.avatar.original_filename
453
+ end
454
+
455
+ end
456
+
457
+ context "An attachment" do
458
+ setup do
459
+ Paperclip::Attachment.default_options.merge!({
460
+ :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
461
+ })
462
+ FileUtils.rm_rf("tmp")
463
+ rebuild_model
464
+ @instance = Dummy.new
465
+ @attachment = Paperclip::Attachment.new(:avatar, @instance)
466
+ @file = File.new(File.join(File.dirname(__FILE__),
467
+ "fixtures",
468
+ "5k.png"), 'rb')
469
+ end
470
+
471
+ teardown { @file.close }
472
+
473
+ should "raise if there are not the correct columns when you try to assign" do
474
+ @other_attachment = Paperclip::Attachment.new(:not_here, @instance)
475
+ assert_raises(Paperclip::PaperclipError) do
476
+ @other_attachment.assign(@file)
477
+ end
478
+ end
479
+
480
+ should "return its default_url when no file assigned" do
481
+ assert @attachment.to_file.nil?
482
+ assert_equal "/avatars/original/missing.png", @attachment.url
483
+ assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
484
+ end
485
+
486
+ should "return nil as path when no file assigned" do
487
+ assert @attachment.to_file.nil?
488
+ assert_equal nil, @attachment.path
489
+ assert_equal nil, @attachment.path(:blah)
490
+ end
491
+
492
+ context "with a file assigned in the database" do
493
+ setup do
494
+ @attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
495
+ @attachment.stubs(:instance_read).with(:content_type).returns("image/png")
496
+ @attachment.stubs(:instance_read).with(:file_size).returns(12345)
497
+ now = Time.now
498
+ Time.stubs(:now).returns(now)
499
+ @attachment.stubs(:instance_read).with(:updated_at).returns(Time.now)
500
+ end
501
+
502
+ should "return a correct url even if the file does not exist" do
503
+ assert_nil @attachment.to_file
504
+ assert_match %r{^/system/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
505
+ end
506
+
507
+ should "make sure the updated_at mtime is in the url if it is defined" do
508
+ assert_match %r{#{Time.now.to_i}$}, @attachment.url(:blah)
509
+ end
510
+
511
+ should "make sure the updated_at mtime is NOT in the url if false is passed to the url method" do
512
+ assert_no_match %r{#{Time.now.to_i}$}, @attachment.url(:blah, false)
513
+ end
514
+
515
+ context "with the updated_at field removed" do
516
+ setup do
517
+ @attachment.stubs(:instance_read).with(:updated_at).returns(nil)
518
+ end
519
+
520
+ should "only return the url without the updated_at when sent #url" do
521
+ assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
522
+ end
523
+ end
524
+
525
+ should "return the proper path when filename has a single .'s" do
526
+ assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png", @attachment.path
527
+ end
528
+
529
+ should "return the proper path when filename has multiple .'s" do
530
+ @attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
531
+ assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png", @attachment.path
532
+ end
533
+
534
+ context "when expecting three styles" do
535
+ setup do
536
+ styles = {:styles => { :large => ["400x400", :png],
537
+ :medium => ["100x100", :gif],
538
+ :small => ["32x32#", :jpg]}}
539
+ @attachment = Paperclip::Attachment.new(:avatar,
540
+ @instance,
541
+ styles)
542
+ end
543
+
544
+ context "and assigned a file" do
545
+ setup do
546
+ now = Time.now
547
+ Time.stubs(:now).returns(now)
548
+ @attachment.assign(@file)
549
+ end
550
+
551
+ should "be dirty" do
552
+ assert @attachment.dirty?
553
+ end
554
+
555
+ context "and saved" do
556
+ setup do
557
+ @attachment.save
558
+ end
559
+
560
+ should "return the real url" do
561
+ file = @attachment.to_file
562
+ assert file
563
+ assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
564
+ assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
565
+ file.close
566
+ end
567
+
568
+ should "commit the files to disk" do
569
+ [:large, :medium, :small].each do |style|
570
+ io = @attachment.to_io(style)
571
+ assert File.exists?(io)
572
+ assert ! io.is_a?(::Tempfile)
573
+ io.close
574
+ end
575
+ end
576
+
577
+ should "save the files as the right formats and sizes" do
578
+ [[:large, 400, 61, "PNG"],
579
+ [:medium, 100, 15, "GIF"],
580
+ [:small, 32, 32, "JPEG"]].each do |style|
581
+ cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
582
+ out = `#{cmd}`
583
+ width, height, size, format = out.split(" ")
584
+ assert_equal style[1].to_s, width.to_s
585
+ assert_equal style[2].to_s, height.to_s
586
+ assert_equal style[3].to_s, format.to_s
587
+ end
588
+ end
589
+
590
+ should "still have its #file attribute not be nil" do
591
+ assert ! (file = @attachment.to_file).nil?
592
+ file.close
593
+ end
594
+
595
+ context "and deleted" do
596
+ setup do
597
+ @existing_names = @attachment.styles.keys.collect do |style|
598
+ @attachment.path(style)
599
+ end
600
+ @attachment.expects(:instance_write).with(:file_name, nil)
601
+ @attachment.expects(:instance_write).with(:content_type, nil)
602
+ @attachment.expects(:instance_write).with(:file_size, nil)
603
+ @attachment.expects(:instance_write).with(:updated_at, nil)
604
+ @attachment.assign nil
605
+ @attachment.save
606
+ end
607
+
608
+ should "delete the files" do
609
+ @existing_names.each{|f| assert ! File.exists?(f) }
610
+ end
611
+ end
612
+ end
613
+ end
614
+ end
615
+
616
+ end
617
+
618
+ context "when trying a nonexistant storage type" do
619
+ setup do
620
+ rebuild_model :storage => :not_here
621
+ end
622
+
623
+ should "not be able to find the module" do
624
+ assert_raise(NameError){ Dummy.new.avatar }
625
+ end
626
+ end
627
+ end
628
+
629
+ context "An attachment with only a avatar_file_name column" do
630
+ setup do
631
+ ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
632
+ table.column :avatar_file_name, :string
633
+ end
634
+ rebuild_class
635
+ @dummy = Dummy.new
636
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
637
+ end
638
+
639
+ teardown { @file.close }
640
+
641
+ should "not error when assigned an attachment" do
642
+ assert_nothing_raised { @dummy.avatar = @file }
643
+ end
644
+
645
+ should "return the time when sent #avatar_updated_at" do
646
+ now = Time.now
647
+ Time.stubs(:now).returns(now)
648
+ @dummy.avatar = @file
649
+ assert now, @dummy.avatar.updated_at
650
+ end
651
+
652
+ should "return nil when reloaded and sent #avatar_updated_at" do
653
+ @dummy.save
654
+ @dummy.reload
655
+ assert_nil @dummy.avatar.updated_at
656
+ end
657
+
658
+ should "return the right value when sent #avatar_file_size" do
659
+ @dummy.avatar = @file
660
+ assert_equal @file.size, @dummy.avatar.size
661
+ end
662
+
663
+ context "and avatar_updated_at column" do
664
+ setup do
665
+ ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
666
+ rebuild_class
667
+ @dummy = Dummy.new
668
+ end
669
+
670
+ should "not error when assigned an attachment" do
671
+ assert_nothing_raised { @dummy.avatar = @file }
672
+ end
673
+
674
+ should "return the right value when sent #avatar_updated_at" do
675
+ now = Time.now
676
+ Time.stubs(:now).returns(now)
677
+ @dummy.avatar = @file
678
+ assert_equal now.to_i, @dummy.avatar.updated_at
679
+ end
680
+ end
681
+
682
+ context "and avatar_content_type column" do
683
+ setup do
684
+ ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
685
+ rebuild_class
686
+ @dummy = Dummy.new
687
+ end
688
+
689
+ should "not error when assigned an attachment" do
690
+ assert_nothing_raised { @dummy.avatar = @file }
691
+ end
692
+
693
+ should "return the right value when sent #avatar_content_type" do
694
+ @dummy.avatar = @file
695
+ assert_equal "image/png", @dummy.avatar.content_type
696
+ end
697
+ end
698
+
699
+ context "and avatar_file_size column" do
700
+ setup do
701
+ ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
702
+ rebuild_class
703
+ @dummy = Dummy.new
704
+ end
705
+
706
+ should "not error when assigned an attachment" do
707
+ assert_nothing_raised { @dummy.avatar = @file }
708
+ end
709
+
710
+ should "return the right value when sent #avatar_file_size" do
711
+ @dummy.avatar = @file
712
+ assert_equal @file.size, @dummy.avatar.size
713
+ end
714
+
715
+ should "return the right value when saved, reloaded, and sent #avatar_file_size" do
716
+ @dummy.avatar = @file
717
+ @dummy.save
718
+ @dummy = Dummy.find(@dummy.id)
719
+ assert_equal @file.size, @dummy.avatar.size
720
+ end
721
+ end
722
+ end
723
+ end