如何在 RSpec 请求规范中模拟 ActiveStorage 上传
How to Simulate ActiveStorage Uploads in RSpec Request Specs
我正在编写一个 API-Only Rails 应用程序 (rails 5.2),我需要使用 ActiveStorage。我想写一个 RSpec 请求规范来确保文件上传正常工作,但事实证明这非常困难。到目前为止,这是我的规格:
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
我尝试使用 put
帮助程序在 before
步骤中的第一个和第二个 post
调用之间上传文件,但我将 运行 保存到422 无法处理的实体错误,可能是因为 put
助手不支持设置原始请求正文。但我不完全确定 put 的格式应该是什么,或者是否有更好的方法来测试它。
我试过使用 fixture_file_upload
,如 this question:
中所述
put json["direct_upload"]["url"], params: {file: fixture_file_upload('photo.jpg')}
但是那个请求 returns 422 就像我所有的其他尝试一样。我认为 direct_upload URL 真的希望请求的主体只包含文件而不是其他内容。
我怀疑我这里的方法有很多错误,但是 Rails 文档中关于如何使用 ActiveStorage 的内容有些稀疏,如果你没有使用开箱即用的话 javascript 隐藏大部分交互。
您可能不关心测试 Active Storage 引擎,因此您不需要 post '/rails/active_storage/direct_uploads'
,您只需要一个有效的签名。
我最终手动创建了一个 ActiveStorage::Blob
,然后我可以要求它签名。在帮助程序中关闭这样的东西:
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
然后在你的规格中你可以说:
post url, params: { signed_id: blob_for('photo.jpg').signed_id }
我正在编写一个 API-Only Rails 应用程序 (rails 5.2),我需要使用 ActiveStorage。我想写一个 RSpec 请求规范来确保文件上传正常工作,但事实证明这非常困难。到目前为止,这是我的规格:
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
我尝试使用 put
帮助程序在 before
步骤中的第一个和第二个 post
调用之间上传文件,但我将 运行 保存到422 无法处理的实体错误,可能是因为 put
助手不支持设置原始请求正文。但我不完全确定 put 的格式应该是什么,或者是否有更好的方法来测试它。
我试过使用 fixture_file_upload
,如 this question:
put json["direct_upload"]["url"], params: {file: fixture_file_upload('photo.jpg')}
但是那个请求 returns 422 就像我所有的其他尝试一样。我认为 direct_upload URL 真的希望请求的主体只包含文件而不是其他内容。
我怀疑我这里的方法有很多错误,但是 Rails 文档中关于如何使用 ActiveStorage 的内容有些稀疏,如果你没有使用开箱即用的话 javascript 隐藏大部分交互。
您可能不关心测试 Active Storage 引擎,因此您不需要 post '/rails/active_storage/direct_uploads'
,您只需要一个有效的签名。
我最终手动创建了一个 ActiveStorage::Blob
,然后我可以要求它签名。在帮助程序中关闭这样的东西:
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
然后在你的规格中你可以说:
post url, params: { signed_id: blob_for('photo.jpg').signed_id }