Attaching files to a field that is handled by Carrierwave uploaders (or maybe any other attachment solution for Rails) in tests allows different approaches. Here is a short summary of the most common methods.
You might also be interested in this card if you see the following error in your test environment:
CarrierWave::FormNotMultipart:
You tried to assign a String or a Pathname to an uploader, for security reasons, this is not allowed.
If this is a file upload, please check that your upload form is multipart encoded.
Factory Bot
FactoryBot.define do
factory :user do
name { 'Bruce' }
email { 'bruce@wayne.us' }
avatar { Rack::Test::UploadedFile.new('spec/fixtures/files/avatar.jpg') }
end
end
Note that if the avatar is an optional field, you want to move the file assignment to an optional trait.
FactoryBot.define do
factory :user do
name { 'Bruce' }
email { 'bruce@wayne.us' }
trait :with_avatar do
avatar { Rack::Test::UploadedFile.new('spec/fixtures/avatar.jpg') }
end
end
end
Storing a file attribute takes a few milliseconds, as CarrierWave needs to write out a file, compute versions, etc. You are going to create a lot of users in your E2E tests, and you won't need avatars for all of them:
RSpec
RSpec has a helper method
file_fixture
Show archive.org snapshot
:
describe User do
let(:user) { build(:user, attachment: file_fixture('avatar.jpg').open) }
end
You can configure the directory where RSpec looks for fixture files:
RSpec.configure do |config|
config.file_fixture_path = "spec/custom_directory"
end
Alternatives:
Rails.root.join('spec/fixtures/files/avatar.jpg').open('r')
Rails.root.join('spec/fixtures/files/avatar.jpg').read
-
File.open('spec/fixtures/files/avatar.jpg')
(might only work if you run the command from the Rails root directory)
Cucumber
When('I attach the file {string} to {string}') do |path, field|
attach_file(field, Rails.root.join('spec', 'fixtures', path))
end
Alternatives
- Spreewald Step with relative path Show archive.org snapshot