Ruby-on-rails – Testing Carrierwave file uploads to s3 with Capybara and Rspec

amazon s3capybaracarrierwaverspecruby-on-rails

I've implemented carrierwave file uploads to Amazon s3 just like in this Railscast.

I'm having trouble testing this though. I can attach a file with Capybara, but when I click the button to upload it doesn't redirect to the correct action. I checked with save_and_open_page and it's displaying the the homepage instead.

When I test it in the browser it works fine, but the info about the s3 upload does get added to the url (screenshot). Not sure why this wouldn't work in the test.

Here are some relevant files:

example_spec.rb – https://gist.github.com/leemcalilly/1e159f1b93005b8113f2

initializers/carrierwave.rb – https://gist.github.com/leemcalilly/924e8755f7c76ecbf5cf

models/work.rb – https://gist.github.com/leemcalilly/cfda1a7f15d87dbab731

controllers/works_controller.rb – https://gist.github.com/leemcalilly/7fca5f2c81c6cb4de6bc

How can I test this type of form with capybara and rspec?

Best Answer

Ok, I've figured this out. The key is CarrierWaveDirect:

https://github.com/dwilkie/carrierwave_direct#using-capybara

I needed to add this line to my spec_helper.rb:

include CarrierWaveDirect::Test::CapybaraHelpers

Then my tests needed these CarrierWaveDirect matchers:

attach_file_for_direct_upload("#{Rails.root}/spec/support/images/example.jpg") upload_directly(ImageUploader.new, "Upload Image")

So the final passing test looks like this:

it "creates a new work with a test image" do
    client = FactoryGirl.create(:client)
    work = FactoryGirl.build(:work)
    visit works_path
    attach_file_for_direct_upload("#{Rails.root}/spec/support/images/example.jpg")
    upload_directly(ImageUploader.new, "Upload Image")
    fill_in "Name", :with => work.name
    select("2012", :from => "work_date_1i")
    select("December", :from => "work_date_2i")
    select("25", :from => "work_date_3i")
    select(client.name, :from => "work_client_ids")
    fill_in "Description", :with => work.description
    fill_in "Service", :with => work.service
    save_and_open_page
    check "Featured"
    click_button "Create Work"
    page.should have_content("Work was successfully created.")
end

I also needed to add this to my initializers/carrierwave.rb:

if Rails.env.test?
    CarrierWave.configure do |config|
      config.storage = :file
      config.enable_processing = false
    end
end

Rather than mock the response to fog, or test an upload to s3, I just switched off uploads to s3 in the test environment.