sqs_web 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 402d02606f9f97d50fa51892ee6b372b34d13cea
4
- data.tar.gz: 85af922a688dbbe657cd445030827184203fb5eb
3
+ metadata.gz: 1255501537a0297a7b1eda47890fc64bc4919b74
4
+ data.tar.gz: 9663fb87014c3efe614e7c30c532657fa60897ed
5
5
  SHA512:
6
- metadata.gz: fbe157d2c9d2342154a0eb92f043c50664e27afc1dabe04133c93d60ac70cd5371cabb021a880c2b66c2ab77abdd91734e4952d1a7dacc3cd90c58da59a2bb04
7
- data.tar.gz: 34d78f607cfaae8ab4d007d2aa698eff188ad41829007b38c319b9c99cb0f34f8a3f64b1255dbce512d8287ffb10f7b8000993b49c9136585cbd3a350a68754f
6
+ metadata.gz: f61f3cb396aa0bff8b8e4dcaca1166c7625c16201fb092e7fae80c9e71ca51fffb8997ee7a7cfddb74f480ef638df4cf5060c3bd5f80cba76ae60adccd6b7503
7
+ data.tar.gz: 179b3470d93fc17143e5acba25e9d769f9ad73eb0b231095b045c22ebb2f0694f6b3fa789a024028af8fc7f67f81e94913a5f732118ece790305b45ca6e3c0b8
@@ -1,6 +1,4 @@
1
1
  $(function() {
2
- var poll_interval = 3;
3
-
4
2
  var relatizer = function(){
5
3
  var dt = $(this).text(), relatized = $.relatizeDate(this)
6
4
  if ($(this).parents("a").length > 0 || $(this).is("a")) {
@@ -55,4 +53,16 @@ $(function() {
55
53
  $("#bulk_action_submit input").click(function() {
56
54
  $('#bulk_action_form').attr("action", $(this).attr("action"));
57
55
  });
56
+
57
+ $(".remove_single").click(function(e) {
58
+ if (!confirm("Are you sure you want to remove the message?")){
59
+ e.preventDefault();
60
+ }
61
+ });
62
+
63
+ $(".remove_bulk").click(function(e) {
64
+ if (!confirm("Are you sure you want to remove the selected messages?")){
65
+ e.preventDefault();
66
+ }
67
+ });
58
68
  })
@@ -10,7 +10,7 @@
10
10
  <%= csrf_token_tag %>
11
11
  Select/Unselect All <input type="checkbox" id="select_all" />
12
12
  <div id="bulk_action_submit">
13
- <input type="submit" value="Bulk Remove" action="<%= u("bulk_remove") %>"/>
13
+ <input class="remove_bulk" type="submit" value="Bulk Remove" action="<%= u("bulk_remove") %>"/>
14
14
  <input type="submit" value="Bulk Move to Source Queue" action="<%= u("bulk_requeue") %>"/>
15
15
  </div>
16
16
  </form>
@@ -8,7 +8,7 @@
8
8
  <div class="controls">
9
9
  <form action="<%= u("remove/#{queue[:name]}/#{message.message_id}") %>" method="post">
10
10
  <%= csrf_token_tag %>
11
- <input type="submit" value="Remove" />
11
+ <input class="remove_single" type="submit" value="Remove" />
12
12
  </form>
13
13
  or
14
14
  <form action="<%= u("requeue/#{queue[:name]}/#{message.message_id}") %>" method="post">
@@ -1,33 +1,4 @@
1
- require 'support/rails_app'
2
- require 'support/fake_sqs'
3
-
4
- Capybara.app = RailsApp
5
-
6
- RSpec.describe "Mounted in Rails Application", :sqs do
7
-
8
- SOURCE_QUEUE_NAME = "TestSourceQueue"
9
-
10
- DLQ_QUEUE_NAME = "TestSourceQueueDLQ"
11
-
12
- let(:sqs) { Aws::SQS::Client.new(region: "us-east-1", credentials: Aws::Credentials.new("fake", "fake")) }
13
-
14
- let(:source_queue_url) { sqs.get_queue_url(queue_name: SOURCE_QUEUE_NAME).queue_url }
15
-
16
- let(:dlq_queue_url) { sqs.get_queue_url(queue_name: DLQ_QUEUE_NAME).queue_url }
17
-
18
- before do
19
- sqs.config.endpoint = $fake_sqs.uri
20
- [SOURCE_QUEUE_NAME, DLQ_QUEUE_NAME].each{|queue_name| sqs.create_queue(queue_name: queue_name)}
21
- dlq_arn = sqs.get_queue_attributes(queue_url: dlq_queue_url).attributes.fetch("QueueArn")
22
- #Set DLQ
23
- sqs.set_queue_attributes(
24
- queue_url: source_queue_url,
25
- attributes: {
26
- "RedrivePolicy" => "{\"deadLetterTargetArn\":\"#{dlq_arn}\",\"maxReceiveCount\":10}"
27
- }
28
- )
29
- SqsWeb.options[:queues] = [SOURCE_QUEUE_NAME, DLQ_QUEUE_NAME]
30
- end
1
+ RSpec.describe "General Application features", :sqs do
31
2
 
32
3
  # basic smoke test all the tabs
33
4
  %w(overview dlq_console).each do |tab|
@@ -36,334 +7,4 @@ RSpec.describe "Mounted in Rails Application", :sqs do
36
7
  expect(page.status_code).to eq 200
37
8
  end
38
9
  end
39
-
40
- describe "Overview page" do
41
- it "will show Visible Messages" do
42
- default_messages
43
-
44
- visit "/sqs/overview"
45
-
46
- match_content(page, "#{SOURCE_QUEUE_NAME} 5 0 N/A")
47
- match_content(page, "#{DLQ_QUEUE_NAME} 3 0 #{source_queue_url}")
48
- end
49
-
50
- specify "In Flight Messages" do
51
- default_messages
52
-
53
- receive_messages(source_queue_url, {count: 3})
54
- receive_messages(dlq_queue_url, {count: 2})
55
-
56
- visit "/sqs/overview"
57
-
58
- match_content(page, "#{SOURCE_QUEUE_NAME} 2 3 N/A")
59
- match_content(page, "#{DLQ_QUEUE_NAME} 1 2 #{source_queue_url}")
60
- end
61
-
62
- specify "should be default page" do
63
- visit "/sqs"
64
-
65
- expect(current_path).to eq "/sqs/overview"
66
- end
67
-
68
- specify "handle non existent queues" do
69
- SqsWeb.options[:queues] = ["BOGUSQUEUE"]
70
-
71
- visit "/sqs/overview"
72
-
73
- match_content(page, "Aws::SQS::Errors::NonExistentQueue: BOGUSQUEUE")
74
- end
75
- end
76
-
77
- describe "DLQ Console", js: true do
78
-
79
- it "should only show unique entries for each message" do
80
- message_ids = generate_messages(dlq_queue_url, 5).map{|c| c.message_id}
81
-
82
- visit "/sqs/dlq_console"
83
-
84
- message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 1}
85
- end
86
-
87
- it "should delete single message" do
88
- messages = generate_messages(dlq_queue_url, 2)
89
- deleted_message_id = messages.pop.message_id
90
- retained_message_id = messages.pop.message_id
91
-
92
- visit "/sqs/dlq_console"
93
-
94
- first("#message_#{deleted_message_id}").hover
95
-
96
- within("#message_#{deleted_message_id}") do
97
- click_on "Remove"
98
- end
99
-
100
- success_message = "Message ID: #{deleted_message_id} in Queue #{DLQ_QUEUE_NAME} was successfully removed."
101
- expect(first("#alert").text).to eq success_message
102
-
103
- expect(page.all("#message_#{deleted_message_id}").count).to eq 0
104
- expect(page.all("#message_#{retained_message_id}").count).to eq 1
105
-
106
- visit "/sqs/overview"
107
-
108
- match_content(page, "#{DLQ_QUEUE_NAME} 1 0 #{source_queue_url}")
109
- end
110
-
111
- it "should handle deleting single message that is already deleted" do
112
- deleted_message_id = generate_messages(dlq_queue_url, 1).first.message_id
113
-
114
- visit "/sqs/dlq_console"
115
-
116
- sqs.purge_queue({ queue_url: dlq_queue_url })
117
-
118
- first("#message_#{deleted_message_id}").hover
119
-
120
- within("#message_#{deleted_message_id}") do
121
- click_on "Remove"
122
- end
123
-
124
- error_message = "Message ID: #{deleted_message_id} in Queue #{DLQ_QUEUE_NAME} has already been deleted or is not visible."
125
- expect(first("#alert").text).to eq error_message
126
- end
127
-
128
- it "should remove multiple selected messages" do
129
- messages = generate_messages(dlq_queue_url, 6)
130
- deleted_message_ids = messages.pop(4).map{|c| c.message_id}
131
- retained_message_ids = messages.pop(2).map{|c| c.message_id}
132
-
133
- visit "/sqs/dlq_console"
134
-
135
- deleted_message_ids.each do |message_id|
136
- first("#batch_action_item_#{message_id}").set(true)
137
- end
138
-
139
- click_on "Bulk Remove"
140
-
141
- expect(first("#alert").text).to eq "Selected messages have been removed successfully."
142
-
143
- deleted_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 0}
144
- retained_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 1}
145
-
146
- visit "/sqs/overview"
147
-
148
- match_content(page, "#{DLQ_QUEUE_NAME} 2 0 #{source_queue_url}")
149
- end
150
-
151
- it "should handle removing multiple selected messages where one or more is already deleted or not visible" do
152
- generate_messages(dlq_queue_url, 3)
153
-
154
- visit "/sqs/dlq_console"
155
-
156
- messages = receive_messages(dlq_queue_url, {count: 3}).messages
157
- sqs.delete_message({queue_url: dlq_queue_url, receipt_handle: messages[2].receipt_handle})
158
- sqs.change_message_visibility_batch({
159
- queue_url: dlq_queue_url,
160
- entries: messages.take(2).map do |message|
161
- {id: message.message_id, receipt_handle: message.receipt_handle, visibility_timeout: 0}
162
- end
163
- })
164
- messages.each do |message|
165
- first("#batch_action_item_#{message.message_id}").set(true)
166
- end
167
-
168
- click_on "Bulk Remove"
169
-
170
- expect(first("#alert").text).to eq "One or more messages may have already been removed or is not visible."
171
-
172
- messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 0}
173
-
174
- visit "/sqs/overview"
175
-
176
- match_content(page, "#{DLQ_QUEUE_NAME} 0 0 #{source_queue_url}")
177
- end
178
-
179
- it "should handle clicking on Bulk Remove without any selection" do
180
- messages = generate_messages(dlq_queue_url, 3)
181
-
182
- visit "/sqs/dlq_console"
183
-
184
- click_on "Bulk Remove"
185
-
186
- expect(first("#alert").text).to eq ""
187
-
188
- messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 1}
189
- end
190
-
191
- it "should render all information related to the visible messages" do
192
- generate_messages(dlq_queue_url, 1)
193
-
194
- visit "/sqs/dlq_console"
195
-
196
- message = receive_messages(dlq_queue_url).messages.first
197
- message.attributes["ApproximateReceiveCount"] = "1"
198
-
199
- message_metadata = <<-EOF
200
- ID #{message.message_id} or Receive Count 1
201
- Queue Name #{DLQ_QUEUE_NAME} Origin Queue #{source_queue_url}
202
- Message Body Test_0
203
- EOF
204
-
205
- message_entry = first("#message_#{message.message_id}")
206
-
207
- within(message_entry) do
208
- click_on "Toggle full message"
209
- first(".toggle_format").click
210
- end
211
-
212
- match_content(message_entry, normalize_whitespace(message_metadata))
213
- match_content(message_entry, normalize_whitespace(message.inspect.to_yaml.split('receipt_handle')[0]))
214
- match_content(message_entry, normalize_whitespace(message.inspect.to_yaml.split('md5', 2)[1]))
215
- match_content(message_entry, normalize_whitespace("Enqueued At #{Time.at(message.attributes["SentTimestamp"].to_i/1000).rfc822}"))
216
- end
217
-
218
- it "should not display any messages that are not in a DLQ" do
219
- generate_messages(source_queue_url, 1)
220
-
221
- visit "/sqs/dlq_console"
222
-
223
- message = receive_messages(source_queue_url).messages.first
224
-
225
- expect(first("#message_#{message.message_id}")).to be_nil
226
-
227
- match_content(page, "Showing 0 visible messages")
228
- end
229
-
230
- it "should be able to move a single message to source queue" do
231
- message_id = generate_messages(dlq_queue_url, 1).first.message_id
232
-
233
-
234
- visit "/sqs/dlq_console"
235
-
236
- first("#message_#{message_id}").hover
237
-
238
- within("#message_#{message_id}") do
239
- click_on "Move to Source Queue"
240
- end
241
-
242
- success_message = "Message ID: #{message_id} in Queue #{DLQ_QUEUE_NAME} was successfully moved to Source Queue #{source_queue_url}."
243
- expect(first("#alert").text).to eq success_message
244
- expect(page.all("#message_#{message_id}").count).to eq 0
245
-
246
- visit "/sqs/overview"
247
-
248
- match_content(page, "#{SOURCE_QUEUE_NAME} 1 0 N/A")
249
- match_content(page, "#{DLQ_QUEUE_NAME} 0 0 #{source_queue_url}")
250
-
251
- moved_message = receive_messages(source_queue_url).messages.first
252
- expect(moved_message).to_not be_nil
253
- expect(moved_message.body).to eq "Test_0"
254
- expect(moved_message.attributes["ApproximateReceiveCount"]).to eq "1"
255
- expect(moved_message.message_attributes["foo_class"].to_hash).to eq({string_value: "FooWorker", data_type: "String"})
256
- end
257
-
258
- it "should move multiple selected messages" do
259
- messages = generate_messages(dlq_queue_url, 6)
260
- retained_message_ids = messages.pop(2).map{|c| c.message_id}
261
- moved_message_ids = messages.pop(4).map{|c| c.message_id}
262
-
263
- visit "/sqs/dlq_console"
264
-
265
- moved_message_ids.each do |message_id|
266
- first("#batch_action_item_#{message_id}").set(true)
267
- end
268
-
269
- click_on "Bulk Move to Source Queue"
270
-
271
- expect(first("#alert").text).to eq "Selected messages have been requeued successfully."
272
-
273
- moved_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 0}
274
- retained_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 1}
275
-
276
- visit "/sqs/overview"
277
-
278
- match_content(page, "#{SOURCE_QUEUE_NAME} 4 0 N/A")
279
- match_content(page, "#{DLQ_QUEUE_NAME} 2 0 #{source_queue_url}")
280
-
281
- moved_messages = receive_messages(source_queue_url, {count: 4}).messages.sort_by{|c| c.body}
282
- moved_messages.each_with_index do |moved_message, index|
283
- expect(moved_message).to_not be_nil
284
- expect(moved_message.body).to match "Test_#{index}"
285
- expect(moved_message.attributes["ApproximateReceiveCount"]).to eq "1"
286
- expect(moved_message.message_attributes["foo_class"].to_hash).to eq({string_value: "FooWorker", data_type: "String"})
287
- end
288
- end
289
-
290
- it "should handle moving multiple selected messages where one or more is already deleted or not visible" do
291
- generate_messages(dlq_queue_url, 3)
292
-
293
- visit "/sqs/dlq_console"
294
-
295
- messages = receive_messages(dlq_queue_url, {count: 3}).messages
296
- sqs.delete_message({queue_url: dlq_queue_url, receipt_handle: messages[2].receipt_handle})
297
- sqs.change_message_visibility_batch({
298
- queue_url: dlq_queue_url,
299
- entries: messages.take(2).map do |message|
300
- {id: message.message_id, receipt_handle: message.receipt_handle, visibility_timeout: 0}
301
- end
302
- })
303
- messages.each do |message|
304
- first("#batch_action_item_#{message.message_id}").set(true)
305
- end
306
-
307
- click_on "Bulk Move to Source Queue"
308
-
309
- expect(first("#alert").text).to eq "One or more messages may have already been requeued or is not visible."
310
-
311
- messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 0}
312
-
313
- visit "/sqs/overview"
314
-
315
- match_content(page, "#{SOURCE_QUEUE_NAME} 2 0 N/A")
316
- match_content(page, "#{DLQ_QUEUE_NAME} 0 0 #{source_queue_url}")
317
- end
318
-
319
- it "should handle clicking on Bulk Move to Source Queue without any selection" do
320
- messages = generate_messages(dlq_queue_url, 3)
321
-
322
- visit "/sqs/dlq_console"
323
-
324
- click_on "Bulk Move to Source Queue"
325
-
326
- expect(first("#alert").text).to eq ""
327
-
328
- messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 1}
329
- end
330
-
331
- it "should have a select/unselect all function" do
332
- messages = generate_messages(dlq_queue_url, 3)
333
-
334
- visit "/sqs/dlq_console"
335
-
336
- first("#select_all").click
337
-
338
- page.all(".bulk_check").each{|node| expect(node["checked"]).to eq true}
339
-
340
- first("#select_all").click
341
-
342
- page.all(".bulk_check").each{|node| expect(node["checked"]).to eq false}
343
- end
344
- end
345
-
346
- def receive_messages(queue_url, options = {count: 1})
347
- sqs.receive_message({
348
- queue_url: queue_url,
349
- attribute_names: ["All"],
350
- message_attribute_names: ["All"],
351
- max_number_of_messages: options[:count],
352
- wait_time_seconds: 1,
353
- visibility_timeout: options[:visibility_timeout]
354
- })
355
- end
356
-
357
- def default_messages
358
- generate_messages(source_queue_url, 5) + generate_messages(dlq_queue_url, 3)
359
- end
360
-
361
- def generate_messages(queue_url, count=1)
362
- messages = []
363
- count.times do |time|
364
- messages << sqs.send_message(queue_url: queue_url, message_body: "Test_#{time}",
365
- message_attributes: {"foo_class"=> {string_value: "FooWorker", data_type: "String"}})
366
- end
367
- messages
368
- end
369
10
  end
