Files
paperclip/test/attachment_test.rb
2024-04-10 19:15:45 +03:00

505 lines
17 KiB
Ruby

require 'test_helper'
class Dummy # rubocop:disable Lint/EmptyClass
# This is a dummy class
end
class AttachmentTest < Test::Unit::TestCase
ATTACHMENT_OPTIONS_TO_VARIABLES_MAPPING = {
url: :url_template,
path: :path_template,
styles: :styles,
default_url: :default_url,
default_style: :default_style,
whiny: :whiny
}.freeze
should "return the path based on the url by default" do
@attachment = attachment :url => "/:class/:id/:basename"
@model = @attachment.instance
@model.id = 1234
@model.avatar_file_name = "fake.jpg"
assert_equal "#{Rails.root}/public/fake_models/1234/fake", @attachment.path
end
context "Attachment default_options" do
setup do
rebuild_model
@old_default_options = Paperclip::Attachment.default_options.dup
@new_default_options = @old_default_options.merge({
:path => "argle/bargle",
:url => "fooferon",
:default_url => "not here.png"
})
end
teardown do
Paperclip::Attachment.default_options.merge! @old_default_options
end
should "be overrideable" do
Paperclip::Attachment.default_options.merge!(@new_default_options)
@new_default_options.keys.each do |key|
assert_equal @new_default_options[key],
Paperclip::Attachment.default_options[key]
end
end
context "without an Attachment" do
setup do
@dummy = Dummy.new
end
should "return false when asked exists?" do
assert !@dummy.avatar.exists?
end
end
context "on an Attachment" do
setup do
@dummy = Dummy.new
@attachment = @dummy.avatar
end
ATTACHMENT_OPTIONS_TO_VARIABLES_MAPPING.each do |option, variable|
should "be the default_options for #{option}" do
assert_equal @old_default_options[option],
@attachment.class.instance_variable_get("@#{variable}")
end
end
context "when redefined" do
setup do
rebuild_class @new_default_options
@dummy = Dummy.new
@attachment = @dummy.avatar
end
ATTACHMENT_OPTIONS_TO_VARIABLES_MAPPING.each do |option, variable|
should "be the new default_options for #{option}" do
assert_equal @new_default_options[option],
@attachment.class.instance_variable_get("@#{variable}")
end
end
end
end
end
context "An attachment with similarly named interpolations" do
setup do
rebuild_model :path => ":id.omg/:id-bbq/:id/what/:id_partition.wtf"
@dummy = Dummy.new
@dummy.stubs(:id).returns(1024)
@file = File.new(File.join(File.dirname(__FILE__),
"fixtures",
"5k.png"), 'rb')
@dummy.avatar = @file
end
teardown { @file.close }
should "make sure that they are interpolated correctly" do
assert_equal "1024.omg/1024-bbq/1024/what/000/001/024.wtf", @dummy.avatar.path
end
end
context "An attachment with a :rails_env interpolation" do
setup do
@rails_env = "blah"
@id = 1024
rebuild_model :path => ":rails_env/:id.png"
@dummy = Dummy.new
@dummy.stubs(:id).returns(@id)
@file = StringIO.new(".")
@dummy.avatar = @file
Rails.stubs(:env).returns(@rails_env)
end
should "return the proper path" do
assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
end
end
context "An attachment with a default style and an extension interpolation" do
setup do
@attachment = attachment :path => ":basename.:extension",
:styles => { :default => ["100x100", :png] },
:default_style => :default
@attachment.post_processing = false
@file = StringIO.new("...")
@file.stubs(:original_filename).returns("file.jpg")
end
should "return the right extension for the path" do
@attachment.assign(@file)
assert_equal "file.png", @attachment.path
end
context "fast upload via nginx" do
should "return the right extension for the path" do
Tempfile.create do |tempfile|
content = "file contents"
tempfile.write(content)
upload = { 'original_name' => 'foo.jpg', 'content_type' => 'application/jpg', 'filepath' => tempfile.tap(&:rewind).path }
@attachment.assign(upload)
assert_equal "foo.png", @attachment.path
assert_equal content, @attachment.queued_for_write[:original].tap(&:rewind).read
end
end
end
end
context "An attachment with both 'normal' and hash-style styles" do
setup do
rebuild_model :styles => {
:normal => ["50x50#", :png],
:hash => { :geometry => "50x50#", :format => :png }
}
@dummy = Dummy.new
@attachment = @dummy.avatar
end
[:processors, :whiny, :convert_options, :geometry, :format].each do |field|
should "have the same #{field} field" do
assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
end
end
end
class Paperclip::Test < Paperclip::Processor; end
context "An attachment with multiple processors" do
setup do
@style_params = { :once => {:one => 1, :two => 2} }
rebuild_model :processors => [:thumbnail, :test], :styles => @style_params
@dummy = Dummy.new
@file = StringIO.new("...")
@file.stubs(:to_tempfile).returns(@file)
Paperclip::Test.stubs(:make).returns(@file)
Paperclip::Thumbnail.stubs(:make).returns(@file)
@dummy.avatar.stubs(:content_type).returns('image/wow')
end
context "when assigned" do
setup { @dummy.avatar = @file }
before_should "call #make on all specified processors" do
expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
end
before_should "call #make with attachment passed as third argument" do
expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
end
end
end
context "An attachment with no processors defined" do
setup do
rebuild_model :processors => [], :styles => {:something => 1}
@dummy = Dummy.new
@file = StringIO.new("...")
@dummy.avatar.stubs(:content_type).returns('image/wow')
end
should "raise when assigned to" do
assert_raises(RuntimeError){ @dummy.avatar = @file }
end
end
context "Assigning an attachment" do
setup do
rebuild_model :styles => { :something => "100x100#" }
@file = StringIO.new(".")
@file.expects(:original_filename).returns("5k.png\n\n")
@file.stubs(:content_type).returns("image/png\n\n")
@file.stubs(:to_tempfile).returns(@file)
@dummy = Dummy.new
Paperclip::Thumbnail.expects(:make).returns(@file)
@attachment = @dummy.avatar
@dummy.avatar = @file
@dummy.stubs(:content_type).returns('image/wow')
end
should "strip whitespace from original_filename field" do
assert_equal "5k.png", @dummy.avatar.original_filename
end
should "strip whitespace from content_type field" do
assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
end
end
context "An attachment" do
setup do
@old_defaults = Paperclip::Attachment.default_options.dup
Paperclip::Attachment.default_options.merge!({
:path => "./tmp/:attachment/:class/:style/:id/:basename.:extension"
})
FileUtils.rm_rf("tmp")
rebuild_model
@instance = Dummy.new
@attachment = Paperclip::Attachment.build_class(:avatar).new(@instance)
@file = File.new(File.join(File.dirname(__FILE__),
"fixtures",
"5k.png"), 'rb')
end
teardown do
@file&.close
Paperclip::Attachment.default_options.merge!(@old_defaults)
end
should "raise if there are not the correct columns when you try to assign" do
@other_attachment = Paperclip::Attachment.build_class(:not_here).new(@instance)
assert_raises(Paperclip::PaperclipError) do
@other_attachment.assign(@file)
end
end
should "return its default_url when no file assigned" do
assert @attachment.to_file.nil?
assert_equal "/avatars/original/missing.png", @attachment.url
assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
end
should "return nil as path when no file assigned" do
assert @attachment.to_file.nil?
assert_equal nil, @attachment.path
assert_equal nil, @attachment.path(:blah)
end
context "with a file assigned in the database" do
setup do
@attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
@attachment.stubs(:instance_read).with(:content_type).returns("image/png")
@attachment.stubs(:instance_read).with(:file_size).returns(12345)
now = Time.now
Time.stubs(:now).returns(now)
@attachment.stubs(:instance_read).with(:updated_at).returns(Time.now)
end
should "return a correct url even if the file does not exist" do
assert_nil @attachment.to_file
assert_match %r{^/system/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
end
should "make sure the updated_at mtime is in the url if it is defined" do
assert_match %r{#{Time.now.to_i}$}, @attachment.url(:blah)
end
should "make sure the updated_at mtime is NOT in the url if false is passed to the url method" do
assert_no_match %r{#{Time.now.to_i}$}, @attachment.url(:blah, false)
end
context "with the updated_at field removed" do
setup do
@attachment.stubs(:instance_read).with(:updated_at).returns(nil)
end
should "only return the url without the updated_at when sent #url" do
assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
end
end
should "return the proper path when filename has a single .'s" do
assert_equal "./tmp/avatars/dummies/original/#{@instance.id}/5k.png", @attachment.path
end
should "return the proper path when filename has multiple .'s" do
@attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
assert_equal "./tmp/avatars/dummies/original/#{@instance.id}/5k.old.png", @attachment.path
end
context "when expecting three styles" do
setup do
styles = {:styles => { :large => ["400x400", :png],
:medium => ["100x100", :gif],
:small => ["32x32#", :jpg]}}
@attachment = Paperclip::Attachment.build_class(:avatar, styles).new(@instance)
end
context "and assigned a file" do
setup do
now = Time.now
Time.stubs(:now).returns(now)
@attachment.assign(@file)
end
should "be dirty" do
assert @attachment.dirty?
end
context "and saved" do
setup do
@attachment.save
end
should "return the real url" do
file = @attachment.to_file
assert file
assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
file.close
end
should "commit the files to disk" do
[:large, :medium, :small].each do |style|
io = @attachment.to_io(style)
assert File.exist?(io)
assert ! io.is_a?(::Tempfile)
io.close
end
end
should "save the files as the right formats and sizes" do
[[:large, 400, 61, "PNG"],
[:medium, 100, 15, "GIF"],
[:small, 32, 32, "JPEG"]].each do |style|
cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
out = `#{cmd}`
width, height, _size, format = out.split(" ")
assert_equal style[1].to_s, width.to_s
assert_equal style[2].to_s, height.to_s
assert_equal style[3].to_s, format.to_s
end
end
should "still have its #file attribute not be nil" do
assert ! (file = @attachment.to_file).nil?
file.close
end
context "and trying to delete" do
setup do
@existing_names = @attachment.styles.keys.collect do |style|
@attachment.path(style)
end
end
should "delete the files after assigning nil" do
@attachment.assign nil
@attachment.save
@existing_names.each { |f| assert !File.exist?(f) }
end
should "delete the files when you call #clear and #save" do
@attachment.clear
@attachment.save
@existing_names.each { |f| assert !File.exist?(f) }
end
should "delete the files when you call #delete" do
@attachment.destroy
@existing_names.each { |f| assert !File.exist?(f) }
end
end
end
end
end
end
context "when trying a nonexistant storage type" do
should "not be able to find the module" do
assert_raise(NameError) { rebuild_model storage: :not_here }
end
end
end
context "An attachment with only a avatar_file_name column" do
setup do
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
table.column :avatar_file_name, :string
end
rebuild_class
@dummy = Dummy.new
@file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
end
teardown { @file.close }
should "not error when assigned an attachment" do
assert_nothing_raised { @dummy.avatar = @file }
end
should "return the time when sent #avatar_updated_at" do
now = Time.now
Time.stubs(:now).returns(now)
@dummy.avatar = @file
assert now.to_s, @dummy.avatar.updated_at.to_s
end
should "return nil when reloaded and sent #avatar_updated_at" do
@dummy.save
@dummy.reload
assert_nil @dummy.avatar.updated_at
end
should "return the right value when sent #avatar_file_size" do
@dummy.avatar = @file
assert_equal @file.size, @dummy.avatar.size
end
context "and avatar_updated_at column" do
setup do
ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
rebuild_class
@dummy = Dummy.new
end
should "not error when assigned an attachment" do
assert_nothing_raised { @dummy.avatar = @file }
end
should "return the right value when sent #avatar_updated_at" do
now = Time.now
Time.stubs(:now).returns(now)
@dummy.avatar = @file
assert_equal now.to_i, @dummy.avatar.updated_at
end
end
context "and avatar_content_type column" do
setup do
ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
rebuild_class
@dummy = Dummy.new
end
should "not error when assigned an attachment" do
assert_nothing_raised { @dummy.avatar = @file }
end
should "return the right value when sent #avatar_content_type" do
@dummy.avatar = @file
assert_equal "image/png", @dummy.avatar.content_type
end
end
context "and avatar_file_size column" do
setup do
ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
rebuild_class
@dummy = Dummy.new
end
should "not error when assigned an attachment" do
assert_nothing_raised { @dummy.avatar = @file }
end
should "return the right value when sent #avatar_file_size" do
@dummy.avatar = @file
assert_equal @file.size, @dummy.avatar.size
end
should "return the right value when saved, reloaded, and sent #avatar_file_size" do
@dummy.avatar = @file
@dummy.save
@dummy = Dummy.find(@dummy.id)
assert_equal @file.size, @dummy.avatar.size
end
end
end
end