require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') module ImportableAttachments describe AttachmentsController do # :call-seq: # set_request_environment [:options] # # sets request headers e.g. X-File-Nmae, content_type, RAW_POST_DATA def set_request_environment(opts = {}) lopts = request_environment_opts opts req_env = request.env req_env['X-Requested-With'] = 'XMLHttpRequest' if lopts[:xml] req_env['content_type'] = lopts[:content_type] req_env['X-File-Name'] = File.basename lopts[:spec_file] req_env['RAW_POST_DATA'] = File.new(lopts[:spec_file], 'rb') end # :call-seq: # request_environment_opts [:options] # # sets request headers e.g. X-File-Nmae, content_type, RAW_POST_DATA def request_environment_opts(opts = {}) lopts = {spec_file: @path_to_spec_file, xml: false, content_type: 'application/excel'} lopts.merge opts end # :call-seq: # mock_attachment [:opts] # # yields a mock ImportableAttachments::Attachment object def mock_attachment(opts = {}) lopts = {id: 27, io_stream: nil, io_stream_file_name: 'zero_length.csv', io_stream_content_type: 'Test Content Type', io_stream_file_size: 1, io_stream_updated_at: DateTime.now, revision_number: 1, attachable_type: nil, attachable_id: nil, version: 1} @attachment = mock_model(ImportableAttachments::Attachment, lopts.merge(opts)) @attachment.stubs(:io_stream).returns(mock_io_stream(attach_to: @attachment)) # In the all_controllers_spec case, the file must be copied stream_path = @attachment.io_stream.path.to_s if @spec_file.path != stream_path FileUtils.cp @spec_file, stream_path end @attachment end # :call-seq: # mock_io_stream [:opts] # # yields a mock Paperclip::Attachment object def mock_io_stream(opts = {}) @io_stream = Paperclip::Attachment.new(:io_stream, @attachment, {path: ':rails_root/public/:rails_env/:style/:attachable_klass/:id_partition/:basename.:stream_version.:extension', preserve_files: true, processors: [:save_upload]}) spec_dir = File.dirname(@io_stream.path).sub(/(?:\/\.?)?$/, "") FileUtils.mkdir_p spec_dir unless File.directory? spec_dir @io_stream.stubs(:path).returns(@path_to_spec_file) @io_stream end before :each do @path_to_spec_file = Rails.root.join('spec', 'attachments', 'mostly_empty_copy.xls').to_s @spec_file = File.new(@path_to_spec_file, 'rb') @spec_file.stubs(:original_filename).returns(File.basename(@path_to_spec_file)) @uploaded_file = fixture_file_upload @path_to_spec_file, 'application/excel' mock_attachment end # TODO: restore @path_to_spec_file via Git... to be anal after :each do end context 'GET index' do it 'assigns all associated attachments as @attachments' do attachments = [@attachment] ImportableAttachments::Attachment.stubs(:order).with(:io_stream_updated_at).returns(attachments) get :index assigns(:attachments).should eq(attachments) end end context 'GET show' do it 'should respond with status 200' do ImportableAttachments::Attachment.stubs(:find).with(@attachment.id.to_s).returns(@attachment) path_to = Rails.root.join('spec', 'attachments', @attachment.io_stream_file_name).to_s @io_stream.stubs(:path).returns(path_to) #@attachment.stubs(:io_stream).returns(@io_stream) get :show, id: @attachment.id.to_s response.status.should be 200 end it 'assigns the requested attachment as @attachment' do ImportableAttachments::Attachment.stubs(:find).with(@attachment.id.to_s).returns(@attachment) get :show, id: @attachment.id.to_s assigns(:attachment).should eq(@attachment) end end context 'GET download' do it 'should send the requested attachment as a file' do set_request_environment spec_file: @path_to_spec_file ImportableAttachments::Attachment.stubs(:find).with(@attachment.id.to_s).returns(@attachment) @attachment.stubs(:io_stream_file_name).returns(File.basename(@path_to_spec_file)) get :download, id: @attachment.id.to_s response.headers['Content-Disposition'].should == "attachment; filename=\"mostly_empty_copy.xls\"" end end context 'GET new' do it 'assigns a new attachment as @attachment' do get :new assigns(:attachment).should be_a_new(ImportableAttachments::Attachment) end end context 'GET edit' do it 'assigns the requested attachment as @attachment' do ImportableAttachments::Attachment.stubs(:find).with(@attachment.id.to_s).returns(@attachment) get :edit, id: @attachment.id.to_s assigns(:attachment).should eq(@attachment) end end context 'POST create' do context 'with valid params' do it 'creates a new ImportableAttachments::Attachment' do set_request_environment expect { post :create, attachment: {io_stream: @uploaded_file} }.to change(ImportableAttachments::Attachment, :count).by(1) end it 'assigns a newly created attachment as @attachment' do set_request_environment post :create, attachment: {io_stream: @uploaded_file} assigns(:attachment).should be_a(ImportableAttachments::Attachment) assigns(:attachment).should be_persisted end it 'should capture the original filename' do set_request_environment post :create, attachment: {io_stream: @uploaded_file} assigns(:attachment).io_stream_file_name.should == request.env['X-File-Name'] end it 'should save the file to disk' do set_request_environment post :create, attachment: {io_stream: @uploaded_file} path = assigns(:attachment).io_stream.path path.should_not be_blank File.exist?(path).should == true end end context 'with invalid params' do it 'assigns a newly created but unsaved attachment as @attachment' do set_request_environment ImportableAttachments::Attachment.any_instance.expects(:save).returns(false) lambda { post :create, attachment: {io_stream: nil} }.should_not change(@attachment, :io_stream) end end end context 'PUT update' do context 'with valid params' do before :each do @path_to_spec_file = Rails.root.join('spec', 'attachments', 'mostly_empty.csv').to_s end it 'updates the requested attachment' do set_request_environment attachment = ImportableAttachments::Attachment.create! io_stream: fixture_file_upload(@path_to_spec_file, 'text/csv') ImportableAttachments::Attachment.stubs(:find).with(attachment.id.to_s).returns(attachment) put :update, id: attachment.id.to_s, attachment: {io_stream: @uploaded_file} assigns(:attachment).io_stream_file_name.should == @uploaded_file.original_filename end it 'assigns the requested attachment as @attachment' do set_request_environment ImportableAttachments::Attachment.stubs(:find).with(@attachment.id.to_s).returns(@attachment) @attachment.stubs(:update_attributes).with('io_stream' => @uploaded_file).returns(@attachment) put :update, id: @attachment.id.to_s, attachment: {io_stream: @uploaded_file} assigns(:attachment).should eq(@attachment) end it 'should create a new version of the file' do set_request_environment attachment = ImportableAttachments::Attachment.create! io_stream: fixture_file_upload(@path_to_spec_file, 'teext/csv') ImportableAttachments::Attachment.stubs(:find).with(attachment.id.to_s).returns(attachment) first_path = attachment.io_stream.path put :update, id: attachment.id.to_s, attachment: {io_stream: @uploaded_file} second_path = assigns(:attachment).io_stream.path first_path.should_not == second_path end end context 'with invalid params' do it 'does not update the attachment if the file is not found' do set_request_environment attachment = ImportableAttachments::Attachment.create! io_stream: @uploaded_file ImportableAttachments::Attachment.stubs(:find).with(attachment.id.to_s).returns(attachment) attachment.stubs(:update_attributes).with('these' => 'params').returns(false) lambda { put :update, id: attachment.id.to_s, attachment: {'these' => 'params'} }.should_not change(attachment, :io_stream) end end end context 'DELETE destroy' do it 'destroys the requested attachment' do attachment = ImportableAttachments::Attachment.create! io_stream: @uploaded_file ImportableAttachments::Attachment.stubs(:find).with(attachment.id.to_s).returns(attachment) expect { delete :destroy, id: attachment.id.to_s }.to change(ImportableAttachments::Attachment, :count).by(-1) end end end end