Capybara FactoryGirl Carrierwave cannot attach file
Asked Answered
R

1

8

I am trying to test my application with cucumber and capybara. I have the following step definition:

Given(/^I fill in the create article form with the valid article data$/) do
  @article_attributes = FactoryGirl.build(:article)
  within("#new_article") do
    fill_in('article_title', with: @article_attributes.title)
    attach_file('article_image', @article_attributes.image)
    fill_in('article_description', with: @article_attributes.description)
    fill_in('article_key_words', with: @article_attributes.key_words)
    fill_in('article_body', with: @article_attributes.body)
  end

My article factory looks like this:

FactoryGirl.define do
  factory :article do
    sequence(:title) {|n| "Title #{n}"}
    description 'Description'
    key_words 'Key word'
    image { File.open(File.join(Rails.root, '/spec/support/example.jpg')) }
    body 'Lorem...'
    association :admin, strategy: :build
  end
end

And this is my uploader file:

# encoding: UTF-8
class ArticleImageUploader < CarrierWave::Uploader::Base
  storage :file
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
  def extension_white_list
    %w(jpg jpeg gif png)
  end
end

But each time i run this scenario i get ERROR message:

Given I fill in the create article form with the valid article data # features/step_definitions/blog_owner_creating_article.rb:1
      cannot attach file, /uploads/article/image/1/example.jpg does not exist (Capybara::FileNotFound)
      ./features/step_definitions/blog_owner_creating_article.rb:5:in `block (2 levels) in <top (required)>'
      ./features/step_definitions/blog_owner_creating_article.rb:3:in `/^I fill in the create article form with the valid article data$/'
      features/blog_owner_creating_article.feature:13:in `Given I fill in the create article form with the valid article data'

I also found that FactoryGirl returns image:nil when i run FactoryGirl.build(:article) in my rails test console.

Could anybody explain me what i am doing wrong,please?

Red answered 11/5, 2013 at 21:56 Comment(0)
S
13

You need to pass the path in directly:

attach_file('article_image', File.join(Rails.root, '/spec/support/example.jpg'))

What's happening here is that attach_file expects a string, not a CarrierWave uploader. When you pass it an uploader (@article_attributes.image), attach_file is calling Uploader#to_s, which calls Uploader#path. Since you haven't saved the article yet, the path at which the uploaded image will be located is invalid.

Note also that calling your variable @article_attributes is confusing, since it's actually a full article object, not just a hash. If that's what you want, you may want to try FactoryGirl.attributes_for(:article).

Skillet answered 12/5, 2013 at 16:49 Comment(3)
Thaks for answering! I'd tried to use @article_attributes = FactoryGirl.attributes_for(:article) as you said. But @article_attributes[:image] returns #<File:/home/olebi/Work/blog_engine/spec/support/example.jpg>. Is there any way to transform this into the direct string path?`Red
@article_attributes[:image].path? It'd be a crazy world if there was no way to get the path from a File object.Skillet
Just a little caveat, because it took me some time to figure out why my tests were failing: If your factory populates the upload with Rack::Test::UploadedFile, the path might not be what you expect. UploadedFile adds some kind of fingerprint to the filename, so 'dummy.jpg' becomes e. g. 'dummy.jpg20140221-25167-11iad2p' (probably because it stores all the files in /tmp). This might trip your extension white list and fail your tests. If this happens, it might be a better solution to call attach_file with the file path itself instead of the attribute that FactoryGirl produces.Declamation

© 2022 - 2024 — McMap. All rights reserved.