@@ -0,0 +1,308 @@
1
+ RSpec.describe "DLQ Console", js: true, sqs: true do
2
+
3
+ it "should only show unique entries for each message" do
4
+ message_ids = generate_messages(dlq_queue_url, 5).map{|c| c.message_id}
5
+
6
+ visit "/sqs/dlq_console"
7
+
8
+ message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 1}
9
+ end
10
+
11
+ it "should render all information related to the visible messages" do
12
+ generate_messages(dlq_queue_url, 1)
13
+
14
+ visit "/sqs/dlq_console"
15
+
16
+ message = receive_messages(dlq_queue_url).messages.first
17
+ message.attributes["ApproximateReceiveCount"] = "1"
18
+
19
+ message_metadata = <<-EOF
20
+ ID #{message.message_id} or Receive Count 1
21
+ Queue Name #{DLQ_QUEUE_NAME} Origin Queue #{source_queue_url}
22
+ Message Body Test_0
23
+ EOF
24
+
25
+ message_entry = first("#message_#{message.message_id}")
26
+
27
+ within(message_entry) do
28
+ click_on "Toggle full message"
29
+ first(".toggle_format").click
30
+ end
31
+
32
+ match_content(message_entry, normalize_whitespace(message_metadata))
33
+ match_content(message_entry, normalize_whitespace(message.inspect.to_yaml.split('receipt_handle')[0]))
34
+ match_content(message_entry, normalize_whitespace(message.inspect.to_yaml.split('md5', 2)[1]))
35
+ match_content(message_entry, normalize_whitespace("Enqueued At #{Time.at(message.attributes["SentTimestamp"].to_i/1000).rfc822}"))
36
+ end
37
+
38
+ it "should not display any messages that are not in a DLQ" do
39
+ generate_messages(source_queue_url, 1)
40
+
41
+ visit "/sqs/dlq_console"
42
+
43
+ message = receive_messages(source_queue_url).messages.first
44
+
45
+ expect(first("#message_#{message.message_id}")).to be_nil
46
+
47
+ match_content(page, "Showing 0 visible messages")
48
+ end
49
+
50
+ it "should have a select/unselect all function" do
51
+ messages = generate_messages(dlq_queue_url, 3)
52
+
53
+ visit "/sqs/dlq_console"
54
+
55
+ first("#select_all").click
56
+
57
+ page.all(".bulk_check").each{|node| expect(node["checked"]).to eq true}
58
+
59
+ first("#select_all").click
60
+
61
+ page.all(".bulk_check").each{|node| expect(node["checked"]).to eq false}
62
+ end
63
+
64
+ describe "Remove" do
65
+ it "should delete single message" do
66
+ messages = generate_messages(dlq_queue_url, 2)
67
+ deleted_message_id = messages.pop.message_id
68
+ retained_message_id = messages.pop.message_id
69
+
70
+ visit "/sqs/dlq_console"
71
+
72
+ first("#message_#{deleted_message_id}").hover
73
+
74
+ within("#message_#{deleted_message_id}") do
75
+ click_on "Remove"
76
+ end
77
+
78
+ success_message = "Message ID: #{deleted_message_id} in Queue #{DLQ_QUEUE_NAME} was successfully removed."
79
+ expect(first("#alert").text).to eq success_message
80
+
81
+ expect(page.all("#message_#{deleted_message_id}").count).to eq 0
82
+ expect(page.all("#message_#{retained_message_id}").count).to eq 1
83
+
84
+ visit "/sqs/overview"
85
+
86
+ match_content(page, "#{DLQ_QUEUE_NAME} 1 0 #{source_queue_url}")
87
+ end
88
+
89
+ it "should show a confirmation popup when deleting single message" do
90
+ messages = generate_messages(dlq_queue_url, 2)
91
+ deleted_message_id = messages.pop.message_id
92
+
93
+ visit "/sqs/dlq_console"
94
+
95
+ first("#message_#{deleted_message_id}").hover
96
+
97
+ message = page.accept_confirm do
98
+ within("#message_#{deleted_message_id}") do
99
+ click_on "Remove"
100
+ end
101
+ end
102
+
103
+ expect(message).to eq('Are you sure you want to remove the message?')
104
+ end
105
+
106
+ it "should handle deleting single message that is already deleted" do
107
+ deleted_message_id = generate_messages(dlq_queue_url, 1).first.message_id
108
+
109
+ visit "/sqs/dlq_console"
110
+
111
+ sqs.purge_queue({ queue_url: dlq_queue_url })
112
+
113
+ first("#message_#{deleted_message_id}").hover
114
+
115
+ within("#message_#{deleted_message_id}") do
116
+ click_on "Remove"
117
+ end
118
+
119
+ error_message = "Message ID: #{deleted_message_id} in Queue #{DLQ_QUEUE_NAME} has already been deleted or is not visible."
120
+ expect(first("#alert").text).to eq error_message
121
+ end
122
+ end
123
+
124
+ describe "Bulk Remove" do
125
+ it "should remove multiple selected messages" do
126
+ messages = generate_messages(dlq_queue_url, 6)
127
+ deleted_message_ids = messages.pop(4).map{|c| c.message_id}
128
+ retained_message_ids = messages.pop(2).map{|c| c.message_id}
129
+
130
+ visit "/sqs/dlq_console"
131
+
132
+ deleted_message_ids.each do |message_id|
133
+ first("#batch_action_item_#{message_id}").set(true)
134
+ end
135
+
136
+ click_on "Bulk Remove"
137
+
138
+ expect(first("#alert").text).to eq "Selected messages have been removed successfully."
139
+
140
+ deleted_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 0}
141
+ retained_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 1}
142
+
143
+ visit "/sqs/overview"
144
+
145
+ match_content(page, "#{DLQ_QUEUE_NAME} 2 0 #{source_queue_url}")
146
+ end
147
+
148
+ it "should show a confirmation popup when removing multiple messages" do
149
+ messages = generate_messages(dlq_queue_url, 6)
150
+ deleted_message_ids = messages.pop(4).map{|c| c.message_id}
151
+
152
+ visit "/sqs/dlq_console"
153
+
154
+ deleted_message_ids.each do |message_id|
155
+ first("#batch_action_item_#{message_id}").set(true)
156
+ end
157
+
158
+ message = page.accept_confirm do
159
+ click_on "Bulk Remove"
160
+ end
161
+
162
+ expect(message).to eq('Are you sure you want to remove the selected messages?')
163
+ end
164
+
165
+ it "should handle removing multiple selected messages where one or more is already deleted or not visible" do
166
+ generate_messages(dlq_queue_url, 3)
167
+
168
+ visit "/sqs/dlq_console"
169
+
170
+ messages = receive_messages(dlq_queue_url, {count: 3}).messages
171
+ sqs.delete_message({queue_url: dlq_queue_url, receipt_handle: messages[2].receipt_handle})
172
+ sqs.change_message_visibility_batch({
173
+ queue_url: dlq_queue_url,
174
+ entries: messages.take(2).map do |message|
175
+ {id: message.message_id, receipt_handle: message.receipt_handle, visibility_timeout: 0}
176
+ end
177
+ })
178
+ messages.each do |message|
179
+ first("#batch_action_item_#{message.message_id}").set(true)
180
+ end
181
+
182
+ click_on "Bulk Remove"
183
+
184
+ expect(first("#alert").text).to eq "One or more messages may have already been removed or is not visible."
185
+
186
+ messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 0}
187
+
188
+ visit "/sqs/overview"
189
+
190
+ match_content(page, "#{DLQ_QUEUE_NAME} 0 0 #{source_queue_url}")
191
+ end
192
+
193
+ it "should handle clicking on Bulk Remove without any selection" do
194
+ messages = generate_messages(dlq_queue_url, 3)
195
+
196
+ visit "/sqs/dlq_console"
197
+
198
+ click_on "Bulk Remove"
199
+
200
+ expect(first("#alert").text).to eq ""
201
+
202
+ messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 1}
203
+ end
204
+ end
205
+
206
+ it "Move to Source Queue should be able to move a single message to source queue" do
207
+ message_id = generate_messages(dlq_queue_url, 1).first.message_id
208
+
209
+
210
+ visit "/sqs/dlq_console"
211
+
212
+ first("#message_#{message_id}").hover
213
+
214
+ within("#message_#{message_id}") do
215
+ click_on "Move to Source Queue"
216
+ end
217
+
218
+ success_message = "Message ID: #{message_id} in Queue #{DLQ_QUEUE_NAME} was successfully moved to Source Queue #{source_queue_url}."
219
+ expect(first("#alert").text).to eq success_message
220
+ expect(page.all("#message_#{message_id}").count).to eq 0
221
+
222
+ visit "/sqs/overview"
223
+
224
+ match_content(page, "#{SOURCE_QUEUE_NAME} 1 0 N/A")
225
+ match_content(page, "#{DLQ_QUEUE_NAME} 0 0 #{source_queue_url}")
226
+
227
+ moved_message = receive_messages(source_queue_url).messages.first
228
+ expect(moved_message).to_not be_nil
229
+ expect(moved_message.body).to eq "Test_0"
230
+ expect(moved_message.attributes["ApproximateReceiveCount"]).to eq "1"
231
+ expect(moved_message.message_attributes["foo_class"].to_hash).to eq({string_value: "FooWorker", data_type: "String"})
232
+ end
233
+
234
+ describe "Bulk Move to Source Queue" do
235
+ it "should move multiple selected messages" do
236
+ messages = generate_messages(dlq_queue_url, 6)
237
+ retained_message_ids = messages.pop(2).map{|c| c.message_id}
238
+ moved_message_ids = messages.pop(4).map{|c| c.message_id}
239
+
240
+ visit "/sqs/dlq_console"
241
+
242
+ moved_message_ids.each do |message_id|
243
+ first("#batch_action_item_#{message_id}").set(true)
244
+ end
245
+
246
+ click_on "Bulk Move to Source Queue"
247
+
248
+ expect(first("#alert").text).to eq "Selected messages have been requeued successfully."
249
+
250
+ moved_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 0}
251
+ retained_message_ids.each{|message_id| expect(page.all("#message_#{message_id}").count).to eq 1}
252
+
253
+ visit "/sqs/overview"
254
+
255
+ match_content(page, "#{SOURCE_QUEUE_NAME} 4 0 N/A")
256
+ match_content(page, "#{DLQ_QUEUE_NAME} 2 0 #{source_queue_url}")
257
+
258
+ moved_messages = receive_messages(source_queue_url, {count: 4}).messages.sort_by{|c| c.body}
259
+ moved_messages.each_with_index do |moved_message, index|
260
+ expect(moved_message).to_not be_nil
261
+ expect(moved_message.body).to match "Test_#{index}"
262
+ expect(moved_message.attributes["ApproximateReceiveCount"]).to eq "1"
263
+ expect(moved_message.message_attributes["foo_class"].to_hash).to eq({string_value: "FooWorker", data_type: "String"})
264
+ end
265
+ end
266
+
267
+ it "should handle moving multiple selected messages where one or more is already deleted or not visible" do
268
+ generate_messages(dlq_queue_url, 3)
269
+
270
+ visit "/sqs/dlq_console"
271
+
272
+ messages = receive_messages(dlq_queue_url, {count: 3}).messages
273
+ sqs.delete_message({queue_url: dlq_queue_url, receipt_handle: messages[2].receipt_handle})
274
+ sqs.change_message_visibility_batch({
275
+ queue_url: dlq_queue_url,
276
+ entries: messages.take(2).map do |message|
277
+ {id: message.message_id, receipt_handle: message.receipt_handle, visibility_timeout: 0}
278
+ end
279
+ })
280
+ messages.each do |message|
281
+ first("#batch_action_item_#{message.message_id}").set(true)
282
+ end
283
+
284
+ click_on "Bulk Move to Source Queue"
285
+
286
+ expect(first("#alert").text).to eq "One or more messages may have already been requeued or is not visible."
287
+
288
+ messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 0}
289
+
290
+ visit "/sqs/overview"
291
+
292
+ match_content(page, "#{SOURCE_QUEUE_NAME} 2 0 N/A")
293
+ match_content(page, "#{DLQ_QUEUE_NAME} 0 0 #{source_queue_url}")
294
+ end
295
+
296
+ it "should handle clicking on Bulk Move to Source Queue without any selection" do
297
+ messages = generate_messages(dlq_queue_url, 3)
298
+
299
+ visit "/sqs/dlq_console"
300
+
301
+ click_on "Bulk Move to Source Queue"
302
+
303
+ expect(first("#alert").text).to eq ""
304
+
305
+ messages.each{|message| expect(page.all("#message_#{message.message_id}").count).to eq 1}
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,36 @@
1
+ RSpec.describe "Overview Page", :sqs do
2
+ it "will show Visible Messages" do
3
+ default_messages
4
+
5
+ visit "/sqs/overview"
6
+
7
+ match_content(page, "#{SOURCE_QUEUE_NAME} 5 0 N/A")
8
+ match_content(page, "#{DLQ_QUEUE_NAME} 3 0 #{source_queue_url}")
9
+ end
10
+
11
+ it "will show In Flight Messages" do
12
+ default_messages
13
+
14
+ receive_messages(source_queue_url, {count: 3})
15
+ receive_messages(dlq_queue_url, {count: 2})
16
+
17
+ visit "/sqs/overview"
18
+
19
+ match_content(page, "#{SOURCE_QUEUE_NAME} 2 3 N/A")
20
+ match_content(page, "#{DLQ_QUEUE_NAME} 1 2 #{source_queue_url}")
21
+ end
22
+
23
+ it "should be default page" do
24
+ visit "/sqs"
25
+
26
+ expect(current_path).to eq "/sqs/overview"
27
+ end
28
+
29
+ it "should gracefully handle non existent queues" do
30
+ SqsWeb.options[:queues] = ["BOGUSQUEUE"]
31
+
32
+ visit "/sqs/overview"
33
+
34
+ match_content(page, "Aws::SQS::Errors::NonExistentQueue: BOGUSQUEUE")
35
+ end
36
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,7 @@ require "codeclimate-test-reporter"
2
2
  require "byebug"
