* Add correct rate limit exception to Articles::Updater * Send Retry-After with HTTP 429 back to the client * Update API specs for error 429 * Test build * Fix spec * Add retry after to ImageUploadsController and fix specs * Generalize a bit
124 lines
4.4 KiB
Ruby
124 lines
4.4 KiB
Ruby
require "rails_helper"
|
|
|
|
RSpec.describe "ImageUploads", type: :request do
|
|
describe "POST/image_uploads" do
|
|
let(:user) { create(:user) }
|
|
let(:headers) { { "Content-Type": "application/json", Accept: "application/json" } }
|
|
let(:image) do
|
|
Rack::Test::UploadedFile.new(
|
|
Rails.root.join("spec/support/fixtures/images/image1.jpeg"),
|
|
"image/jpeg",
|
|
)
|
|
end
|
|
let(:bad_image) do
|
|
Rack::Test::UploadedFile.new(
|
|
Rails.root.join("spec/support/fixtures/images/bad-image.jpg"),
|
|
"image/jpeg",
|
|
)
|
|
end
|
|
|
|
context "when not logged-in" do
|
|
it "responds with 401" do
|
|
post "/image_uploads", headers: headers
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
end
|
|
|
|
context "when logged-in" do
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
it "returns json" do
|
|
post "/image_uploads", headers: headers
|
|
expect(response.content_type).to eq("application/json")
|
|
end
|
|
|
|
it "provides a link" do
|
|
# this test is a little flimsy
|
|
post "/image_uploads", headers: headers, params: { image: [image] }
|
|
expect(response.parsed_body["links"].length).to eq(1)
|
|
expect(response.body).to match("\/i\/.+\.")
|
|
end
|
|
|
|
it "supports for uploading a single image not in an array" do
|
|
post "/image_uploads", headers: headers, params: { image: image }
|
|
expect(response.parsed_body["links"].length).to eq(1)
|
|
expect(response.body).to match("\/i\/.+\.")
|
|
end
|
|
|
|
it "supports upload of more than one image at a time" do
|
|
image2 = Rack::Test::UploadedFile.new(
|
|
Rails.root.join("spec/support/fixtures/images/image2.jpeg"), "image/jpeg"
|
|
)
|
|
post "/image_uploads", headers: headers, params: { image: [image, image2] }
|
|
|
|
expect(response.body).to match("\/i\/.+\.")
|
|
expect(response.parsed_body["links"].length).to eq(2)
|
|
end
|
|
|
|
it "prevents image with resolutions larger than 4096x4096" do
|
|
post "/image_uploads", headers: headers, params: { image: [bad_image] }
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
|
|
it "returns a JSON error if something goes wrong" do
|
|
post "/image_uploads", headers: headers, params: { image: [bad_image] }
|
|
expect(response.parsed_body["error"]).not_to be_nil
|
|
end
|
|
|
|
it "catches error if image file name is too long" do
|
|
article_image_uploader = instance_double(ArticleImageUploader)
|
|
allow(ArticleImageUploader).to receive(:new).and_return(article_image_uploader)
|
|
allow(article_image_uploader).to receive(:store!).and_raise(Errno::ENAMETOOLONG)
|
|
allow(DatadogStatsClient).to receive(:increment)
|
|
|
|
expect do
|
|
post "/image_uploads", headers: headers, params: { image: [bad_image] }
|
|
end.to raise_error(Errno::ENAMETOOLONG)
|
|
|
|
tags = hash_including(tags: instance_of(Array))
|
|
|
|
expect(DatadogStatsClient).to have_received(:increment).with("image_upload_error", tags)
|
|
end
|
|
|
|
it "returns error if image file name is too long" do
|
|
allow(image).to receive(:original_filename).and_return("#{'a_very_long_filename' * 15}.png")
|
|
post "/image_uploads", headers: headers, params: { image: image }
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
context "when uploading rate limiting works" do
|
|
let(:cache_store) { ActiveSupport::Cache.lookup_store(:redis_cache_store) }
|
|
let(:cache) { Rails.cache }
|
|
let(:cache_key) { "#{user.id}_image_upload" }
|
|
|
|
before do
|
|
sign_in user
|
|
allow(Rails).to receive(:cache).and_return(cache_store)
|
|
end
|
|
|
|
it "counts number of uploads in cache" do
|
|
post "/image_uploads", headers: headers, params: { image: [image] }
|
|
expect(cache.read(cache_key).to_i).to eq(1)
|
|
end
|
|
|
|
it "responds with HTTP 429 with too many uploads" do
|
|
upload = proc do
|
|
Rack::Test::UploadedFile.new(
|
|
Rails.root.join("spec/support/fixtures/images/image1.jpeg"),
|
|
"image/jpeg",
|
|
)
|
|
end
|
|
|
|
11.times { post "/image_uploads", headers: headers, params: { image: [upload.call] } }
|
|
|
|
expect(response).to have_http_status(:too_many_requests)
|
|
|
|
expected_retry_after = RateLimitChecker::RETRY_AFTER[:image_upload]
|
|
expect(response.headers["Retry-After"]).to eq(expected_retry_after)
|
|
end
|
|
end
|
|
end
|
|
end
|