Testeando subida de archivos (file uploads) con Cucumber, Rspec y Paperclip +
Por Boris Barroso
Ultimamente estoy realizando una aplicación que requiere subir archivos Excel, fue un poco difícil encontrar la forma de que pasaran mis tests con Paperclip, pero hay que reconocer que esta gema hace magia con los uploads, el problema que tenía era con los uploads y el content_type, mi modelo realiza la validación del tipo de contenido usando las validaciones que provee paperclip, el modelo luce de esta forma:
class Archivo < ActiveRecord::Base
before_create :adicionar_usuario
belongs_to :usuario
has_many :hojas
validates_associated :usuario
validates_presence_of :nombre
validates_format_of :archivo_excel_file_name, :with => /\A^.+\.xls$\Z/i, :message => 'Solo se permite archivos excel ".xls"'
attr_accessible :archivo_excel, :nombre, :descripcion
has_attached_file :archivo_excel, :path => "archivos/:id/:basename.xls"
# Validacion de tipos de contenido para excel
validates_attachment_content_type :archivo_excel, :content_type => ['application/vnd.ms-excel'],
:message => ‘Solo se permite archivos Excel’
#’application/x-msexcel’,'application/ms-excel’, ‘application/msexcel’, ‘application/x-excel’
validates_attachment_presence :archivo_excel, :message => “Debe ingresar un archivo excel”
protected
def adicionar_usuario
self.usuario = UsuarioSession.find.record
end
end
Además estoy usando Authlogic para hacer la autenticación, junto con shoulda. El test del modelo es de la siguiente forma:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe Archivo do
it{should belong_to(:usuario)}
it{should validate_presence_of(:nombre)}
before(:each) do
archivo = File.join(RAILS_ROOT, 'ejemplos/VentasPrecio2000-2008.xls')
up = ActionController::UploadedStringIO.new
up.original_path = archivo
up.content_type = 'application/vnd.ms-excel'
@archivo_params = {
:nombre => 'Excel',
:archivo_excel => up
}
@usuario_mock = mock_model(Usuario, :id => 1, :nombre => 'Juan')
Usuario.stub!(:find).with(kind_of(Fixnum)).and_return(@usuario_mock)
@us = mock("record", :record => @usuario_mock)
UsuarioSession.stub!(:find).and_return(@us)
end
def create_archivo
@archivo = Archivo.create(@archivo_params)
end
it "debe crear" do
a = Archivo.create!(@archivo_params)
end
it "debe guardar el usuario" do
create_archivo()
@archivo.usuario.id.should == 1
end
end
Lo importante aquí está en cuando defino el before(:each) del test rspec, en el cual creo un mock ActionController::UploadedStringIO.new, despues defino la ruta y el tipo de content_type para el archivo que hago upload. Esta es la clave para poder hacer el subida del archivo y de que pase el test.
El problema para testear con Cucumber era mucho mas simple pero me llevo algún tiempo darme cuenta de ello (mi amigo Felix Carreño lo hizo), lo que sucedía era que Webrat tiene un comando para poder subir archivos en el cual solo se pasa el archivo que se desea subir y este asigna al file_field que uno define en el formulario, pero además uno debe indicar el tipo de conten_type, para que el test funcione y pase la validación de contenido de paperclip, osea solo es necesario hacerlo de esta forma:
#Archivo que uso para mi test archivo = File.join(RAILS_ROOT, "ejemplos/VentasPrecio2000-2008.xls") attach_file "archivo[archivo_excel]“, archivo, ‘application/vnd.ms-excel’
Hey Boris, parece que sin querer estamos trabajando en equipo =D Te dejo un link a mi tutorial sobre cómo instalar y configurar Paperclip: http://viarails.wordpress.com/2009/11/29/como-adjuntar-archivos-a-un-modelo-en-rails/
En la parte del before(:each) en ves de usar la clase ActionController::UploadedStringIO
se puede usar:
up = ActionController::TestUploadedFile(’ejemplos/VentdasPrecio2000-2008.xls’, ‘application/vnd.ms-excel’)