fake_servicebus 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.md +20 -0
  7. data/README.md +41 -0
  8. data/Rakefile +31 -0
  9. data/bin/fake_servicebus +65 -0
  10. data/fake_servicebus.gemspec +33 -0
  11. data/lib/fake_servicebus.rb +90 -0
  12. data/lib/fake_servicebus/actions/create_queue.rb +64 -0
  13. data/lib/fake_servicebus/actions/delete_message.rb +19 -0
  14. data/lib/fake_servicebus/actions/delete_queue.rb +18 -0
  15. data/lib/fake_servicebus/actions/get_queue.rb +20 -0
  16. data/lib/fake_servicebus/actions/list_queues.rb +28 -0
  17. data/lib/fake_servicebus/actions/receive_message.rb +44 -0
  18. data/lib/fake_servicebus/actions/renew_lock_message.rb +19 -0
  19. data/lib/fake_servicebus/actions/send_message.rb +22 -0
  20. data/lib/fake_servicebus/actions/unlock_message.rb +19 -0
  21. data/lib/fake_servicebus/api.rb +71 -0
  22. data/lib/fake_servicebus/catch_errors.rb +19 -0
  23. data/lib/fake_servicebus/collection_view.rb +20 -0
  24. data/lib/fake_servicebus/daemonize.rb +30 -0
  25. data/lib/fake_servicebus/databases/file.rb +129 -0
  26. data/lib/fake_servicebus/databases/memory.rb +30 -0
  27. data/lib/fake_servicebus/error_response.rb +55 -0
  28. data/lib/fake_servicebus/error_responses.yml +32 -0
  29. data/lib/fake_servicebus/message.rb +59 -0
  30. data/lib/fake_servicebus/queue.rb +201 -0
  31. data/lib/fake_servicebus/queue_factory.rb +16 -0
  32. data/lib/fake_servicebus/queues.rb +72 -0
  33. data/lib/fake_servicebus/responder.rb +41 -0
  34. data/lib/fake_servicebus/server.rb +19 -0
  35. data/lib/fake_servicebus/show_output.rb +21 -0
  36. data/lib/fake_servicebus/test_integration.rb +122 -0
  37. data/lib/fake_servicebus/version.rb +3 -0
  38. data/lib/fake_servicebus/web_interface.rb +74 -0
  39. data/spec/acceptance/message_actions_spec.rb +452 -0
  40. data/spec/acceptance/queue_actions_spec.rb +82 -0
  41. data/spec/integration_spec_helper.rb +23 -0
  42. data/spec/spec_helper.rb +3 -0
  43. data/spec/unit/api_spec.rb +76 -0
  44. data/spec/unit/catch_errors_spec.rb +43 -0
  45. data/spec/unit/collection_view_spec.rb +41 -0
  46. data/spec/unit/error_response_spec.rb +65 -0
  47. data/spec/unit/message_spec.rb +76 -0
  48. data/spec/unit/queue_factory_spec.rb +13 -0
  49. data/spec/unit/queue_spec.rb +204 -0
  50. data/spec/unit/queues_spec.rb +102 -0
  51. data/spec/unit/responder_spec.rb +44 -0
  52. data/spec/unit/show_output_spec.rb +22 -0
  53. data/spec/unit/web_interface_spec.rb +15 -0
  54. metadata +266 -0
