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