1# frozen_string_literal: true
2
3require "rack/test"
4require "test_helper"
5require "bwmsgsv2_repo"
6require "customer_repo"
7require_relative "../web"
8
9ExpiringLock::REDIS = Minitest::Mock.new
10Customer::BLATHER = Minitest::Mock.new
11CustomerFwd::BANDWIDTH_VOICE = Minitest::Mock.new
12Web::BANDWIDTH_VOICE = Minitest::Mock.new
13LowBalance::AutoTopUp::CreditCardSale = Minitest::Mock.new
14
15ReachableRedis = Minitest::Mock.new
16
17class WebTest < Minitest::Test
18 include Rack::Test::Methods
19
20 def app
21 Web.opts[:customer_repo] = CustomerRepo.new(
22 redis: FakeRedis.new(
23 "jmp_customer_jid-customerid" => "customer@example.com",
24 "catapult_jid-+15551234567" => "customer_customerid@component",
25 "jmp_customer_jid-customerid_low" => "customer@example.com",
26 "catapult_jid-+15551234560" => "customer_customerid_low@component",
27 "jmp_customer_jid-customerid_topup" => "customer@example.com",
28 "jmp_customer_auto_top_up_amount-customerid_topup" => "15",
29 "jmp_customer_monthly_overage_limit-customerid_topup" => "99999",
30 "catapult_jid-+15551234562" => "customer_customerid_topup@component",
31 "jmp_customer_jid-customerid_limit" => "customer@example.com",
32 "catapult_jid-+15551234561" => "customer_customerid_limit@component",
33 "jmp_customer_jid-customerid_reach" => "customerid_reach@example.com",
34 "catapult_jid-+15551234563" => "customer_customerid_reach@component",
35 "jmp_customer_jid-customerid2" => "customer2@example.com",
36 "catapult_jid-+15551230000" => "customer_customerid2@component"
37 ),
38 db: FakeDB.new(
39 ["customerid"] => [{
40 "balance" => BigDecimal(10),
41 "plan_name" => "test_usd",
42 "expires_at" => Time.now + 100
43 }],
44 ["customerid2"] => [{
45 "balance" => BigDecimal(10),
46 "plan_name" => "test_usd",
47 "expires_at" => Time.now + 100
48 }],
49 ["customerid_low"] => [{
50 "balance" => BigDecimal("0.01"),
51 "plan_name" => "test_usd",
52 "expires_at" => Time.now + 100
53 }],
54 ["customerid_topup"] => [{
55 "balance" => BigDecimal("0.01"),
56 "plan_name" => "test_usd",
57 "expires_at" => Time.now + 100
58 }],
59 ["customerid_reach"] => [{
60 "balance" => BigDecimal(10),
61 "plan_name" => "test_usd",
62 "expires_at" => Time.now + 100
63 }],
64 ["customerid_limit"] => [{
65 "balance" => BigDecimal(10),
66 "plan_name" => "test_usd",
67 "expires_at" => Time.now + 100
68 }]
69 ),
70 sgx_repo: Bwmsgsv2Repo.new(
71 redis: FakeRedis.new(
72 "catapult_fwd-+15551234567" => "xmpp:customer@example.com",
73 "catapult_fwd_timeout-customer_customerid@component" => "30",
74 "catapult_fwd-+15551234560" => "xmpp:customer@example.com",
75 "catapult_fwd_timeout-customer_customerid_low@component" => "30",
76 "catapult_fwd-+15551234561" => "xmpp:customer@example.com",
77 "catapult_fwd_timeout-customer_customerid_limit@component" => "30",
78 "catapult_fwd-+15551234563" => "xmpp:customer@example.com",
79 "catapult_fwd_timeout-customer_customerid_reach@component" => "30",
80 "catapult_fwd-+15551230000" => "xmpp:customer2@example.com",
81 "catapult_fwd_timeout-customer_customerid2@component" => "30"
82 ),
83 ibr_repo: FakeIBRRepo.new(
84 "sgx" => {
85 "customer_customerid@component" =>
86 Blather::Stanza::Iq::IBR.new.tap do |ibr|
87 ibr.phone = "+15551234567"
88 end,
89 "customer_customerid_low@component" =>
90 Blather::Stanza::Iq::IBR.new.tap do |ibr|
91 ibr.phone = "+15551234567"
92 end,
93 "customer_customerid_topup@component" =>
94 Blather::Stanza::Iq::IBR.new.tap do |ibr|
95 ibr.phone = "+15551234567"
96 end,
97 "customer_customerid_reach@component" =>
98 Blather::Stanza::Iq::IBR.new.tap do |ibr|
99 ibr.phone = "+15551234563"
100 end,
101 "customer_customerid_limit@component" =>
102 Blather::Stanza::Iq::IBR.new.tap do |ibr|
103 ibr.phone = "+15551234567"
104 end
105 }
106 )
107 )
108 )
109 Web.opts[:call_attempt_repo] = CallAttemptRepo.new(
110 redis: FakeRedis.new,
111 db: FakeDB.new(
112 ["test_usd", "+15557654321", :outbound] => [{ "rate" => 0.01 }],
113 ["test_usd", "+1911", :outbound] => [{ "rate" => 0.01 }],
114 ["test_usd", "+19116", :outbound] => [{ "rate" => 0.01 }],
115 ["test_usd", "+15557654321", :inbound] => [{ "rate" => 0.01 }],
116 ["test_usd", "+14445556666", :inbound] => [{ "rate" => 0.01 }],
117 ["test_usd", "+18001234567", :outbound] => [{ "rate" => 0.00 }],
118 ["customerid_limit"] => FakeDB::MultiResult.new(
119 [{ "a" => 1000 }],
120 [{ "settled_amount" => 15 }]
121 ),
122 ["customerid_low"] => FakeDB::MultiResult.new(
123 [{ "a" => 1000 }],
124 [{ "settled_amount" => 15 }]
125 ),
126 ["customerid_topup"] => FakeDB::MultiResult.new(
127 [{ "a" => 1000 }],
128 [{ "settled_amount" => 15 }]
129 )
130 )
131 )
132 Web.opts[:cdr_repo] = CDRRepo.new(db: FakeDB.new)
133 Web.opts[:common_logger] = FakeLog.new
134 Web.opts[:reachability_repo] = ReachabilityRepo::Voice.new(
135 redis: ReachableRedis,
136 senders: ["+14445556666"]
137 )
138 Web.instance_variable_set(:@outbound_transfers, { "bcall" => "oocall" })
139 Web.app
140 end
141
142 def test_outbound_forwards
143 post(
144 "/outbound/calls",
145 {
146 from: "ccustomerid",
147 to: "+15557654321",
148 callId: "acall"
149 }.to_json,
150 { "CONTENT_TYPE" => "application/json" }
151 )
152
153 assert last_response.ok?
154 assert_equal(
155 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
156 "<Transfer transferCallerId=\"+15551234567\">" \
157 "<PhoneNumber>+15557654321</PhoneNumber></Transfer></Response>",
158 last_response.body
159 )
160 end
161 em :test_outbound_forwards
162
163 def test_outbound_low_balance
164 ExpiringLock::REDIS.expect(
165 :set,
166 EMPromise.resolve(nil),
167 ["jmp_customer_low_balance-customerid_low", Time, "EX", 604800, "NX"]
168 )
169
170 post(
171 "/outbound/calls",
172 {
173 from: "ccustomerid_low",
174 to: "+15557654321",
175 callId: "acall"
176 }.to_json,
177 { "CONTENT_TYPE" => "application/json" }
178 )
179
180 assert last_response.ok?
181 assert_equal(
182 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
183 "<SpeakSentence>Your balance of $0.01 is not enough to " \
184 "complete this call.</SpeakSentence></Response>",
185 last_response.body
186 )
187 assert_mock ExpiringLock::REDIS
188 end
189 em :test_outbound_low_balance
190
191 def test_outbound_low_balance_top_up
192 LowBalance::AutoTopUp::CreditCardSale.expect(
193 :create,
194 EMPromise.resolve(
195 OpenStruct.new(total: 15)
196 ),
197 [Customer], amount: 15
198 )
199
200 ExpiringLock::REDIS.expect(
201 :set,
202 EMPromise.resolve("OK"),
203 ["jmp_customer_low_balance-customerid_topup", Time, "EX", 604800, "NX"]
204 )
205
206 CustomerFinancials::REDIS.expect(
207 :smembers,
208 EMPromise.resolve([]),
209 ["block_credit_cards"]
210 )
211 LowBalance::AutoTopUp::REDIS.expect(
212 :exists,
213 0,
214 ["jmp_auto_top_up_block-abcd"]
215 )
216 braintree_customer = Minitest::Mock.new
217 CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer)
218 payment_methods = OpenStruct.new(payment_methods: [
219 OpenStruct.new(default?: true, unique_number_identifier: "abcd")
220 ])
221 braintree_customer.expect(
222 :find,
223 EMPromise.resolve(payment_methods),
224 ["customerid_topup"]
225 )
226
227 Customer::BLATHER.expect(
228 :<<,
229 nil,
230 [Blather::Stanza]
231 )
232
233 post(
234 "/outbound/calls",
235 {
236 from: "ccustomerid_topup",
237 to: "+15557654321",
238 callId: "acall"
239 }.to_json,
240 { "CONTENT_TYPE" => "application/json" }
241 )
242
243 assert last_response.ok?
244 assert_equal(
245 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
246 "<Transfer transferCallerId=\"+15551234567\">" \
247 "<PhoneNumber>+15557654321</PhoneNumber></Transfer></Response>",
248 last_response.body
249 )
250 assert_mock ExpiringLock::REDIS
251 assert_mock Customer::BLATHER
252 assert_mock LowBalance::AutoTopUp::CreditCardSale
253 end
254 em :test_outbound_low_balance_top_up
255
256 def test_outbound_unsupported
257 post(
258 "/outbound/calls",
259 {
260 from: "ccustomerid",
261 to: "+95557654321",
262 callId: "acall"
263 }.to_json,
264 { "CONTENT_TYPE" => "application/json" }
265 )
266
267 assert last_response.ok?
268 assert_equal(
269 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
270 "<SpeakSentence>The number you have dialled is not " \
271 "supported on your account.</SpeakSentence></Response>",
272 last_response.body
273 )
274 end
275 em :test_outbound_unsupported
276
277 def test_outbound_unsupported_short_numbers_911
278 post(
279 "/outbound/calls",
280 {
281 from: "ccustomerid",
282 to: "+1911",
283 callId: "acall"
284 }.to_json,
285 { "CONTENT_TYPE" => "application/json" }
286 )
287
288 assert last_response.ok?
289 assert_equal(
290 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
291 "<SpeakSentence>The number you have dialled is not " \
292 "supported on your account.</SpeakSentence></Response>",
293 last_response.body
294 )
295 end
296 em :test_outbound_unsupported_short_numbers_911
297
298 def test_outbound_supported_9116
299 post(
300 "/outbound/calls",
301 {
302 from: "ccustomerid",
303 to: "+19116",
304 callId: "acall"
305 }.to_json,
306 { "CONTENT_TYPE" => "application/json" }
307 )
308
309 assert last_response.ok?
310 assert_equal(
311 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
312 "<Transfer transferCallerId=\"+15551234567\">" \
313 "<PhoneNumber>+19116</PhoneNumber></Transfer></Response>",
314 last_response.body
315 )
316 end
317 em :test_outbound_supported_9116
318
319 def test_outbound_atlimit
320 post(
321 "/outbound/calls",
322 {
323 from: "ccustomerid_limit",
324 to: "+15557654321",
325 callId: "acall"
326 }.to_json,
327 { "CONTENT_TYPE" => "application/json" }
328 )
329
330 assert last_response.ok?
331 assert_equal(
332 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
333 "<Gather gatherUrl=\"\/outbound/calls\" maxDigits=\"1\" " \
334 "repeatCount=\"3\"><SpeakSentence>This call will take you over " \
335 "your configured monthly overage limit.</SpeakSentence><SpeakSentence>" \
336 "Change your limit in your account settings or press 1 to accept the " \
337 "charges. You can hang up to cancel.</SpeakSentence></Gather></Response>",
338 last_response.body
339 )
340 end
341 em :test_outbound_atlimit
342
343 def test_outbound_no_customer
344 post(
345 "/outbound/calls",
346 {
347 from: "no_such_customer",
348 to: "+15557654321",
349 callId: "acall"
350 }.to_json,
351 { "CONTENT_TYPE" => "application/json" }
352 )
353
354 assert last_response.ok?
355 assert_equal(
356 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
357 "<SpeakSentence>Your credentials are invalid, please contact support." \
358 "</SpeakSentence></Response>",
359 last_response.body
360 )
361 end
362 em :test_outbound_no_customer
363
364 def test_outbound_atlimit_digits
365 post(
366 "/outbound/calls",
367 {
368 from: "ccustomerid_limit",
369 to: "+15557654321",
370 callId: "acall",
371 digits: "1"
372 }.to_json,
373 { "CONTENT_TYPE" => "application/json" }
374 )
375
376 assert last_response.ok?
377 assert_equal(
378 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
379 "<Transfer transferCallerId=\"+15551234567\">" \
380 "<PhoneNumber>+15557654321</PhoneNumber></Transfer></Response>",
381 last_response.body
382 )
383 end
384 em :test_outbound_atlimit_digits
385
386 def test_outbound_toll_free
387 post(
388 "/outbound/calls",
389 {
390 from: "ccustomerid",
391 to: "+18001234567",
392 callId: "acall"
393 }.to_json,
394 { "CONTENT_TYPE" => "application/json" }
395 )
396
397 assert last_response.ok?
398 assert_equal(
399 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
400 "<Transfer transferCallerId=\"+15551234567\">" \
401 "<PhoneNumber>+18001234567</PhoneNumber></Transfer></Response>",
402 last_response.body
403 )
404 end
405 em :test_outbound_toll_free
406
407 def test_outbound_disconnect
408 post(
409 "/outbound/calls/status",
410 {
411 eventType: "disconnect",
412 from: "ccustomerid",
413 to: "+15557654321",
414 callId: "acall",
415 startTime: Time.now.to_s,
416 endTime: Time.now.to_s,
417 cause: "hangup"
418 }.to_json,
419 { "CONTENT_TYPE" => "application/json" }
420 )
421
422 assert last_response.ok?
423 assert_equal("OK", last_response.body)
424 end
425 em :test_outbound_disconnect
426
427 def test_inbound
428 CustomerFwd::BANDWIDTH_VOICE.expect(
429 :create_call,
430 OpenStruct.new(data: OpenStruct.new(call_id: "ocall")),
431 ["test_bw_account"],
432 body: Matching.new do |arg|
433 assert_equal(
434 "http://example.org/inbound/calls/acall?customer_id=customerid",
435 arg.answer_url
436 )
437 end
438 )
439
440 post(
441 "/inbound/calls",
442 {
443 from: "+15557654321",
444 to: "+15551234567",
445 callId: "acall"
446 }.to_json,
447 { "CONTENT_TYPE" => "application/json" }
448 )
449
450 assert last_response.ok?
451 assert_equal(
452 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
453 "<Ring answerCall=\"false\" duration=\"300\" />" \
454 "</Response>",
455 last_response.body
456 )
457 assert_mock CustomerFwd::BANDWIDTH_VOICE
458 end
459 em :test_inbound
460
461 def test_inbound_from_reachability
462 CustomerFwd::BANDWIDTH_VOICE.expect(
463 :create_call,
464 OpenStruct.new(data: OpenStruct.new(call_id: "ocall")),
465 ["test_bw_account"],
466 body: Matching.new do |arg|
467 assert_equal(
468 "http://example.org/inbound/calls/acall?customer_id=customerid",
469 arg.answer_url
470 )
471 end
472 )
473
474 ReachableRedis.expect(
475 :exists,
476 EMPromise.resolve(0),
477 ["jmp_customer_reachability_voice-customerid"]
478 )
479
480 post(
481 "/inbound/calls",
482 {
483 from: "+14445556666",
484 to: "+15551234567",
485 callId: "acall"
486 }.to_json,
487 { "CONTENT_TYPE" => "application/json" }
488 )
489
490 assert last_response.ok?
491 assert_equal(
492 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
493 "<Ring answerCall=\"false\" duration=\"300\" />" \
494 "</Response>",
495 last_response.body
496 )
497 assert_mock CustomerFwd::BANDWIDTH_VOICE
498 assert_mock ReachableRedis
499 end
500 em :test_inbound_from_reachability
501
502 def test_inbound_no_bwmsgsv2
503 CustomerFwd::BANDWIDTH_VOICE.expect(
504 :create_call,
505 OpenStruct.new(data: OpenStruct.new(call_id: "ocall")),
506 ["test_bw_account"],
507 body: Matching.new do |arg|
508 assert_equal(
509 "http://example.org/inbound/calls/acall?customer_id=customerid2",
510 arg.answer_url
511 )
512 end
513 )
514
515 post(
516 "/inbound/calls",
517 {
518 from: "+15557654321",
519 to: "+15551230000",
520 callId: "acall"
521 }.to_json,
522 { "CONTENT_TYPE" => "application/json" }
523 )
524
525 assert last_response.ok?
526 assert_equal(
527 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
528 "<Ring answerCall=\"false\" duration=\"300\" />" \
529 "</Response>",
530 last_response.body
531 )
532 assert_mock CustomerFwd::BANDWIDTH_VOICE
533 end
534 em :test_inbound_no_bwmsgsv2
535
536 def test_inbound_low
537 ExpiringLock::REDIS.expect(
538 :set,
539 EMPromise.resolve(nil),
540 ["jmp_customer_low_balance-customerid_low", Time, "EX", 604800, "NX"]
541 )
542
543 post(
544 "/inbound/calls",
545 {
546 from: "+15557654321",
547 to: "+15551234560",
548 callId: "acall"
549 }.to_json,
550 { "CONTENT_TYPE" => "application/json" }
551 )
552
553 assert last_response.ok?
554 assert_equal(
555 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
556 "<Redirect redirectUrl=\"/inbound/calls/acall/voicemail\" />" \
557 "</Response>",
558 last_response.body
559 )
560 assert_mock CustomerFwd::BANDWIDTH_VOICE
561 assert_mock ExpiringLock::REDIS
562 end
563 em :test_inbound_low
564
565 def test_inbound_leg2
566 post(
567 "/inbound/calls/acall?customer_id=customerid",
568 {
569 from: "+15557654321",
570 to: "sip:boop@example.com",
571 callId: "ocall"
572 }.to_json,
573 { "CONTENT_TYPE" => "application/json" }
574 )
575
576 assert last_response.ok?
577 assert_equal(
578 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
579 "<Tag>connected</Tag><Bridge>acall</Bridge>" \
580 "</Response>",
581 last_response.body
582 )
583 end
584 em :test_inbound_leg2
585
586 def test_inbound_limit_leg2
587 path = "/inbound/calls/acall?customer_id=customerid_limit"
588
589 post(
590 path,
591 {
592 from: "+15557654321",
593 to: "sip:boop@example.com",
594 callId: "ocall"
595 }.to_json,
596 { "CONTENT_TYPE" => "application/json" }
597 )
598
599 assert last_response.ok?
600 assert_equal(
601 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
602 "<Gather gatherUrl=\"#{path}\" maxDigits=\"1\" " \
603 "repeatCount=\"3\"><SpeakSentence>This call will take you over " \
604 "your configured monthly overage limit.</SpeakSentence><SpeakSentence>" \
605 "Change your limit in your account settings or press 1 to accept the " \
606 "charges. You can hang up to send the caller to voicemail." \
607 "</SpeakSentence></Gather></Response>",
608 last_response.body
609 )
610 end
611 em :test_inbound_limit_leg2
612
613 def test_inbound_limit_digits_leg2
614 post(
615 "/inbound/calls/acall?customer_id=customerid_limit",
616 {
617 from: "+15557654321",
618 to: "sip:boop@example.com",
619 callId: "ocall",
620 digits: "1"
621 }.to_json,
622 { "CONTENT_TYPE" => "application/json" }
623 )
624
625 assert last_response.ok?
626 assert_equal(
627 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
628 "<Tag>connected</Tag><Bridge>acall</Bridge>" \
629 "</Response>",
630 last_response.body
631 )
632 end
633 em :test_inbound_limit_digits_leg2
634
635 def test_inbound_limit_hangup
636 Web::BANDWIDTH_VOICE.expect(
637 :modify_call,
638 nil,
639 [
640 "test_bw_account",
641 "bcall"
642 ],
643 body: Matching.new do |arg|
644 assert_equal(
645 "http://example.org/inbound/calls/oocall/voicemail",
646 arg.redirect_url
647 )
648 end
649 )
650
651 post(
652 "/inbound/calls/bcall/transfer_complete",
653 {
654 from: "+15557654321",
655 to: "+15551234561",
656 callId: "oocall",
657 cause: "hangup"
658 }.to_json,
659 { "CONTENT_TYPE" => "application/json" }
660 )
661
662 assert last_response.ok?
663 assert_mock Web::BANDWIDTH_VOICE
664 end
665 em :test_inbound_limit_hangup
666
667 def test_voicemail
668 language_id = stub_request(:post, "https://api.rev.ai/languageid/v1/jobs")
669 .with(body: {
670 metadata: {
671 media_url: "https://jmp.chat/media",
672 from_jid: "+15557654321@component",
673 customer_id: "customerid"
674 }.to_json,
675 source_config: {
676 url: "https://jmp.chat/media"
677 },
678 notification_config: {
679 url: "http://example.org/inbound/calls/CALLID/voicemail/language_id"
680 }
681 }.to_json)
682
683 Customer::BLATHER.expect(
684 :<<,
685 nil,
686 [Matching.new do |stanza|
687 assert_equal "+15557654321@component", stanza.from.to_s
688 assert_equal "customer@example.com", stanza.to.to_s
689 assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
690 end]
691 )
692
693 post(
694 "/inbound/calls/CALLID/voicemail/audio",
695 {
696 "startTime" => "2021-01-01T00:00:00Z",
697 "endTime" => "2021-01-01T00:00:06Z",
698 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
699 "to" => "+15551234567",
700 "from" => "+15557654321"
701 }.to_json,
702 { "CONTENT_TYPE" => "application/json" }
703 )
704
705 assert last_response.ok?
706 assert_mock Customer::BLATHER
707 assert_requested language_id
708 end
709 em :test_voicemail
710
711 def test_anonymous_voicemail
712 language_id = stub_request(:post, "https://api.rev.ai/languageid/v1/jobs")
713 .with(body: {
714 metadata: {
715 media_url: "https://jmp.chat/media",
716 from_jid:
717 "16;phone-context=anonymous.phone-context.soprani.ca@component",
718 customer_id: "customerid"
719 }.to_json,
720 source_config: {
721 url: "https://jmp.chat/media"
722 },
723 notification_config: {
724 url: "http://example.org/inbound/calls/CALLID/voicemail/language_id"
725 }
726 }.to_json)
727
728 Customer::BLATHER.expect(
729 :<<,
730 nil,
731 [Matching.new do |stanza|
732 assert_equal(
733 "16;phone-context=anonymous.phone-context.soprani.ca@component",
734 stanza.from.to_s
735 )
736 assert_equal "customer@example.com", stanza.to.to_s
737 assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
738 end]
739 )
740
741 post(
742 "/inbound/calls/CALLID/voicemail/audio",
743 {
744 "startTime" => "2021-01-01T00:00:00Z",
745 "endTime" => "2021-01-01T00:00:06Z",
746 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
747 "to" => "+15551234567",
748 "from" => "Anonymous"
749 }.to_json,
750 { "CONTENT_TYPE" => "application/json" }
751 )
752
753 assert last_response.ok?
754 assert_mock Customer::BLATHER
755 assert_requested language_id
756 end
757 em :test_anonymous_voicemail
758
759 def test_voicemail_short
760 post(
761 "/inbound/calls/CALLID/voicemail/audio",
762 {
763 "startTime" => "2021-01-01T00:00:00Z",
764 "endTime" => "2021-01-01T00:00:05Z"
765 }.to_json,
766 { "CONTENT_TYPE" => "application/json" }
767 )
768
769 assert last_response.ok?
770 assert_mock Customer::BLATHER
771 end
772 em :test_voicemail_short
773
774 def test_voicemail_no_customer
775 post(
776 "/inbound/calls/CALLID/voicemail",
777 {
778 "startTime" => "2021-01-01T00:00:00Z",
779 "endTime" => "2021-01-01T00:00:06Z",
780 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
781 "to" => "+15551200000",
782 "from" => "+15557654321"
783 }.to_json,
784 { "CONTENT_TYPE" => "application/json" }
785 )
786
787 assert last_response.ok?
788 assert_equal(
789 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
790 "<SpeakSentence>The number you have dialled is not in service." \
791 "</SpeakSentence></Response>",
792 last_response.body
793 )
794 end
795 em :test_voicemail_no_customer
796
797 def test_inbound_from_reachability_during_reachability
798 ReachableRedis.expect(
799 :exists,
800 EMPromise.resolve(1),
801 ["jmp_customer_reachability_voice-customerid_reach"]
802 )
803 ReachableRedis.expect(
804 :incr,
805 EMPromise.resolve(1),
806 ["jmp_customer_reachability_voice-customerid_reach"]
807 )
808
809 post(
810 "/inbound/calls",
811 {
812 from: "+14445556666",
813 to: "+15551234563",
814 callId: "acall"
815 }.to_json,
816 { "CONTENT_TYPE" => "application/json" }
817 )
818
819 assert last_response.ok?
820 assert_equal(
821 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
822 "<Hangup />" \
823 "</Response>",
824 last_response.body
825 )
826 assert_mock CustomerFwd::BANDWIDTH_VOICE
827 assert_mock ReachableRedis
828 end
829 em :test_inbound_from_reachability_during_reachability
830end