3
3
  require 'capybara-webkit'
4
4
  require 'capybara/rspec'
5
+ require 'support/shared_context.rb'
5
6
  CodeClimate::TestReporter.start
6
7
 
7
8
  ENV['RACK_ENV'] = 'development'
@@ -13,7 +13,7 @@ SqsWeb.options[:aws][:secret_access_key] = "fake"
13
13
  SqsWeb.options[:aws][:endpoint] = $fake_sqs.uri
14
14
 
15
15
  RSpec.configure do |config|
16
- config.before(:each, :sqs) { $fake_sqs.start }
16
+ config.before(:suite) { $fake_sqs.start }
17
17
  config.before(:each, :sqs) { $fake_sqs.reset }
18
18
  config.after(:suite) { $fake_sqs.stop }
19
19
  end
@@ -3,7 +3,7 @@ require "logger"
3
3
  require "sqs_web"
4
4
 
5
5
  class RailsApp < Rails::Application
6
- config.logger = Rails.logger = Logger.new($stdout)
6
+ config.logger = Rails.logger = Logger.new("test.log")
7
7
  config.secret_token = "a3d6cee7966878577a764ed273359d9e"
8
8
 
9
9
  routes.draw do
@@ -0,0 +1,54 @@
1
+ SOURCE_QUEUE_NAME = "TestSourceQueue"
2
+
3
+ DLQ_QUEUE_NAME = "TestSourceQueueDLQ"
4
+
5
+ RSpec.shared_context "sqs_setup", :sqs do
6
+ require 'support/rails_app'
7
+ require 'support/fake_sqs'
8
+
9
+ Capybara.app = RailsApp
10
+
11
+ let(:sqs) { Aws::SQS::Client.new(region: "us-east-1", credentials: Aws::Credentials.new("fake", "fake")) }
12
+
13
+ let(:source_queue_url) { sqs.get_queue_url(queue_name: SOURCE_QUEUE_NAME).queue_url }
14
+
15
+ let(:dlq_queue_url) { sqs.get_queue_url(queue_name: DLQ_QUEUE_NAME).queue_url }
16
+
17
+ before do
18
+ sqs.config.endpoint = $fake_sqs.uri
19
+ [SOURCE_QUEUE_NAME, DLQ_QUEUE_NAME].each{|queue_name| sqs.create_queue(queue_name: queue_name)}
20
+ dlq_arn = sqs.get_queue_attributes(queue_url: dlq_queue_url).attributes.fetch("QueueArn")
21
+ #Set DLQ
22
+ sqs.set_queue_attributes(
23
+ queue_url: source_queue_url,
24
+ attributes: {
25
+ "RedrivePolicy" => "{\"deadLetterTargetArn\":\"#{dlq_arn}\",\"maxReceiveCount\":10}"
26
+ }
27
+ )
28
+ SqsWeb.options[:queues] = [SOURCE_QUEUE_NAME, DLQ_QUEUE_NAME]
29
+ end
30
+
31
+ def receive_messages(queue_url, options = {count: 1})
32
+ sqs.receive_message({
33
+ queue_url: queue_url,
34
+ attribute_names: ["All"],
35
+ message_attribute_names: ["All"],
36
+ max_number_of_messages: options[:count],
37
+ wait_time_seconds: 1,
38
+ visibility_timeout: options[:visibility_timeout]
39
+ })
40
+ end
41
+
42
+ def default_messages
43
+ generate_messages(source_queue_url, 5) + generate_messages(dlq_queue_url, 3)
44
+ end
45
+
46
+ def generate_messages(queue_url, count=1)
47
+ messages = []
48
+ count.times do |time|
49
+ messages << sqs.send_message(queue_url: queue_url, message_body: "Test_#{time}",
50
+ message_attributes: {"foo_class"=> {string_value: "FooWorker", data_type: "String"}})
51
+ end
52
+ messages
53
+ end
54
+ end
data/sqs_web.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "sqs_web"
3
- gem.version = "0.0.1"
3
+ gem.version = "0.0.2"
4
4
  gem.author = "Nathaniel Ritholtz"
