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
14Transaction::DB = Minitest::Mock.new
15
16ReachableRedis = Minitest::Mock.new
17
18class WebTest < Minitest::Test
19 include Rack::Test::Methods
20
21 def setup
22 @cdr_repo = CDRRepo.new(db: FakeDB.new)
23 end
24
25 def app
26 Web.opts[:customer_repo] = CustomerRepo.new(
27 redis: FakeRedis.new(
28 "jmp_customer_jid-customerid" => "customer@example.com",
29 "catapult_jid-+15551234567" => "customer_customerid@component",
30 "jmp_customer_jid-customerid_low" => "customer@example.com",
31 "catapult_jid-+15551234560" => "customer_customerid_low@component",
32 "jmp_customer_jid-customerid_topup" => "customer@example.com",
33 "jmp_customer_auto_top_up_amount-customerid_topup" => "15",
34 "jmp_customer_monthly_overage_limit-customerid_topup" => "99999",
35 "catapult_jid-+15551234562" => "customer_customerid_topup@component",
36 "jmp_customer_jid-customerid_limit" => "customer@example.com",
37 "catapult_jid-+15551234561" => "customer_customerid_limit@component",
38 "jmp_customer_jid-customerid_reach" => "customerid_reach@example.com",
39 "catapult_jid-+15551234563" => "customer_customerid_reach@component",
40 "jmp_customer_jid-customerid2" => "customer2@example.com",
41 "catapult_jid-+15551230000" => "customer_customerid2@component",
42 "jmp_customer_jid-customerid_tombed" => "customer_tombed@example.com",
43 "jmp_customer_jid-bulkcustomer" => "bulk@example.com"
44 ),
45 db: FakeDB.new(
46 ["customerid"] => [{
47 "balance" => BigDecimal(10),
48 "plan_name" => "test_usd",
49 "expires_at" => Time.now + 100
50 }],
51 ["customerid2"] => [{
52 "balance" => BigDecimal(10),
53 "plan_name" => "test_usd",
54 "expires_at" => Time.now + 100
55 }],
56 ["customerid_low"] => [{
57 "balance" => BigDecimal("0.01"),
58 "plan_name" => "test_usd",
59 "expires_at" => Time.now + 100
60 }],
61 ["customerid_topup"] => [{
62 "balance" => BigDecimal("0.01"),
63 "plan_name" => "test_usd",
64 "expires_at" => Time.now + 100
65 }],
66 ["customerid_reach"] => [{
67 "balance" => BigDecimal(10),
68 "plan_name" => "test_usd",
69 "expires_at" => Time.now + 100
70 }],
71 ["customerid_limit"] => [{
72 "balance" => BigDecimal(10),
73 "plan_name" => "test_usd",
74 "expires_at" => Time.now + 100
75 }],
76 ["customerid_tombed"] => [{
77 "balance" => BigDecimal(10),
78 "plan_name" => "test_usd",
79 "expires_at" => Time.now + 100
80 }],
81 ["bulkcustomer"] => [{
82 "balance" => BigDecimal(1000),
83 "plan_name" => "test_usd",
84 "expires_at" => Time.now + 100
85 }]
86 ),
87 sgx_repo: Bwmsgsv2Repo.new(
88 redis: FakeRedis.new(
89 "catapult_fwd-+15551234567" => "xmpp:customer@example.com",
90 "catapult_fwd_timeout-customer_customerid@component" => "30",
91 "catapult_fwd-+15551234560" => "xmpp:customer@example.com",
92 "catapult_fwd_timeout-customer_customerid_low@component" => "30",
93 "catapult_fwd-+15551234561" => "xmpp:customer@example.com",
94 "catapult_fwd_timeout-customer_customerid_limit@component" => "30",
95 "catapult_fwd-+15551234563" => "xmpp:customer@example.com",
96 "catapult_fwd_timeout-customer_customerid_reach@component" => "30",
97 "catapult_fwd-+15551230000" => "xmpp:customer2@example.com",
98 "catapult_fwd_timeout-customer_customerid2@component" => "30"
99 ),
100 ibr_repo: FakeIBRRepo.new(
101 "sgx" => {
102 "customer_customerid@component" =>
103 Blather::Stanza::Iq::IBR.new.tap do |ibr|
104 ibr.phone = "+15551234567"
105 end,
106 "customer_customerid_low@component" =>
107 Blather::Stanza::Iq::IBR.new.tap do |ibr|
108 ibr.phone = "+15551234567"
109 end,
110 "customer_customerid_topup@component" =>
111 Blather::Stanza::Iq::IBR.new.tap do |ibr|
112 ibr.phone = "+15551234567"
113 end,
114 "customer_customerid_reach@component" =>
115 Blather::Stanza::Iq::IBR.new.tap do |ibr|
116 ibr.phone = "+15551234563"
117 end,
118 "customer_customerid_limit@component" =>
119 Blather::Stanza::Iq::IBR.new.tap do |ibr|
120 ibr.phone = "+15551234567"
121 end
122 }
123 )
124 )
125 )
126 Web.opts[:call_attempt_repo] = CallAttemptRepo.new(
127 redis: FakeRedis.new(
128 "jmp_customer_activater-customerid" => "+15551234567",
129 "jmp_customer_activater-customerid2" => "+15551234567",
130 "jmp_customer_activater-customerid_limit" => "+15551234567",
131 "jmp_customer_activater-customerid_low" => "+15551234567",
132 "jmp_customer_activater-customerid_topup" => "+15551234567"
133 ),
134 db: FakeDB.new(
135 ["test_usd", "+15557654321", :outbound] => [{ "rate" => 0.01 }],
136 ["test_usd", "+1911", :outbound] => [{ "rate" => 0.01 }],
137 ["test_usd", "+19116", :outbound] => [{ "rate" => 0.01 }],
138 ["test_usd", "+15557654321", :inbound] => [{ "rate" => 0.01 }],
139 ["test_usd", "+14445556666", :inbound] => [{ "rate" => 0.01 }],
140 ["test_usd", "+18001234567", :outbound] => [{ "rate" => 0.00 }],
141 ["customerid_limit"] => FakeDB::MultiResult.new(
142 [{ "a" => 1000 }],
143 [],
144 [{ "settled_amount" => 15 }]
145 ),
146 ["customerid_low"] => FakeDB::MultiResult.new(
147 [{ "a" => 1000 }],
148 [],
149 [{ "settled_amount" => 15 }]
150 ),
151 ["customerid_topup"] => FakeDB::MultiResult.new(
152 [{ "a" => 1000 }],
153 [],
154 [{ "settled_amount" => 15 }]
155 )
156 )
157 )
158 Web.opts[:cdr_repo] = @cdr_repo
159 Web.opts[:trust_level_repo] = TrustLevelRepo.new(
160 db: FakeDB.new,
161 redis: FakeRedis.new(
162 "jmp_customer_trust_level-customerid_tombed" => "Tomb"
163 )
164 )
165 Web.opts[:common_logger] = FakeLog.new
166 Web.opts[:reachability_repo] = ReachabilityRepo::Voice.new(
167 redis: ReachableRedis,
168 senders: ["+14445556666"]
169 )
170 Web.instance_variable_set(:@outbound_transfers, { "bcall" => "oocall" })
171 Web.app
172 end
173
174 def test_outbound_forwards
175 CustomerPlan::DB.expect(
176 :query_one, {}, [String, "customerid"]
177 )
178
179 post(
180 "/outbound/calls",
181 {
182 from: "ccustomerid",
183 to: "+15557654321",
184 callId: "acall"
185 }.to_json,
186 { "CONTENT_TYPE" => "application/json" }
187 )
188
189 assert last_response.ok?
190 assert_equal(
191 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
192 "<Transfer transferCallerId=\"+15551234567\">" \
193 "<PhoneNumber>+15557654321</PhoneNumber></Transfer></Response>",
194 last_response.body
195 )
196 assert_mock CustomerPlan::DB
197 end
198 em :test_outbound_forwards
199
200 def test_outbound_low_balance
201 CustomerPlan::DB.expect(
202 :query_one, {}, [String, "customerid_low"]
203 )
204
205 ExpiringLock::REDIS.expect(
206 :set,
207 EMPromise.resolve(nil),
208 ["jmp_customer_low_balance-customerid_low", Time, "EX", 604800, "NX"]
209 )
210
211 post(
212 "/outbound/calls",
213 {
214 from: "ccustomerid_low",
215 to: "+15557654321",
216 callId: "acall"
217 }.to_json,
218 { "CONTENT_TYPE" => "application/json" }
219 )
220
221 assert last_response.ok?
222 assert_equal(
223 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
224 "<SpeakSentence>Your balance of $0.01 is not enough to " \
225 "complete this call.</SpeakSentence></Response>",
226 last_response.body
227 )
228 assert_mock ExpiringLock::REDIS
229 assert_mock CustomerPlan::DB
230 end
231 em :test_outbound_low_balance
232
233 def test_outbound_low_balance_top_up
234 CustomerPlan::DB.expect(
235 :query_one, {}, [String, "customerid_topup"]
236 )
237
238 LowBalance::AutoTopUp::CreditCardSale.expect(
239 :create,
240 EMPromise.resolve(
241 OpenStruct.new(total: 15)
242 ),
243 [Customer], amount: 15
244 )
245
246 ExpiringLock::REDIS.expect(
247 :set,
248 EMPromise.resolve("OK"),
249 ["jmp_customer_low_balance-customerid_topup", Time, "EX", 604800, "NX"]
250 )
251
252 CustomerFinancials::REDIS.expect(
253 :smembers,
254 EMPromise.resolve([]),
255 ["block_credit_cards"]
256 )
257 LowBalance::AutoTopUp::REDIS.expect(
258 :exists,
259 0,
260 ["jmp_auto_top_up_block-abcd"]
261 )
262 braintree_customer = Minitest::Mock.new
263 CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer)
264 payment_methods = OpenStruct.new(payment_methods: [
265 OpenStruct.new(default?: true, unique_number_identifier: "abcd")
266 ])
267 braintree_customer.expect(
268 :find,
269 EMPromise.resolve(payment_methods),
270 ["customerid_topup"]
271 )
272
273 Customer::BLATHER.expect(
274 :<<,
275 nil,
276 [Blather::Stanza]
277 )
278
279 post(
280 "/outbound/calls",
281 {
282 from: "ccustomerid_topup",
283 to: "+15557654321",
284 callId: "acall"
285 }.to_json,
286 { "CONTENT_TYPE" => "application/json" }
287 )
288
289 assert last_response.ok?
290 assert_equal(
291 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
292 "<Transfer transferCallerId=\"+15551234567\">" \
293 "<PhoneNumber>+15557654321</PhoneNumber></Transfer></Response>",
294 last_response.body
295 )
296 assert_mock ExpiringLock::REDIS
297 assert_mock Customer::BLATHER
298 assert_mock LowBalance::AutoTopUp::CreditCardSale
299 assert_mock CustomerPlan::DB
300 end
301 em :test_outbound_low_balance_top_up
302
303 def test_outbound_unsupported
304 CustomerPlan::DB.expect(
305 :query_one, {}, [String, "customerid"]
306 )
307
308 post(
309 "/outbound/calls",
310 {
311 from: "ccustomerid",
312 to: "+95557654321",
313 callId: "acall"
314 }.to_json,
315 { "CONTENT_TYPE" => "application/json" }
316 )
317
318 assert last_response.ok?
319 assert_equal(
320 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
321 "<SpeakSentence>The number you have dialled is not " \
322 "supported on your account.</SpeakSentence></Response>",
323 last_response.body
324 )
325 assert_mock CustomerPlan::DB
326 end
327 em :test_outbound_unsupported
328
329 def test_outbound_unsupported_short_numbers_911
330 CustomerPlan::DB.expect(
331 :query_one, {}, [String, "customerid"]
332 )
333
334 post(
335 "/outbound/calls",
336 {
337 from: "ccustomerid",
338 to: "+1911",
339 callId: "acall"
340 }.to_json,
341 { "CONTENT_TYPE" => "application/json" }
342 )
343
344 assert last_response.ok?
345 assert_equal(
346 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
347 "<SpeakSentence>The number you have dialled is not " \
348 "supported on your account.</SpeakSentence></Response>",
349 last_response.body
350 )
351 assert_mock CustomerPlan::DB
352 end
353 em :test_outbound_unsupported_short_numbers_911
354
355 def test_outbound_supported_9116
356 CustomerPlan::DB.expect(
357 :query_one, {}, [String, "customerid"]
358 )
359
360 post(
361 "/outbound/calls",
362 {
363 from: "ccustomerid",
364 to: "+19116",
365 callId: "acall"
366 }.to_json,
367 { "CONTENT_TYPE" => "application/json" }
368 )
369
370 assert last_response.ok?
371 assert_equal(
372 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
373 "<Transfer transferCallerId=\"+15551234567\">" \
374 "<PhoneNumber>+19116</PhoneNumber></Transfer></Response>",
375 last_response.body
376 )
377 assert_mock CustomerPlan::DB
378 end
379 em :test_outbound_supported_9116
380
381 def test_outbound_atlimit
382 CustomerPlan::DB.expect(
383 :query_one, {}, [String, "customerid_limit"]
384 )
385
386 post(
387 "/outbound/calls",
388 {
389 from: "ccustomerid_limit",
390 to: "+15557654321",
391 callId: "acall"
392 }.to_json,
393 { "CONTENT_TYPE" => "application/json" }
394 )
395
396 assert last_response.ok?
397 assert_equal(
398 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
399 "<Gather gatherUrl=\"\/outbound/calls\" maxDigits=\"1\" " \
400 "repeatCount=\"3\"><SpeakSentence>This call will take you over " \
401 "your configured monthly overage limit.</SpeakSentence><SpeakSentence>" \
402 "Change your limit in your account settings or press 1 to accept the " \
403 "charges. You can hang up to cancel.</SpeakSentence></Gather></Response>",
404 last_response.body
405 )
406 assert_mock CustomerPlan::DB
407 end
408 em :test_outbound_atlimit
409
410 def test_outbound_no_customer
411 post(
412 "/outbound/calls",
413 {
414 from: "no_such_customer",
415 to: "+15557654321",
416 callId: "acall"
417 }.to_json,
418 { "CONTENT_TYPE" => "application/json" }
419 )
420
421 assert last_response.ok?
422 assert_equal(
423 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
424 "<SpeakSentence>Your credentials are invalid, please contact support." \
425 "</SpeakSentence></Response>",
426 last_response.body
427 )
428 end
429 em :test_outbound_no_customer
430
431 def test_outbound_atlimit_digits
432 CustomerPlan::DB.expect(
433 :query_one, {}, [String, "customerid_limit"]
434 )
435
436 post(
437 "/outbound/calls",
438 {
439 from: "ccustomerid_limit",
440 to: "+15557654321",
441 callId: "acall",
442 digits: "1"
443 }.to_json,
444 { "CONTENT_TYPE" => "application/json" }
445 )
446
447 assert last_response.ok?
448 assert_equal(
449 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
450 "<Transfer transferCallerId=\"+15551234567\">" \
451 "<PhoneNumber>+15557654321</PhoneNumber></Transfer></Response>",
452 last_response.body
453 )
454 assert_mock CustomerPlan::DB
455 end
456 em :test_outbound_atlimit_digits
457
458 def test_outbound_toll_free
459 CustomerPlan::DB.expect(
460 :query_one, {}, [String, "customerid"]
461 )
462
463 post(
464 "/outbound/calls",
465 {
466 from: "ccustomerid",
467 to: "+18001234567",
468 callId: "acall"
469 }.to_json,
470 { "CONTENT_TYPE" => "application/json" }
471 )
472
473 assert last_response.ok?
474 assert_equal(
475 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
476 "<Transfer transferCallerId=\"+15551234567\">" \
477 "<PhoneNumber>+18001234567</PhoneNumber></Transfer></Response>",
478 last_response.body
479 )
480 assert_mock CustomerPlan::DB
481 end
482 em :test_outbound_toll_free
483
484 def test_outbound_disconnect
485 CustomerPlan::DB.expect(
486 :query_one, {}, [String, "customerid"]
487 )
488
489 post(
490 "/outbound/calls/status",
491 {
492 eventType: "disconnect",
493 from: "ccustomerid",
494 to: "+15557654321",
495 callId: "acall",
496 startTime: Time.now.to_s,
497 endTime: Time.now.to_s,
498 cause: "hangup"
499 }.to_json,
500 { "CONTENT_TYPE" => "application/json" }
501 )
502
503 assert last_response.ok?
504 assert_equal("OK", last_response.body)
505 assert_mock CustomerPlan::DB
506 end
507 em :test_outbound_disconnect
508
509 def test_outbound_disconnect_tombed
510 CustomerPlan::DB.expect(
511 :query_one, {}, [String, "customerid_tombed"]
512 )
513
514 @cdr_repo.stub(:put, ->(*) { raise "put called" }) do
515 post(
516 "/outbound/calls/status",
517 {
518 eventType: "disconnect",
519 from: "ccustomerid_tombed",
520 to: "+15557654321",
521 callId: "acall",
522 startTime: Time.now.to_s,
523 endTime: Time.now.to_s,
524 cause: "hangup"
525 }.to_json,
526 { "CONTENT_TYPE" => "application/json" }
527 )
528 end
529
530 assert last_response.ok?
531 assert_equal("OK", last_response.body)
532 assert_mock CustomerPlan::DB
533 end
534 em :test_outbound_disconnect_tombed
535
536 def test_inbound
537 expected_answer_url =
538 "http://example.org/inbound/calls/acall?customer_id=customerid"
539
540 CustomerPlan::DB.expect(
541 :query_one, {}, [String, "customerid"]
542 )
543 CustomerFwd::BANDWIDTH_VOICE.expect(
544 :create_call,
545 OpenStruct.new(call_id: "ocall")
546 ) do |account, request, *|
547 assert_equal("test_bw_account", account)
548 assert_equal(expected_answer_url, request.answer_url)
549 end
550
551 post(
552 "/inbound/calls",
553 {
554 from: "+15557654321",
555 to: "+15551234567",
556 callId: "acall",
557 applicationId: "app123"
558 }.to_json,
559 { "CONTENT_TYPE" => "application/json" }
560 )
561
562 assert last_response.ok?
563 assert_equal(
564 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
565 "<Ring answerCall=\"false\" duration=\"300\" />" \
566 "</Response>",
567 last_response.body
568 )
569 assert_mock CustomerFwd::BANDWIDTH_VOICE
570 assert_mock CustomerPlan::DB
571 end
572 em :test_inbound
573
574 def test_inbound_from_reachability
575 expected_answer_url =
576 "http://example.org/inbound/calls/acall?customer_id=customerid"
577
578 CustomerPlan::DB.expect(
579 :query_one, {}, [String, "customerid"]
580 )
581 CustomerFwd::BANDWIDTH_VOICE.expect(
582 :create_call,
583 OpenStruct.new(call_id: "ocall")
584 ) do |account, request, *|
585 assert_equal("test_bw_account", account)
586 assert_equal(expected_answer_url, request.answer_url)
587 end
588
589 ReachableRedis.expect(
590 :exists,
591 EMPromise.resolve(0),
592 ["jmp_customer_reachability_voice-customerid"]
593 )
594
595 post(
596 "/inbound/calls",
597 {
598 from: "+14445556666",
599 to: "+15551234567",
600 callId: "acall",
601 applicationId: "app123"
602 }.to_json,
603 { "CONTENT_TYPE" => "application/json" }
604 )
605
606 assert last_response.ok?
607 assert_equal(
608 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
609 "<Ring answerCall=\"false\" duration=\"300\" />" \
610 "</Response>",
611 last_response.body
612 )
613 assert_mock CustomerFwd::BANDWIDTH_VOICE
614 assert_mock ReachableRedis
615 assert_mock CustomerPlan::DB
616 end
617 em :test_inbound_from_reachability
618
619 def test_inbound_no_bwmsgsv2
620 expected_answer_url =
621 "http://example.org/inbound/calls/acall?customer_id=customerid2"
622
623 CustomerPlan::DB.expect(
624 :query_one, {}, [String, "customerid2"]
625 )
626 CustomerFwd::BANDWIDTH_VOICE.expect(
627 :create_call,
628 OpenStruct.new(call_id: "ocall")
629 ) do |account, request, *|
630 assert_equal("test_bw_account", account)
631 assert_equal(expected_answer_url, request.answer_url)
632 end
633
634 post(
635 "/inbound/calls",
636 {
637 from: "+15557654321",
638 to: "+15551230000",
639 callId: "acall",
640 applicationId: "app123"
641 }.to_json,
642 { "CONTENT_TYPE" => "application/json" }
643 )
644
645 assert last_response.ok?
646 assert_equal(
647 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
648 "<Ring answerCall=\"false\" duration=\"300\" />" \
649 "</Response>",
650 last_response.body
651 )
652 assert_mock CustomerFwd::BANDWIDTH_VOICE
653 assert_mock CustomerPlan::DB
654 end
655 em :test_inbound_no_bwmsgsv2
656
657 def test_inbound_low
658 CustomerPlan::DB.expect(
659 :query_one, {}, [String, "customerid_low"]
660 )
661
662 ExpiringLock::REDIS.expect(
663 :set,
664 EMPromise.resolve(nil),
665 ["jmp_customer_low_balance-customerid_low", Time, "EX", 604800, "NX"]
666 )
667
668 post(
669 "/inbound/calls",
670 {
671 from: "+15557654321",
672 to: "+15551234560",
673 callId: "acall"
674 }.to_json,
675 { "CONTENT_TYPE" => "application/json" }
676 )
677
678 assert last_response.ok?
679 assert_equal(
680 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
681 "<Redirect redirectUrl=\"/inbound/calls/acall/voicemail\" />" \
682 "</Response>",
683 last_response.body
684 )
685 assert_mock CustomerFwd::BANDWIDTH_VOICE
686 assert_mock ExpiringLock::REDIS
687 assert_mock CustomerPlan::DB
688 end
689 em :test_inbound_low
690
691 def test_inbound_leg2
692 CustomerPlan::DB.expect(
693 :query_one, {}, [String, "customerid"]
694 )
695
696 post(
697 "/inbound/calls/acall?customer_id=customerid",
698 {
699 from: "+15557654321",
700 to: "sip:boop@example.com",
701 callId: "ocall"
702 }.to_json,
703 { "CONTENT_TYPE" => "application/json" }
704 )
705
706 assert last_response.ok?
707 assert_equal(
708 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
709 "<Tag>connected</Tag><Bridge>acall</Bridge>" \
710 "</Response>",
711 last_response.body
712 )
713 assert_mock CustomerPlan::DB
714 end
715 em :test_inbound_leg2
716
717 def test_inbound_limit_leg2
718 CustomerPlan::DB.expect(
719 :query_one, {}, [String, "customerid_limit"]
720 )
721
722 path = "/inbound/calls/acall?customer_id=customerid_limit"
723
724 post(
725 path,
726 {
727 from: "+15557654321",
728 to: "sip:boop@example.com",
729 callId: "ocall"
730 }.to_json,
731 { "CONTENT_TYPE" => "application/json" }
732 )
733
734 assert last_response.ok?
735 assert_equal(
736 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
737 "<Gather gatherUrl=\"#{path}\" maxDigits=\"1\" " \
738 "repeatCount=\"3\"><SpeakSentence>This call will take you over " \
739 "your configured monthly overage limit.</SpeakSentence><SpeakSentence>" \
740 "Change your limit in your account settings or press 1 to accept the " \
741 "charges. You can hang up to send the caller to voicemail." \
742 "</SpeakSentence></Gather></Response>",
743 last_response.body
744 )
745 assert_mock CustomerPlan::DB
746 end
747 em :test_inbound_limit_leg2
748
749 def test_inbound_limit_digits_leg2
750 CustomerPlan::DB.expect(
751 :query_one, {}, [String, "customerid_limit"]
752 )
753
754 post(
755 "/inbound/calls/acall?customer_id=customerid_limit",
756 {
757 from: "+15557654321",
758 to: "sip:boop@example.com",
759 callId: "ocall",
760 digits: "1"
761 }.to_json,
762 { "CONTENT_TYPE" => "application/json" }
763 )
764
765 assert last_response.ok?
766 assert_equal(
767 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
768 "<Tag>connected</Tag><Bridge>acall</Bridge>" \
769 "</Response>",
770 last_response.body
771 )
772 assert_mock CustomerPlan::DB
773 end
774 em :test_inbound_limit_digits_leg2
775
776 def test_inbound_limit_hangup
777 Web::BANDWIDTH_VOICE.expect(:update_call, nil) do |acc, cid, body, **kw|
778 assert_equal "test_bw_account", acc
779 assert_equal "bcall", cid
780 assert_equal(
781 "http://example.org/inbound/calls/oocall/voicemail",
782 body.redirect_url
783 )
784 assert_equal({}, kw)
785 end
786
787 post(
788 "/inbound/calls/bcall/transfer_complete",
789 {
790 from: "+15557654321",
791 to: "+15551234561",
792 callId: "oocall",
793 cause: "hangup"
794 }.to_json,
795 { "CONTENT_TYPE" => "application/json" }
796 )
797
798 assert last_response.ok?
799 assert_mock Web::BANDWIDTH_VOICE
800 end
801 em :test_inbound_limit_hangup
802
803 def test_voicemail
804 language_id = stub_request(:post, "https://api.rev.ai/languageid/v1/jobs")
805 .with(body: {
806 metadata: {
807 media_url: "https://jmp.chat/media",
808 from_jid: "+15557654321@component",
809 customer_id: "customerid"
810 }.to_json,
811 source_config: {
812 url: "https://jmp.chat/media"
813 },
814 notification_config: {
815 url: "http://example.org/inbound/calls/CALLID/voicemail/language_id"
816 }
817 }.to_json)
818
819 Customer::BLATHER.expect(
820 :<<,
821 nil,
822 [Matching.new do |stanza|
823 assert_equal "+15557654321@component", stanza.from.to_s
824 assert_equal "customer@example.com", stanza.to.to_s
825 assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
826 end]
827 )
828
829 post(
830 "/inbound/calls/CALLID/voicemail/audio",
831 {
832 "startTime" => "2021-01-01T00:00:00Z",
833 "endTime" => "2021-01-01T00:00:06Z",
834 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
835 "to" => "+15551234567",
836 "from" => "+15557654321"
837 }.to_json,
838 { "CONTENT_TYPE" => "application/json" }
839 )
840
841 assert last_response.ok?
842 assert_mock Customer::BLATHER
843 assert_requested language_id
844 end
845 em :test_voicemail
846
847 def test_anonymous_voicemail
848 language_id = stub_request(:post, "https://api.rev.ai/languageid/v1/jobs")
849 .with(body: {
850 metadata: {
851 media_url: "https://jmp.chat/media",
852 from_jid:
853 "16;phone-context=anonymous.phone-context.soprani.ca@component",
854 customer_id: "customerid"
855 }.to_json,
856 source_config: {
857 url: "https://jmp.chat/media"
858 },
859 notification_config: {
860 url: "http://example.org/inbound/calls/CALLID/voicemail/language_id"
861 }
862 }.to_json)
863
864 Customer::BLATHER.expect(
865 :<<,
866 nil,
867 [Matching.new do |stanza|
868 assert_equal(
869 "16;phone-context=anonymous.phone-context.soprani.ca@component",
870 stanza.from.to_s
871 )
872 assert_equal "customer@example.com", stanza.to.to_s
873 assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
874 end]
875 )
876
877 post(
878 "/inbound/calls/CALLID/voicemail/audio",
879 {
880 "startTime" => "2021-01-01T00:00:00Z",
881 "endTime" => "2021-01-01T00:00:06Z",
882 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
883 "to" => "+15551234567",
884 "from" => "Anonymous"
885 }.to_json,
886 { "CONTENT_TYPE" => "application/json" }
887 )
888
889 assert last_response.ok?
890 assert_mock Customer::BLATHER
891 assert_requested language_id
892 end
893 em :test_anonymous_voicemail
894
895 def test_voicemail_short
896 post(
897 "/inbound/calls/CALLID/voicemail/audio",
898 {
899 "startTime" => "2021-01-01T00:00:00Z",
900 "endTime" => "2021-01-01T00:00:05Z"
901 }.to_json,
902 { "CONTENT_TYPE" => "application/json" }
903 )
904
905 assert last_response.ok?
906 assert_mock Customer::BLATHER
907 end
908 em :test_voicemail_short
909
910 def test_voicemail_no_customer
911 post(
912 "/inbound/calls/CALLID/voicemail",
913 {
914 "startTime" => "2021-01-01T00:00:00Z",
915 "endTime" => "2021-01-01T00:00:06Z",
916 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
917 "to" => "+15551200000",
918 "from" => "+15557654321"
919 }.to_json,
920 { "CONTENT_TYPE" => "application/json" }
921 )
922
923 assert last_response.ok?
924 assert_equal(
925 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
926 "<SpeakSentence>The number you have dialled is not in service." \
927 "</SpeakSentence></Response>",
928 last_response.body
929 )
930 end
931 em :test_voicemail_no_customer
932
933 def test_inbound_from_reachability_during_reachability
934 ReachableRedis.expect(
935 :exists,
936 EMPromise.resolve(1),
937 ["jmp_customer_reachability_voice-customerid_reach"]
938 )
939 ReachableRedis.expect(
940 :incr,
941 EMPromise.resolve(1),
942 ["jmp_customer_reachability_voice-customerid_reach"]
943 )
944
945 post(
946 "/inbound/calls",
947 {
948 from: "+14445556666",
949 to: "+15551234563",
950 callId: "acall"
951 }.to_json,
952 { "CONTENT_TYPE" => "application/json" }
953 )
954
955 assert last_response.ok?
956 assert_equal(
957 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
958 "<Hangup />" \
959 "</Response>",
960 last_response.body
961 )
962 assert_mock CustomerFwd::BANDWIDTH_VOICE
963 assert_mock ReachableRedis
964 end
965 em :test_inbound_from_reachability_during_reachability
966
967 def test_bulk_order
968 create_order = stub_request(
969 :post,
970 "https://dashboard.bandwidth.com/v1.0/accounts//orders"
971 ).to_return(status: 201, body: <<~RESPONSE)
972 <OrderResponse>
973 <Order>
974 <id>test_order</id>
975 </Order>
976 </OrderResponse>
977 RESPONSE
978
979 post(
980 "/orders",
981 { quantity: 100 },
982 "HTTP_ACCEPT" => "application/json",
983 "HTTP_AUTHORIZATION" => "Bearer sometoken"
984 )
985
986 assert last_response.ok?
987 assert_equal(
988 { id: "test_order" }.to_json,
989 last_response.body
990 )
991 assert_requested create_order
992 end
993 em :test_bulk_order
994
995 def test_bulk_order_low_balance
996 post(
997 "/orders",
998 { quantity: 100 },
999 "HTTP_ACCEPT" => "application/json",
1000 "HTTP_AUTHORIZATION" => "Bearer lowtoken"
1001 )
1002
1003 assert_equal 402, last_response.status
1004 end
1005 em :test_bulk_order_low_balance
1006
1007 def test_bulk_order_bad_token
1008 post(
1009 "/orders",
1010 { quantity: 100 },
1011 "HTTP_ACCEPT" => "application/json",
1012 "HTTP_AUTHORIZATION" => "Bearer badtoken"
1013 )
1014
1015 assert_equal 401, last_response.status
1016 end
1017 em :test_bulk_order_bad_token
1018
1019 def test_order_get
1020 stub_request(
1021 :get,
1022 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1023 ).to_return(status: 200, body: <<~RESPONSE)
1024 <OrderResponse>
1025 <id>testorder</id>
1026 <OrderStatus>complete</OrderStatus>
1027 <CompletedNumbers>
1028 <TelephoneNumber>
1029 <FullNumber>5551234567</FullNumber>
1030 </TelephoneNumber>
1031 </CompletedNumbers>
1032 </OrderResponse>
1033 RESPONSE
1034
1035 Transaction::DB.expect(:transaction, nil) do |&blk|
1036 blk.call
1037 true
1038 end
1039 Transaction::DB.expect(
1040 :exec,
1041 nil,
1042 [String, Matching.new { |params|
1043 assert_equal "bulkcustomer", params[0]
1044 assert_equal "testorder", params[1]
1045 assert_equal(-1.75, params[4])
1046 assert_equal "Bulk order", params[5]
1047 }]
1048 )
1049
1050 get(
1051 "/orders/testorder",
1052 "",
1053 "HTTP_ACCEPT" => "application/json",
1054 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1055 )
1056
1057 assert last_response.ok?
1058 assert_equal(
1059 { id: "testorder", status: "complete", tels: ["+15551234567"] }.to_json,
1060 last_response.body
1061 )
1062 assert_mock Transaction::DB
1063 end
1064 em :test_order_get
1065
1066 def test_order_get_multi
1067 stub_request(
1068 :get,
1069 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1070 ).to_return(status: 200, body: <<~RESPONSE)
1071 <OrderResponse>
1072 <id>testorder</id>
1073 <OrderStatus>complete</OrderStatus>
1074 <CompletedNumbers>
1075 <TelephoneNumber>
1076 <FullNumber>5551234567</FullNumber>
1077 </TelephoneNumber>
1078 <TelephoneNumber>
1079 <FullNumber>5551234568</FullNumber>
1080 </TelephoneNumber>
1081 </CompletedNumbers>
1082 </OrderResponse>
1083 RESPONSE
1084
1085 Transaction::DB.expect(:transaction, nil) do |&blk|
1086 blk.call
1087 true
1088 end
1089 Transaction::DB.expect(
1090 :exec,
1091 nil,
1092 [String, Matching.new { |params|
1093 assert_equal "bulkcustomer", params[0]
1094 assert_equal "testorder", params[1]
1095 assert_equal (-1.75 * 2), params[4]
1096 assert_equal "Bulk order", params[5]
1097 }]
1098 )
1099
1100 get(
1101 "/orders/testorder",
1102 "",
1103 "HTTP_ACCEPT" => "application/json",
1104 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1105 )
1106
1107 assert last_response.ok?
1108 assert_equal(
1109 {
1110 id: "testorder",
1111 status: "complete",
1112 tels: ["+15551234567", "+15551234568"]
1113 }.to_json,
1114 last_response.body
1115 )
1116 assert_mock Transaction::DB
1117 end
1118 em :test_order_get_multi
1119
1120 def test_order_get_received
1121 stub_request(
1122 :get,
1123 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1124 ).to_return(status: 200, body: <<~RESPONSE)
1125 <OrderResponse>
1126 <id>testorder</id>
1127 <OrderStatus>received</OrderStatus>
1128 </OrderResponse>
1129 RESPONSE
1130
1131 get(
1132 "/orders/testorder",
1133 "",
1134 "HTTP_ACCEPT" => "application/json",
1135 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1136 )
1137
1138 assert last_response.ok?
1139 assert_equal(
1140 { id: "testorder", status: "received" }.to_json,
1141 last_response.body
1142 )
1143 end
1144 em :test_order_get_received
1145
1146 def test_order_get_failed
1147 stub_request(
1148 :get,
1149 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1150 ).to_return(status: 200, body: <<~RESPONSE)
1151 <OrderResponse>
1152 <id>testorder</id>
1153 <OrderStatus>failed</OrderStatus>
1154 </OrderResponse>
1155 RESPONSE
1156
1157 get(
1158 "/orders/testorder",
1159 "",
1160 "HTTP_ACCEPT" => "application/json",
1161 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1162 )
1163
1164 assert last_response.ok?
1165 assert_equal(
1166 { id: "testorder", status: "failed" }.to_json,
1167 last_response.body
1168 )
1169 end
1170 em :test_order_get_failed
1171
1172 def test_order_get_bad_token
1173 get(
1174 "/orders/testorder",
1175 "",
1176 "HTTP_ACCEPT" => "application/json",
1177 "HTTP_AUTHORIZATION" => "Bearer badtoken"
1178 )
1179
1180 assert_equal 401, last_response.status
1181 end
1182 em :test_order_get_bad_token
1183
1184 def test_delete_tel
1185 stub_request(
1186 :get,
1187 "https://dashboard.bandwidth.com/v1.0/tns/+15551234567/tndetails"
1188 ).to_return(status: 200, body: <<~RESPONSE)
1189 <Response>
1190 <TelephoneNumberDetails>
1191 <SipPeer><PeerId>bulkpeer</PeerId></SipPeer>
1192 </TelephoneNumberDetails>
1193 </Response>
1194 RESPONSE
1195
1196 req = stub_request(
1197 :post,
1198 "https://dashboard.bandwidth.com/v1.0/accounts//disconnects"
1199 ).to_return(status: 200, body: "")
1200
1201 delete(
1202 "/orders/tels/+15551234567",
1203 "",
1204 "HTTP_ACCEPT" => "application/json",
1205 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1206 )
1207
1208 assert last_response.ok?
1209 assert_requested req
1210 end
1211 em :test_delete_tel
1212
1213 def test_delete_tel_not_yours
1214 stub_request(
1215 :get,
1216 "https://dashboard.bandwidth.com/v1.0/tns/+15551234567/tndetails"
1217 ).to_return(status: 200, body: <<~RESPONSE)
1218 <Response>
1219 <TelephoneNumberDetails>
1220 <SipPeer><PeerId>mainpeer</PeerId></SipPeer>
1221 </TelephoneNumberDetails>
1222 </Response>
1223 RESPONSE
1224
1225 delete(
1226 "/orders/tels/+15551234567",
1227 "",
1228 "HTTP_ACCEPT" => "application/json",
1229 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1230 )
1231
1232 assert_equal 401, last_response.status
1233 end
1234 em :test_delete_tel_not_yours
1235
1236 def test_delete_tel_bad_token
1237 delete(
1238 "/orders/tels/+15551234567",
1239 "",
1240 "HTTP_ACCEPT" => "application/json",
1241 "HTTP_AUTHORIZATION" => "Bearer badtoken"
1242 )
1243
1244 assert_equal 401, last_response.status
1245 end
1246 em :test_delete_tel_bad_token
1247end