require 'test/unit'
# Add the methods +upload+, the setup_file_fixtures and
# teardown_file_fixtures to the class Test::Unit::TestCase.
class Test::Unit::TestCase
# Returns a +Tempfile+ object as it would have been generated on file upload.
# Use this method to create the parameters when emulating form posts with
# file fields.
#
# === Example:
#
# def test_file_column_post
# entry = { :title => 'foo', :file => upload('/tmp/foo.txt')}
# post :upload, :entry => entry
#
# # ...
# end
#
# === Parameters
#
# * path The path to the file to upload.
# * content_type The MIME type of the file. If it is :guess,
# the method will try to guess it.
def upload(path, content_type=:guess, type=:tempfile)
if content_type == :guess
case path
when /\.jpg$/ then content_type = "image/jpeg"
when /\.png$/ then content_type = "image/png"
else content_type = nil
end
end
uploaded_file(path, content_type, File.basename(path), type)
end
# Copies the fixture files from "RAILS_ROOT/test/fixtures/file_column" into
# the temporary storage directory used for testing
# ("RAILS_ROOT/test/tmp/file_column"). Call this method in your
# setup methods to get the file fixtures (images, for example) into
# the directory used by file_column in testing.
#
# Note that the files and directories in the "fixtures/file_column" directory
# must have the same structure as you would expect in your "/public" directory
# after uploading with FileColumn.
#
# For example, the directory structure could look like this:
#
# test/fixtures/file_column/
# `-- container
# |-- first_image
# | |-- 1
# | | `-- image1.jpg
# | `-- tmp
# `-- second_image
# |-- 1
# | `-- image2.jpg
# `-- tmp
#
# Your fixture file for this one "container" class fixture could look like this:
#
# first:
# id: 1
# first_image: image1.jpg
# second_image: image1.jpg
#
# A usage example:
#
# def setup
# setup_fixture_files
#
# # ...
# end
def setup_fixture_files
tmp_path = File.join(RAILS_ROOT, "test", "tmp", "file_column")
file_fixtures = Dir.glob File.join(RAILS_ROOT, "test", "fixtures", "file_column", "*")
FileUtils.mkdir_p tmp_path unless File.exists?(tmp_path)
FileUtils.cp_r file_fixtures, tmp_path
end
# Removes the directory "RAILS_ROOT/test/tmp/file_column/" so the files
# copied on test startup are removed. Call this in your unit test's +teardown+
# method.
#
# A usage example:
#
# def teardown
# teardown_fixture_files
#
# # ...
# end
def teardown_fixture_files
FileUtils.rm_rf File.join(RAILS_ROOT, "test", "tmp", "file_column")
end
private
def uploaded_file(path, content_type, filename, type=:tempfile) # :nodoc:
if type == :tempfile
t = Tempfile.new(File.basename(filename))
FileUtils.copy_file(path, t.path)
else
if path
t = StringIO.new(IO.read(path))
else
t = StringIO.new
end
end
(class << t; self; end).class_eval do
alias local_path path if type == :tempfile
define_method(:local_path) { "" } if type == :stringio
define_method(:original_filename) {filename}
define_method(:content_type) {content_type}
end
return t
end
end
# If we are running in the "test" environment, we overwrite the default
# settings for FileColumn so that files are not uploaded into "/public/"
# in tests but rather into the directory "/test/tmp/file_column".
if RAILS_ENV == "test"
FileColumn::ClassMethods::DEFAULT_OPTIONS[:root_path] =
File.join(RAILS_ROOT, "test", "tmp", "file_column")
end