Steps to to reproduce (using rails 4.2.5.1):
rails new fixture_file_upload
cd fixture_file_upload
echo "gem 'rspec-rails', '~> 3.0'" >> Gemfile
bundle
rails generate rspec:install
mkdir -p spec/fixtures/files
touch spec/fixtures/files/test.jpg
mkdir spec/requests
Create spec/requests/test_spec.rb with the following contents:
require 'rails_helper'
describe 'test', type: :request do
it 'tests' do
fixture_file_upload('test.jpg')
end
end
rake
Failures:
1) test tests
Failure/Error: fixture_file_upload('test.jpg')
RuntimeError:
test.jpg file does not exist
@mmb As per rails documentation http://api.rubyonrails.org/classes/ActionDispatch/TestProcess.html#method-i-fixture_file_upload I think you have to use fixture_file_upload('files/test.jpg', 'image/jpg'). If still didn't work then it could be an issue. Could you please check?
When I change that line in the reproduction steps above I get the same result:
Failures:
1) test tests
Failure/Error: fixture_file_upload('files/test.jpg', 'image/jpg')
RuntimeError:
files/test.jpg file does not exist
:+1: I'm also seeing this issue on Rails 3.2.13, rspec 2.14.8, rspec-rails 2.14.2. The issue is specific to request specs.
@mmb Can you tell me what your RSpec.configuration.fixture_path is?
@ngottlieb those versions of RSpec are extremely old and unsupported, please consider upgrading
@JonRowe we're actually upgrading this week, coincidentally. I was just trying to give another datapoint as it seems this problem may have been around for a long time. My fixture path is spec/fixtures and the method works in controller specs but fails in request specs.
When I run the example above in a fresh rails app in /private/tmp, RSpec.configuration.fixture_path is set to /private/tmp/fixture_file_upload/spec/fixtures.
whats the fixture_path value within the spec? (it { puts fixture_path }) as that's what needs to be picked up by Rails here
The fixture path within the spec is /private/tmp/fixture_file_upload/spec/fixtures. I re-ran it inside a docker container to make sure no configuration was influencing it and got the same result:
docker run -it ruby bash
apt-get update
apt-get install --assume-yes nodejs
gem install rails
rails new fixture_file_upload
cd fixture_file_upload
echo "gem 'rspec-rails', '~> 3.4', '>= 3.4.2'" >> Gemfile
bundle
rails generate rspec:install
mkdir -p spec/fixtures/files
touch spec/fixtures/files/test.jpg
mkdir spec/requests
cat > spec/requests/test_spec.rb << EOF
require 'rails_helper'
describe 'test', type: :request do
it 'tests' do
puts fixture_path
fixture_file_upload('test.jpg')
end
end
EOF
rake
/fixture_file_upload/spec/fixtures
F
Failures:
1) test tests
Failure/Error: fixture_file_upload('test.jpg')
RuntimeError:
test.jpg file does not exist
I'm actually having this exact error right now; my rails_helper.rb has in it:
config.fixture_path = "#{::Rails.root}/spec/fixtures"
however, within the request spec:
require "rails_helper"
RSpec.describe "doing something" do
before(:each) do
puts fixture_path
@valid_attribs = {
...
"picture" => fixture_file_upload("profile.jpg", "image/jpg")
...
}
end
end
nothing is output for the fixture path, just the errors for the contexts within the spec.
running:
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
Rails 5.0.0.rc1
and latest since I'm using rails 5, i'm using rspec 3.5.0.beta4
Same problem here. I found out the following while poking around:
#fixture_file_upload uses fixture_path only if self.class.respond_to?(:fixture_path) returns true (see https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/testing/test_process.rb#L38)p self.class, self.class.respond_to?(:fixture_path) to my example it prints RSpec::ExampleGroups::FoobarExample, true. So far, so good.#fixture_file_upload method it prints ActionDispatch::Integration::Session, false.So somehow the context inside fixture_file_upload seems to be wrong?
I get exactly the same symptoms with MiniTest. Are we 100% sure this is just an rspec-rails thing?
For what it's worth, in case this is blocking people, passing an absolute path does work:
fixture_file_upload("#{fixture_path}/files/image.jpg")
Seems like ActionDispatch::TestProcess doesn't have access to fixture_path so it won't be able to prepend it to the passed file path.
Also, it's probably obvious to everybody else, but you have to explicitly put it under the params key, you can't path it through the path (duh):
RSpec.describe 'POST /uploads' do
let(:file) { fixture_file_upload("#{fixture_path}/files/image.jpg") }
it 'works' do
post uploads_path,
params: { uploads: { file: file } }
end
it 'fails' do
post uploads_path(uploads: { file: file })
end
end
In my case,
When running a spec, fixtures_file_upload self.class is ActionDispatch::Integration::Session. which respond_to?(:fixture_path) is false But, if you include ActionDispatch::TestProcess in your spec, the same self.class is a RSpec::ExampleGroups which respond_to?(:fixture_path) is true.
In that case, this code should work:
include ActionDispatch::TestProcess
RSpec.describe 'POST /uploads' do
let(:file) { fixture_file_upload('files/image.jpg') }
it 'works' do
post uploads_path,
params: { uploads: { file: file } }
end
it 'fails' do
post uploads_path(uploads: { file: file })
end
end
The include ActionDispatch::TestProcess section works for me using Rails 5.0.0.1 and RSpec rails - 3.5.2.
Thanks!
Hey not sure this is related, but I am using fixture_file_upload with an absolute path (Using Rails.root.join(...) and with carrierwave I get the following
No such file or directory @ rb_sysopen - /var/folders/9r/5rbbwszx4fv5psztd460bpw80000gn/T/mini_magick20170803-18824-1aw8216.jpg
(The file exists and when I run the endpoint with postman it works 100%)
I submitted a PR about that https://github.com/rspec/rspec-rails/pull/1880
I did the same than @ericproulx and works!
can be closed
Look for Dir.chdir in your code:
Fixture uses relative paths, changing your current directory kills it.
Most helpful comment
The
include ActionDispatch::TestProcesssection works for me using Rails 5.0.0.1 and RSpec rails - 3.5.2.Thanks!