I'm writing an API-Only Rails App (rails 5.2) and I need to make use of ActiveStorage. I want to write an RSpec Request Spec to ensure that file uploads work properly, but that's proving very difficult. Here's my spec so far:
RSpec.describe 'POST /profile/photos', type: :request do
let(:url) { '/profile/photos' }
let(:file) { fixture_file_upload('photo.jpg') }
before do
log_user_in
## Do a file upload ##
post '/rails/active_storage/direct_uploads', params: {
blob: {
filename: "woman.jpg",
content_type: "image/jpeg",
byte_size: File.size(file.path),
checksum: Digest::MD5.base64digest(File.read(file.path))
}
}
post url, params: {signed_id: json["signed_id"]}
end
it "Performs an upload" do
# Never gets here, error instead
end
end
I've tried using the put
helper to upload the file between the first and second post
call in the before
step, but I keep running into 422 unprocessable entity errors, likely because the put
helper doesn't support setting the raw request body. But I'm not entirely sure what the format of that put should be, or if there's a better way to test this.
I've tried using fixture_file_upload
, as described in this question:
put json["direct_upload"]["url"], params: {file: fixture_file_upload('photo.jpg')}
But that request returns 422 like all of my other attempts. I think the direct_upload URL really wants the body of the request to contain the file and nothing else.
I suspect there's a lot wrong with my approach here, but the Rails docs are somewhat sparse on how to use ActiveStorage if you're not using the out-of-the-box javascript to hide most of the interactions.
You probably don't care about testing the Active Storage engine so you don't need to post '/rails/active_storage/direct_uploads'
, you just need a valid signature.
I ended up creating an ActiveStorage::Blob
by hand and then I can ask it for the signature. Something like this off in a helper:
def blob_for(name)
ActiveStorage::Blob.create_after_upload!(
io: File.open(Rails.root.join(file_fixture(name)), 'rb'),
filename: name,
content_type: 'image/jpeg' # Or figure it out from `name` if you have non-JPEGs
)
end
and then in your specs you can say:
post url, params: { signed_id: blob_for('photo.jpg').signed_id }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With