@@ -0,0 +1,82 @@
1
+ require "integration_spec_helper"
2
+
3
+ RSpec.describe "Actions for Queues", :sqs do
4
+
5
+ let(:sqs) { Aws::SQS::Client.new }
6
+ before do
7
+ sqs.config.endpoint = $fake_sqs.uri
8
+ end
9
+
10
+ specify "CreateQueue" do
11
+ response = sqs.create_queue(queue_name: "test-create-queue")
12
+ expect(response.queue_url).to eq "http://0.0.0.0:4568/test-create-queue"
13
+ response2 = sqs.get_queue_attributes(queue_url: response.queue_url)
14
+ expect(response2.attributes.fetch("QueueArn")).to match %r"arn:aws:sqs:us-east-1:.+:test-create-queue"
15
+ end
16
+
17
+ specify "GetQueueUrl" do
18
+ sqs.create_queue(queue_name: "test-get-queue-url")
19
+ response = sqs.get_queue_url(queue_name: "test-get-queue-url")
20
+ expect(response.queue_url).to eq "http://0.0.0.0:4568/test-get-queue-url"
21
+ end
22
+
23
+ specify "ListQueues" do
24
+ sqs.create_queue(queue_name: "test-list-1")
25
+ sqs.create_queue(queue_name: "test-list-2")
26
+ expect(sqs.list_queues.queue_urls).to eq [
27
+ "http://0.0.0.0:4568/test-list-1",
28
+ "http://0.0.0.0:4568/test-list-2"
29
+ ]
30
+ end
31
+
32
+ specify "ListQueues with prefix" do
33
+ sqs.create_queue(queue_name: "test-list-1")
34
+ sqs.create_queue(queue_name: "test-list-2")
35
+ sqs.create_queue(queue_name: "other-list-3")
36
+ expect(sqs.list_queues(queue_name_prefix: "test").queue_urls).to eq [
37
+ "http://0.0.0.0:4568/test-list-1",
38
+ "http://0.0.0.0:4568/test-list-2",
39
+ ]
40
+ end
41
+
42
+ specify "ListDeadLetterSourceQueues" do
43
+ dlq_queue_url = sqs.create_queue(queue_name: "source-list-DLQ").queue_url
44
+ dlq_arn = sqs.get_queue_attributes(queue_url: dlq_queue_url).attributes.fetch("QueueArn")
45
+ source_queue_urls = []
46
+ 2.times do |time|
47
+ queue_url = sqs.create_queue(queue_name: "source-list-#{time}").queue_url
48
+ sqs.set_queue_attributes(queue_url: queue_url,
49
+ attributes: {
50
+ "RedrivePolicy" => "{\"deadLetterTargetArn\":\"#{dlq_arn}\",\"maxReceiveCount\":10}"
51
+ }
52
+ )
53
+ source_queue_urls << queue_url
54
+ end
55
+ expect(sqs.list_dead_letter_source_queues(queue_url: dlq_queue_url).queue_urls).to eq source_queue_urls
56
+ end
57
+
58
+ specify "DeleteQueue" do
59
+ url = sqs.create_queue(queue_name: "test-delete").queue_url
60
+ expect(sqs.list_queues.queue_urls.size).to eq 1
61
+ sqs.delete_queue(queue_url: url)
62
+ expect(sqs.list_queues.queue_urls.size).to eq 0
63
+ end
64
+
65
+ specify "SetQueueAttributes / GetQueueAttributes" do
66
+ queue_url = sqs.create_queue(queue_name: "my-queue").queue_url
67
+
68
+
69
+ sqs.set_queue_attributes(
70
+ queue_url: queue_url,
71
+ attributes: {
72
+ "DelaySeconds" => "900"
73
+ }
74
+ )
75
+
76
+ response = sqs.get_queue_attributes(
77
+ queue_url: queue_url,
78
+ )
79
+ expect(response.attributes.fetch("DelaySeconds")).to eq "900"
80
+ end
81
+
82
+ end
@@ -0,0 +1,23 @@
1
+ require "aws-sdk"
2
+ require "fake_sqs/test_integration"
3
+
4
+ Aws.config.update(
5
+ region: "us-east-1",
6
+ credentials: Aws::Credentials.new("fake", "fake"),
7
+ )
8
+
9
+ db = ENV["SQS_DATABASE"] || ":memory:"
10
+ puts "\n\e[34mRunning specs with database \e[33m#{db}\e[0m"
11
+
12
+ $fake_sqs = FakeSQS::TestIntegration.new(
13
+ database: db,
14
+ sqs_endpoint: "0.0.0.0",
15
+ sqs_port: 4568,
16
+ start_timeout: 2,
17
+ )
18
+
19
+ RSpec.configure do |config|
20
+ config.before(:each, :sqs) { $fake_sqs.start }
21
+ config.before(:each, :sqs) { $fake_sqs.reset }
22
+ config.after(:suite) { $fake_sqs.stop }
23
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.disable_monkey_patching!
3
+ end
@@ -0,0 +1,76 @@
1
+ require 'fake_sqs/api'
2
+
3
+ class FakeSQS::Actions::ImmediateAction
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ end
8
+
9
+ def call(params)
10
+ { :options => @options, :params => params }
11
+ end
12
+
13
+ end
14
+
15
+ class FakeSQS::Actions::PollingAction
16
+
17
+ def initialize(options)
18
+ @options = options
19
+ @call_count = 0
20
+ end
21
+
22
+ def call(params)
23
+ @call_count += 1
24
+ end
25
+
26
+ def satisfied?
27
+ @call_count >= 3
28
+ end
29
+ end
30
+
31
+ RSpec.describe FakeSQS::API do
32
+
33
+ it "delegates actions to classes" do
34
+ queues = double :queues
35
+ allow(queues).to receive(:transaction).and_yield
36
+ api = FakeSQS::API.new(:queues => queues)
37
+
38
+ response = api.call("ImmediateAction", {}, {:foo => "bar"})
39
+
40
+ expect(response[:options]).to eq :queues => queues, :request => {}
41
+ expect(response[:params]).to eq :foo => "bar"
42
+ end
43
+
44
+ it "attempts a polling action until it's satisfied" do
45
+ queues = double :queues
46
+ allow(queues).to receive(:transaction).and_yield
47
+ api = FakeSQS::API.new(:queues => queues)
48
+
49
+ call_count = api.call("PollingAction", {}, {})
50
+ expect(call_count).to eq 3
51
+ end
52
+
53
+ it "raises InvalidAction for unknown actions" do
54
+ api = FakeSQS::API.new(:queues => [])
55
+
56
+ expect {
57
+ api.call("SomethingDifferentAndUnknown", {:foo => "bar"})
58
+ }.to raise_error(FakeSQS::InvalidAction)
59
+
60
+ end
61
+
62
+ it "resets queues" do
63
+ queues = double :queues
64
+ api = FakeSQS::API.new(:queues => queues)
65
+ expect(queues).to receive(:reset)
66
+ api.reset
67
+ end
68
+
69
+ it "expires messages in queues" do
70
+ queues = double :queues
71
+ api = FakeSQS::API.new(:queues => queues)
72
+ expect(queues).to receive(:expire)
73
+ api.expire
74
+ end
75
+
76
+ end
@@ -0,0 +1,43 @@
1
+ require 'fake_sqs/catch_errors'
2
+
3
+ RSpec.describe FakeSQS::CatchErrors do
4
+
5
+ let(:app) { double :app }
6
+ let(:error_response) { double :error_response, :status => 500, :body => "X" }
7
+ let(:response) { double :response, :new => error_response }
8
+ subject(:catch_errors) { FakeSQS::CatchErrors.new(app, response: response) }
9
+
10
+ context "when the app behaves normally" do
11
+
12
+ let(:normal_response) { double :normal_response }
13
+ before { allow(app).to receive(:call).and_return(normal_response) }
14
+
15
+ it "doesn't modify normal responses" do
16
+ expect(catch_errors.call({})).to eq normal_response
17
+ end
18
+
19
+ end
20
+
21
+ context "when the app raises an exception" do
22
+
23
+ let(:error) { RuntimeError.new("it went wrong") }
24
+ before { allow(app).to receive(:call).and_raise(error) }
25
+
26
+ it "cathes and processes errors" do
27
+ expect(response).to receive(:new).with(error)
28
+ catch_errors.call({})
29
+ end
30
+
31
+ it "sets the status determined by the error response" do
32
+ allow(error_response).to receive(:status).and_return(123)
33
+ expect(catch_errors.call({}).fetch(0)).to eq 123
34
+ end
35
+
36
+ it "set the body determined by the error response" do
37
+ allow(error_response).to receive(:body).and_return("foobar")
38
+ expect(catch_errors.call({}).fetch(2)).to eq ["foobar"]
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'fake_sqs/collection_view'
2
+
3
+ RSpec.describe FakeSQS::CollectionView do
4
+
5
+ def wrap(collection)
6
+ FakeSQS::CollectionView.new(collection)
7
+ end
8
+
9
+ it 'should correctly wrap an array' do
10
+ array = %w{one two three four}
11
+ view = wrap(array)
12
+ expect(view[0]).to eq 'one'
13
+ expect(view[1]).to eq 'two'
14
+ expect(view[2]).to eq 'three'
15
+ expect(view[3]).to eq 'four'
16
+ end
17
+
18
+ it 'should correctly wrap a hash' do
19
+ hash = { :one => 1, :two => 2, :three => 3 }
20
+ view = wrap(hash)
21
+ expect(view[:one]).to eq 1
22
+ expect(view[:two]).to eq 2
23
+ expect(view[:three]).to eq 3
24
+ end
25
+
26
+ it 'should respond to empty correctly' do
27
+ expect(wrap([])).to be_empty
28
+ expect(wrap({'one' => 1})).to_not be_empty
29
+ end
30
+
31
+ it 'should be enumerable' do
32
+ result = wrap([1, 2, 3]).map { |i| i * i }
33
+ expect(result).to eq [1, 4, 9]
34
+ end
35
+
36
+ it 'should respond to size/length' do
37
+ expect(wrap([1, 2, 3]).size).to eq 3
38
+ expect(wrap([]).size).to eq 0
39
+ end
40
+
41
+ end
@@ -0,0 +1,65 @@
1
+ require 'fake_sqs/error_response'
2
+ require 'active_support/core_ext/hash'
3
+ require 'verbose_hash_fetch'
4
+
5
+ RSpec.describe FakeSQS::ErrorResponse do
6
+
7
+ module FakeSQS
8
+ MissingCredentials = Class.new(RuntimeError)
9
+ end
10
+ ErrorUnknownToSQS = Class.new(RuntimeError)
11
+
12
+ describe "#status" do
13
+
14
+ it "picks the right error status" do
15
+ error = FakeSQS::MissingCredentials.new("message")
16
+ response = FakeSQS::ErrorResponse.new(error)
17
+ expect(response.status).to eq 401
18
+ end
19
+
20
+ it "uses 400 as default status" do
21
+ error = ErrorUnknownToSQS.new("message")
22
+ response = FakeSQS::ErrorResponse.new(error)
23
+ expect(response.status).to eq 500
24
+ end
25
+
26
+ end
27
+
28
+ describe "#body" do
29
+
30
+ let(:error) { FakeSQS::MissingCredentials.new("the message") }
31
+ let(:response) { FakeSQS::ErrorResponse.new(error) }
32
+ let(:data) { Hash.from_xml(response.body) }
33
+
34
+ it "uses the error class name as error code" do
35
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Code")).to eq "MissingCredentials"
36
+ end
37
+
38
+ it "uses InternalError as code for unknown errors" do
39
+ error = ErrorUnknownToSQS.new("the message")
40
+ response = FakeSQS::ErrorResponse.new(error)
41
+ data = Hash.from_xml(response.body)
42
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Code")).to eq "InternalError"
43
+ end
44
+
45
+ it "uses the to_s of the error as message" do
46
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Message")).to eq "the message"
47
+ end
48
+
49
+ it "has a request id" do
50
+ expect(data.fetch("ErrorResponse").fetch("RequestId").size).to eq 36
51
+ end
52
+
53
+ it "uses Sender as type for 4xx responses" do
54
+ allow(response).to receive(:status).and_return(400)
55
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Type")).to eq "Sender"
56
+ end
57
+
58
+ it "uses Receiver as type for 5xx responses" do
59
+ allow(response).to receive(:status).and_return(500)
60
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Type")).to eq "Receiver"
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,76 @@
1
+ require 'fake_sqs/message'
2
+
3
+ RSpec.describe FakeSQS::Message do
4
+
5
+ describe "#body" do
6
+
7
+ it "is extracted from the MessageBody" do
8
+ message = create_message("MessageBody" => "abc")
9
+ expect(message.body).to eq "abc"
10
+ end
11
+
12
+ end
13
+
14
+ describe "#md5" do
15
+
16
+ it "is calculated from body" do
17
+ message = create_message("MessageBody" => "abc")
18
+ expect(message.md5).to eq "900150983cd24fb0d6963f7d28e17f72"
19
+ end
20
+
21
+ end
22
+
23
+ describe "#id" do
24
+
25
+ it "is generated" do
26
+ message = create_message
27
+ expect(message.id.size).to eq 36
28
+ end
29
+
30
+ end
31
+
32
+ describe "#delay_seconds" do
33
+
34
+ it "is generated" do
35
+ message = create_message({"DelaySeconds" => 10})
36
+ expect(message.delay_seconds).to eq 10
37
+ end
38
+
39
+ end
40
+
41
+ describe 'visibility_timeout' do
42
+
43
+ let :message do
44
+ create_message
45
+ end
46
+
47
+ it 'should default to nil' do
48
+ expect(message.visibility_timeout).to eq nil
49
+ end
50
+
51
+ it 'should be expired when it is nil' do
52
+ expect(message).to be_expired
53
+ end
54
+
55
+ it 'should be expired if set to a previous time' do
56
+ message.visibility_timeout = Time.now - 1
57
+ expect(message).to be_expired
58
+ end
59
+
60
+ it 'should not be expired at a future date' do
61
+ message.visibility_timeout = Time.now + 1
62
+ expect(message).not_to be_expired
63
+ end
64
+
65
+ it 'should not be expired when set to expire at a future date' do
66
+ message.expire_at(5)
67
+ expect(message.visibility_timeout).to be >=(Time.now + 4)
68
+ end
69
+
70
+ end
71
+
72
+ def create_message(options = {})
73
+ FakeSQS::Message.new({"MessageBody" => "test"}.merge(options))
74
+ end
75
+
76
+ end
@@ -0,0 +1,13 @@
1
+ require 'fake_sqs/queue_factory'
2
+
3
+ RSpec.describe FakeSQS::QueueFactory do
4
+
5
+ it "builds queues with a message factory" do
6
+ message_factory = double :message_factory
7
+ queue = double :queue
8
+ queue_factory = FakeSQS::QueueFactory.new(message_factory: message_factory, queue: queue)
9
+ expect(queue).to receive(:new).with(message_factory: message_factory, name: "Foo")
10
+ queue_factory.new(name: "Foo")
11
+ end
12
+
13
+ end
@@ -0,0 +1,204 @@
1
+ require 'fake_sqs/queue'
2
+ require 'fake_sqs/message'
3
+
4
+ RSpec.describe FakeSQS::Queue do
5
+
6
+ class MessageFactory
7
+ def new(options = {})
8
+ FakeSQS::Message.new({'MessageBody' => 'sample-body'}.merge(options))
9
+ end
10
+ end
11
+
12
+ let(:message_factory) { MessageFactory.new }
13
+ subject(:queue) { FakeSQS::Queue.new(:message_factory => message_factory, "QueueName" => "test-queue") }
14
+
15
+ describe "#send_message" do
16
+
17
+ it "adds a message" do
18
+ expect(queue.messages.size).to eq 0
19
+ send_message
20
+ expect(queue.messages.size).to eq 1
21
+ end
22
+
23
+ it "returns the message" do
24
+ message = double.as_null_object
25
+ allow(message_factory).to receive(:new).and_return(message)
26
+ expect(send_message).to eq message
27
+ end
28
+
29
+ it "uses the message factory" do
30
+ options = { "MessageBody" => "abc" }
31
+ expect(message_factory).to receive(:new).with(options)
32
+ send_message(options)
33
+ end
34
+
35
+ it "should set the message's SentTimestamp attribute" do
36
+ expect(send_message.attributes["SentTimestamp"]).to eq (Time.now.to_i * 1000)
37
+ end
38
+
39
+ it "should set the SenderId of the sender" do
40
+ sender_id = send_message.attributes["SenderId"]
41
+ expect(sender_id).to be_a String
42
+ expect(sender_id.length).to eq 21
43
+ end
44
+ end
45
+
46
+ describe "#receive_message" do
47
+
48
+ it "gets the message" do
49
+ sent = send_message
50
+ received = receive_message
51
+ expect(received.values.first).to eq sent
52
+ end
53
+
54
+ it "gets the message with 'DelaySeconds' option" do
55
+ delay_seconds = 3
56
+ sent = send_message({ "DelaySeconds" => delay_seconds })
57
+ received = receive_message
58
+ expect(received.values.first).to be_nil
59
+
60
+ allow(Time).to receive(:now).and_return(Time.now + delay_seconds)
61
+ received = receive_message
62
+ expect(received.values.first).to eq sent
63
+ end
64
+
65
+ it "gets you a random message" do
66
+ indexes = { :first => 0, :second => 0 }
67
+ sample_group = 1_000
68
+ half_sample_group = sample_group / 2
69
+ ten_percent = half_sample_group / 0.1
70
+
71
+ sample_group.times do
72
+ sent_first = send_message
73
+ _ = send_message
74
+ message = receive_message.values.first
75
+ if message == sent_first
76
+ indexes[:first] += 1
77
+ else
78
+ indexes[:second] += 1
79
+ end
80
+ reset_queue
81
+ end
82
+
83
+ expect(indexes[:first] + indexes[:second]).to eq sample_group
84
+
85
+ expect(indexes[:first]).to be_within(ten_percent).of(half_sample_group)
86
+ expect(indexes[:second]).to be_within(ten_percent).of(half_sample_group)
87
+ end
88
+
89
+ it "cannot get received messages" do
90
+ sample_group = 1_000
91
+
92
+ sample_group.times do
93
+ sent_first = send_message
94
+ sent_second = send_message
95
+ received_first = receive_message.values.first
96
+
97
+ if received_first == sent_first
98
+ expect(receive_message.values.first).to eq sent_second
99
+ else
100
+ expect(receive_message.values.first).to eq sent_first
101
+ end
102
+ reset_queue
103
+ end
104
+ end
105
+
106
+ it "keeps track of sent messages" do
107
+
108
+ send_message
109
+
110
+ expect(queue.messages_in_flight.size).to eq 0
111
+ expect(queue.attributes["ApproximateNumberOfMessagesNotVisible"]).to eq 0
112
+ expect(queue.attributes["ApproximateNumberOfMessages"]).to eq 1
113
+
114
+ receive_message
115
+
116
+ expect(queue.messages_in_flight.size).to eq 1
117
+ expect(queue.attributes["ApproximateNumberOfMessagesNotVisible"]).to eq 1
118
+ expect(queue.attributes["ApproximateNumberOfMessages"]).to eq 0
119
+ end
120
+
121
+ it "gets multiple message" do
122
+ sent_first = send_message
123
+ sent_second = send_message
124
+ messages = receive_message("MaxNumberOfMessages" => "2")
125
+ expect(messages.size).to eq 2
126
+ expect(messages.values).to match_array [ sent_first, sent_second ]
127
+ end
128
+
129
+ it "won't accept more than 10 message" do
130
+ expect {
131
+ receive_message("MaxNumberOfMessages" => "11")
132
+ }.to raise_error(FakeSQS::ReadCountOutOfRange, "11")
133
+ end
134
+
135
+ it "won't error on empty queues" do
136
+ expect(receive_message).to eq({})
137
+ end
138
+
139
+ it "should increment the ApproximateReceiveCount" do
140
+ sent_message = send_message
141
+ expect(sent_message.attributes["ApproximateReceiveCount"]).to eq 0
142
+ queue.change_message_visibility(receive_message.keys.first, 0)
143
+ expect(sent_message.attributes["ApproximateReceiveCount"]).to eq 1
144
+ receive_message
145
+ expect(sent_message.attributes["ApproximateReceiveCount"]).to eq 2
146
+ end
147
+
148
+ it "should set the ApproximateFirstReceiveTimestamp only when the message is first received" do
149
+ sent_message = send_message
150
+ expect(sent_message.attributes["ApproximateFirstReceiveTimestamp"]).to eq nil
151
+ receive_time = (Time.now.to_i * 1000)
152
+ queue.change_message_visibility(receive_message.keys.first, 0)
153
+ expect(sent_message.attributes["ApproximateFirstReceiveTimestamp"]).to eq receive_time
154
+ sleep 1
155
+ receive_message
156
+ expect(sent_message.attributes["ApproximateFirstReceiveTimestamp"]).to eq receive_time
157
+ end
158
+ end
159
+
160
+ describe "#delete_message" do
161
+
162
+ it "deletes by the receipt" do
163
+ send_message
164
+ receipt = receive_message.keys.first
165
+
166
+ expect(queue.messages_in_flight.size).to eq 1
167
+ queue.delete_message(receipt)
168
+ expect(queue.messages_in_flight.size).to eq 0
169
+ expect(queue.messages.size).to eq 0
170
+ end
171
+
172
+ it "won't raise if the receipt is unknown" do
173
+ queue.delete_message("abc")
174
+ end
175
+
176
+ end
177
+
178
+ describe "#add_queue_attributes" do
179
+
180
+ it "adds to it's queue attributes" do
181
+ queue.add_queue_attributes("foo" => "bar")
182
+ expect(queue.attributes).to eq(
183
+ "foo" => "bar",
184
+ "QueueArn" => queue.arn,
185
+ "ApproximateNumberOfMessages" => 0,
186
+ "ApproximateNumberOfMessagesNotVisible" => 0
187
+ )
188
+ end
189
+
190
+ end
191
+
192
+ def send_message(options = {})
193
+ queue.send_message(options)
194
+ end
195
+
196
+ def receive_message(options = {})
197
+ queue.receive_message(options)
198
+ end
199
+
200
+ def reset_queue
201
+ queue.reset
202
+ end
203
+
204
+ end