demarches-normaliennes/spec/controllers/concerns/lockable_concern_spec.rb

46 lines
1.3 KiB
Ruby

describe LockableConcern, type: :controller do
controller(ApplicationController) do
include LockableConcern
def test_action
lock_action(params.fetch(:lock_key)) do
render plain: 'Action completed'
end
end
end
before do
routes.draw { get 'test_action/:lock_key' => 'anonymous#test_action' }
end
describe '#lock_action' do
# randomize key to avoid collision on concurrent tests
let(:lock_key) { "test_lock_#{SecureRandom.uuid}" }
subject { get :test_action, params: { lock_key: } }
context 'when there is no concurrent request' do
it 'completes the action' do
expect(subject).to have_http_status(:ok)
end
end
context 'when there are concurrent requests' do
it 'aborts the second request' do
# Simulating the first request acquiring the lock
Kredis.flag(lock_key, config: :volatile).mark(expires_in: 3.seconds)
# Making the second request
expect(subject).to have_http_status(:locked)
end
end
context 'when the lock expires' do
it 'allows another request after expiration' do
Kredis.flag(lock_key, config: :volatile).mark(expires_in: 0.001.seconds)
sleep 0.002
expect(subject).to have_http_status(:ok)
end
end
end
end