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(
778 :update_call,
779 nil,
780 [
781 "test_bw_account",
782 "bcall",
783 Matching.new do |arg|
784 assert_equal(
785 "http://example.org/inbound/calls/oocall/voicemail",
786 arg.redirect_url
787 )
788 end
789 ]
790 )
791
792 post(
793 "/inbound/calls/bcall/transfer_complete",
794 {
795 from: "+15557654321",
796 to: "+15551234561",
797 callId: "oocall",
798 cause: "hangup"
799 }.to_json,
800 { "CONTENT_TYPE" => "application/json" }
801 )
802
803 assert last_response.ok?
804 assert_mock Web::BANDWIDTH_VOICE
805 end
806 em :test_inbound_limit_hangup
807
808 def test_voicemail
809 language_id = stub_request(:post, "https://api.rev.ai/languageid/v1/jobs")
810 .with(body: {
811 metadata: {
812 media_url: "https://jmp.chat/media",
813 from_jid: "+15557654321@component",
814 customer_id: "customerid"
815 }.to_json,
816 source_config: {
817 url: "https://jmp.chat/media"
818 },
819 notification_config: {
820 url: "http://example.org/inbound/calls/CALLID/voicemail/language_id"
821 }
822 }.to_json)
823
824 Customer::BLATHER.expect(
825 :<<,
826 nil,
827 [Matching.new do |stanza|
828 assert_equal "+15557654321@component", stanza.from.to_s
829 assert_equal "customer@example.com", stanza.to.to_s
830 assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
831 end]
832 )
833
834 post(
835 "/inbound/calls/CALLID/voicemail/audio",
836 {
837 "startTime" => "2021-01-01T00:00:00Z",
838 "endTime" => "2021-01-01T00:00:06Z",
839 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
840 "to" => "+15551234567",
841 "from" => "+15557654321"
842 }.to_json,
843 { "CONTENT_TYPE" => "application/json" }
844 )
845
846 assert last_response.ok?
847 assert_mock Customer::BLATHER
848 assert_requested language_id
849 end
850 em :test_voicemail
851
852 def test_anonymous_voicemail
853 language_id = stub_request(:post, "https://api.rev.ai/languageid/v1/jobs")
854 .with(body: {
855 metadata: {
856 media_url: "https://jmp.chat/media",
857 from_jid:
858 "16;phone-context=anonymous.phone-context.soprani.ca@component",
859 customer_id: "customerid"
860 }.to_json,
861 source_config: {
862 url: "https://jmp.chat/media"
863 },
864 notification_config: {
865 url: "http://example.org/inbound/calls/CALLID/voicemail/language_id"
866 }
867 }.to_json)
868
869 Customer::BLATHER.expect(
870 :<<,
871 nil,
872 [Matching.new do |stanza|
873 assert_equal(
874 "16;phone-context=anonymous.phone-context.soprani.ca@component",
875 stanza.from.to_s
876 )
877 assert_equal "customer@example.com", stanza.to.to_s
878 assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
879 end]
880 )
881
882 post(
883 "/inbound/calls/CALLID/voicemail/audio",
884 {
885 "startTime" => "2021-01-01T00:00:00Z",
886 "endTime" => "2021-01-01T00:00:06Z",
887 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
888 "to" => "+15551234567",
889 "from" => "Anonymous"
890 }.to_json,
891 { "CONTENT_TYPE" => "application/json" }
892 )
893
894 assert last_response.ok?
895 assert_mock Customer::BLATHER
896 assert_requested language_id
897 end
898 em :test_anonymous_voicemail
899
900 def test_voicemail_short
901 post(
902 "/inbound/calls/CALLID/voicemail/audio",
903 {
904 "startTime" => "2021-01-01T00:00:00Z",
905 "endTime" => "2021-01-01T00:00:05Z"
906 }.to_json,
907 { "CONTENT_TYPE" => "application/json" }
908 )
909
910 assert last_response.ok?
911 assert_mock Customer::BLATHER
912 end
913 em :test_voicemail_short
914
915 def test_voicemail_no_customer
916 post(
917 "/inbound/calls/CALLID/voicemail",
918 {
919 "startTime" => "2021-01-01T00:00:00Z",
920 "endTime" => "2021-01-01T00:00:06Z",
921 "mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
922 "to" => "+15551200000",
923 "from" => "+15557654321"
924 }.to_json,
925 { "CONTENT_TYPE" => "application/json" }
926 )
927
928 assert last_response.ok?
929 assert_equal(
930 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
931 "<SpeakSentence>The number you have dialled is not in service." \
932 "</SpeakSentence></Response>",
933 last_response.body
934 )
935 end
936 em :test_voicemail_no_customer
937
938 def test_inbound_from_reachability_during_reachability
939 ReachableRedis.expect(
940 :exists,
941 EMPromise.resolve(1),
942 ["jmp_customer_reachability_voice-customerid_reach"]
943 )
944 ReachableRedis.expect(
945 :incr,
946 EMPromise.resolve(1),
947 ["jmp_customer_reachability_voice-customerid_reach"]
948 )
949
950 post(
951 "/inbound/calls",
952 {
953 from: "+14445556666",
954 to: "+15551234563",
955 callId: "acall"
956 }.to_json,
957 { "CONTENT_TYPE" => "application/json" }
958 )
959
960 assert last_response.ok?
961 assert_equal(
962 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
963 "<Hangup />" \
964 "</Response>",
965 last_response.body
966 )
967 assert_mock CustomerFwd::BANDWIDTH_VOICE
968 assert_mock ReachableRedis
969 end
970 em :test_inbound_from_reachability_during_reachability
971
972 def test_bulk_order
973 create_order = stub_request(
974 :post,
975 "https://dashboard.bandwidth.com/v1.0/accounts//orders"
976 ).to_return(status: 201, body: <<~RESPONSE)
977 <OrderResponse>
978 <Order>
979 <id>test_order</id>
980 </Order>
981 </OrderResponse>
982 RESPONSE
983
984 post(
985 "/orders",
986 { quantity: 100 },
987 "HTTP_ACCEPT" => "application/json",
988 "HTTP_AUTHORIZATION" => "Bearer sometoken"
989 )
990
991 assert last_response.ok?
992 assert_equal(
993 { id: "test_order" }.to_json,
994 last_response.body
995 )
996 assert_requested create_order
997 end
998 em :test_bulk_order
999
1000 def test_bulk_order_low_balance
1001 post(
1002 "/orders",
1003 { quantity: 100 },
1004 "HTTP_ACCEPT" => "application/json",
1005 "HTTP_AUTHORIZATION" => "Bearer lowtoken"
1006 )
1007
1008 assert_equal 402, last_response.status
1009 end
1010 em :test_bulk_order_low_balance
1011
1012 def test_bulk_order_bad_token
1013 post(
1014 "/orders",
1015 { quantity: 100 },
1016 "HTTP_ACCEPT" => "application/json",
1017 "HTTP_AUTHORIZATION" => "Bearer badtoken"
1018 )
1019
1020 assert_equal 401, last_response.status
1021 end
1022 em :test_bulk_order_bad_token
1023
1024 def test_order_get
1025 stub_request(
1026 :get,
1027 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1028 ).to_return(status: 200, body: <<~RESPONSE)
1029 <OrderResponse>
1030 <id>testorder</id>
1031 <OrderStatus>complete</OrderStatus>
1032 <CompletedNumbers>
1033 <TelephoneNumber>
1034 <FullNumber>5551234567</FullNumber>
1035 </TelephoneNumber>
1036 </CompletedNumbers>
1037 </OrderResponse>
1038 RESPONSE
1039
1040 Transaction::DB.expect(:transaction, nil) do |&blk|
1041 blk.call
1042 true
1043 end
1044 Transaction::DB.expect(
1045 :exec,
1046 nil,
1047 [String, Matching.new { |params|
1048 assert_equal "bulkcustomer", params[0]
1049 assert_equal "testorder", params[1]
1050 assert_equal(-1.75, params[4])
1051 assert_equal "Bulk order", params[5]
1052 }]
1053 )
1054
1055 get(
1056 "/orders/testorder",
1057 "",
1058 "HTTP_ACCEPT" => "application/json",
1059 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1060 )
1061
1062 assert last_response.ok?
1063 assert_equal(
1064 { id: "testorder", status: "complete", tels: ["+15551234567"] }.to_json,
1065 last_response.body
1066 )
1067 assert_mock Transaction::DB
1068 end
1069 em :test_order_get
1070
1071 def test_order_get_multi
1072 stub_request(
1073 :get,
1074 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1075 ).to_return(status: 200, body: <<~RESPONSE)
1076 <OrderResponse>
1077 <id>testorder</id>
1078 <OrderStatus>complete</OrderStatus>
1079 <CompletedNumbers>
1080 <TelephoneNumber>
1081 <FullNumber>5551234567</FullNumber>
1082 </TelephoneNumber>
1083 <TelephoneNumber>
1084 <FullNumber>5551234568</FullNumber>
1085 </TelephoneNumber>
1086 </CompletedNumbers>
1087 </OrderResponse>
1088 RESPONSE
1089
1090 Transaction::DB.expect(:transaction, nil) do |&blk|
1091 blk.call
1092 true
1093 end
1094 Transaction::DB.expect(
1095 :exec,
1096 nil,
1097 [String, Matching.new { |params|
1098 assert_equal "bulkcustomer", params[0]
1099 assert_equal "testorder", params[1]
1100 assert_equal (-1.75 * 2), params[4]
1101 assert_equal "Bulk order", params[5]
1102 }]
1103 )
1104
1105 get(
1106 "/orders/testorder",
1107 "",
1108 "HTTP_ACCEPT" => "application/json",
1109 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1110 )
1111
1112 assert last_response.ok?
1113 assert_equal(
1114 {
1115 id: "testorder",
1116 status: "complete",
1117 tels: ["+15551234567", "+15551234568"]
1118 }.to_json,
1119 last_response.body
1120 )
1121 assert_mock Transaction::DB
1122 end
1123 em :test_order_get_multi
1124
1125 def test_order_get_received
1126 stub_request(
1127 :get,
1128 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1129 ).to_return(status: 200, body: <<~RESPONSE)
1130 <OrderResponse>
1131 <id>testorder</id>
1132 <OrderStatus>received</OrderStatus>
1133 </OrderResponse>
1134 RESPONSE
1135
1136 get(
1137 "/orders/testorder",
1138 "",
1139 "HTTP_ACCEPT" => "application/json",
1140 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1141 )
1142
1143 assert last_response.ok?
1144 assert_equal(
1145 { id: "testorder", status: "received" }.to_json,
1146 last_response.body
1147 )
1148 end
1149 em :test_order_get_received
1150
1151 def test_order_get_failed
1152 stub_request(
1153 :get,
1154 "https://dashboard.bandwidth.com/v1.0/accounts//orders/testorder"
1155 ).to_return(status: 200, body: <<~RESPONSE)
1156 <OrderResponse>
1157 <id>testorder</id>
1158 <OrderStatus>failed</OrderStatus>
1159 </OrderResponse>
1160 RESPONSE
1161
1162 get(
1163 "/orders/testorder",
1164 "",
1165 "HTTP_ACCEPT" => "application/json",
1166 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1167 )
1168
1169 assert last_response.ok?
1170 assert_equal(
1171 { id: "testorder", status: "failed" }.to_json,
1172 last_response.body
1173 )
1174 end
1175 em :test_order_get_failed
1176
1177 def test_order_get_bad_token
1178 get(
1179 "/orders/testorder",
1180 "",
1181 "HTTP_ACCEPT" => "application/json",
1182 "HTTP_AUTHORIZATION" => "Bearer badtoken"
1183 )
1184
1185 assert_equal 401, last_response.status
1186 end
1187 em :test_order_get_bad_token
1188
1189 def test_delete_tel
1190 stub_request(
1191 :get,
1192 "https://dashboard.bandwidth.com/v1.0/tns/+15551234567/tndetails"
1193 ).to_return(status: 200, body: <<~RESPONSE)
1194 <Response>
1195 <TelephoneNumberDetails>
1196 <SipPeer><PeerId>bulkpeer</PeerId></SipPeer>
1197 </TelephoneNumberDetails>
1198 </Response>
1199 RESPONSE
1200
1201 req = stub_request(
1202 :post,
1203 "https://dashboard.bandwidth.com/v1.0/accounts//disconnects"
1204 ).to_return(status: 200, body: "")
1205
1206 delete(
1207 "/orders/tels/+15551234567",
1208 "",
1209 "HTTP_ACCEPT" => "application/json",
1210 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1211 )
1212
1213 assert last_response.ok?
1214 assert_requested req
1215 end
1216 em :test_delete_tel
1217
1218 def test_delete_tel_not_yours
1219 stub_request(
1220 :get,
1221 "https://dashboard.bandwidth.com/v1.0/tns/+15551234567/tndetails"
1222 ).to_return(status: 200, body: <<~RESPONSE)
1223 <Response>
1224 <TelephoneNumberDetails>
1225 <SipPeer><PeerId>mainpeer</PeerId></SipPeer>
1226 </TelephoneNumberDetails>
1227 </Response>
1228 RESPONSE
1229
1230 delete(
1231 "/orders/tels/+15551234567",
1232 "",
1233 "HTTP_ACCEPT" => "application/json",
1234 "HTTP_AUTHORIZATION" => "Bearer sometoken"
1235 )
1236
1237 assert_equal 401, last_response.status
1238 end
1239 em :test_delete_tel_not_yours
1240
1241 def test_delete_tel_bad_token
1242 delete(
1243 "/orders/tels/+15551234567",
1244 "",
1245 "HTTP_ACCEPT" => "application/json",
1246 "HTTP_AUTHORIZATION" => "Bearer badtoken"
1247 )
1248
1249 assert_equal 401, last_response.status
1250 end
1251 em :test_delete_tel_bad_token
1252end