require 'spec_helper' RSpec.describe Shoryuken::Queue do let(:credentials) { Aws::Credentials.new('access_key_id', 'secret_access_key') } let(:sqs) { Aws::SQS::Client.new(stub_responses: true, credentials: credentials) } let(:queue_name) { 'shoryuken' } let(:queue_url) { "https://sqs.eu-west-1.amazonaws.com:6059/0123456789/#{queue_name}" } subject { described_class.new(sqs, queue_name) } before do # Required as Aws::SQS::Client.get_queue_url returns 'String' when responses are stubbed, # which is not accepted by Aws::SQS::Client.get_queue_attributes for :queue_name parameter. allow(subject).to receive(:url).and_return(queue_url) end describe '#new' do context 'when queue url supplied' do subject { described_class.new(sqs, queue_url) } specify do expect(subject.name).to eq(queue_name) end end end describe '#delete_messages' do let(:entries) do [ { id: '1', receipt_handle: '1' }, { id: '2', receipt_handle: '2' } ] end it 'deletes' do expect(sqs).to receive(:delete_message_batch).with(entries: entries, queue_url: queue_url).and_return(double(failed: [])) subject.delete_messages(entries: entries) end context 'when it fails' do it 'logs the reason' do failure = double(id: 'id', code: 'code', message: '...', sender_fault: false) logger = double 'Logger' expect(sqs).to receive(:delete_message_batch).with(entries: entries, queue_url: queue_url).and_return(double(failed: [failure])) expect(subject).to receive(:logger).and_return(logger) expect(logger).to receive(:error) subject.delete_messages(entries: entries) end end end describe '#send_message' do before { allow(subject).to receive(:fifo?).and_return(false) } it 'accepts SQS request parameters' do # https://docs.aws.amazon.com/sdkforruby/api/Aws/SQS/Client.html#send_message-instance_method expect(sqs).to receive(:send_message).with(hash_including(message_body: 'msg1')) subject.send_message(message_body: 'msg1') end it 'accepts a string' do expect(sqs).to receive(:send_message).with(hash_including(message_body: 'msg1')) subject.send_message('msg1') end context 'when a client middleware' do class MyClientMiddleware def call(options) options[:message_body] = 'changed' yield end end before do allow(Shoryuken).to receive(:server?).and_return(false) Shoryuken.configure_client do |config| config.client_middleware do |chain| chain.add MyClientMiddleware end end end after do Shoryuken.configure_client do |config| config.client_middleware do |chain| chain.remove MyClientMiddleware end end end it 'invokes MyClientMiddleware' do expect(sqs).to receive(:send_message).with(hash_including(message_body: 'changed')) subject.send_message(message_body: 'original') end end end describe '#send_messages' do before { allow(subject).to receive(:fifo?).and_return(false) } it 'accepts SQS request parameters' do # https://docs.aws.amazon.com/sdkforruby/api/Aws/SQS/Client.html#send_message_batch-instance_method expect(sqs).to receive(:send_message_batch).with(hash_including(entries: [{id: '0', message_body: 'msg1'}, {id: '1', message_body: 'msg2'}])) subject.send_messages(entries: [{id: '0', message_body: 'msg1'}, {id: '1', message_body: 'msg2'}]) end it 'accepts an array of messages' do options = { entries: [{ id: '0', message_body: 'msg1', delay_seconds: 1, message_attributes: { attr: 'attr1' } }, { id: '1', message_body: 'msg2', delay_seconds: 1, message_attributes: { attr: 'attr2' } }] } expect(sqs).to receive(:send_message_batch).with(hash_including(options)) subject.send_messages([{ message_body: 'msg1', delay_seconds: 1, message_attributes: { attr: 'attr1' } }, { message_body: 'msg2', delay_seconds: 1, message_attributes: { attr: 'attr2' } }]) end context 'when FIFO' do before do allow(subject).to receive(:fifo?).and_return(true) end context 'and message_group_id and message_deduplication_id are absent' do it 'sets default values' do expect(sqs).to receive(:send_message_batch) do |arg| first_entry = arg[:entries].first expect(first_entry[:message_group_id]).to eq described_class::MESSAGE_GROUP_ID expect(first_entry[:message_deduplication_id]).to be end subject.send_messages([{ message_body: 'msg1', message_attributes: { attr: 'attr1' } }]) end end context 'and message_group_id and message_deduplication_id are present' do it 'preserves existing values' do expect(sqs).to receive(:send_message_batch) do |arg| first_entry = arg[:entries].first expect(first_entry[:message_group_id]).to eq 'my group' expect(first_entry[:message_deduplication_id]).to eq 'my id' end subject.send_messages([{ message_body: 'msg1', message_attributes: { attr: 'attr1' }, message_group_id: 'my group', message_deduplication_id: 'my id' }]) end end end it 'accepts an array of string' do expect(sqs).to receive(:send_message_batch).with(hash_including(entries: [{ id: '0', message_body: 'msg1' }, { id: '1', message_body: 'msg2' }])) subject.send_messages(%w(msg1 msg2)) end end describe '#fifo?' do before do attribute_response = double 'Aws::SQS::Types::GetQueueAttributesResponse' allow(attribute_response).to receive(:attributes).and_return('FifoQueue' => fifo.to_s, 'ContentBasedDeduplication' => 'true') allow(subject).to receive(:url).and_return(queue_url) allow(sqs).to receive(:get_queue_attributes).with(queue_url: queue_url, attribute_names: ['All']).and_return(attribute_response) end context 'when queue is FIFO' do let(:fifo) { true } specify { expect(subject.fifo?).to be } end context 'when queue is not FIFO' do let(:fifo) { false } specify { expect(subject.fifo?).to_not be } end end end