5
5
  gem.email = "nritholtz@gmail.com"
6
6
  gem.homepage = "https://github.com/nritholtz/sqs_web"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqs_web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathaniel Ritholtz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-18 00:00:00.000000000 Z
11
+ date: 2015-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -156,9 +156,12 @@ files:
156
156
  - lib/sqs_web/application/views/working.erb
157
157
  - lib/sqs_web/railtie.rb
158
158
  - spec/integration/app_spec.rb
159
+ - spec/integration/dlq_console_spec.rb
160
+ - spec/integration/overview_spec.rb
159
161
  - spec/spec_helper.rb
160
162
  - spec/support/fake_sqs.rb
161
163
  - spec/support/rails_app.rb
164
+ - spec/support/shared_context.rb
162
165
  - sqs_web.gemspec
163
166
  homepage: https://github.com/nritholtz/sqs_web
164
167
  licenses:
@@ -186,6 +189,9 @@ specification_version: 4
186
189
  summary: Web interface for SQS inspired by delayed_job_web
187
190
  test_files:
188
191
  - spec/integration/app_spec.rb
192
+ - spec/integration/dlq_console_spec.rb
193
+ - spec/integration/overview_spec.rb
189
194
  - spec/spec_helper.rb
190
195
  - spec/support/fake_sqs.rb
191
196
  - spec/support/rails_app.rb
197
+ - spec/support/shared_context.rb