1# frozen_string_literal: true
2
3require "test_helper"
4require "registration"
5
6class RegistrationTest < Minitest::Test
7 def test_for_registered
8 BACKEND_SGX.expect(
9 :registered?,
10 EMPromise.resolve(OpenStruct.new(phone: "+15555550000")),
11 ["test"]
12 )
13 iq = Blather::Stanza::Iq::Command.new
14 iq.from = "test@example.com"
15 result = Registration.for(iq, Customer.new("test"), Minitest::Mock.new).sync
16 assert_kind_of Registration::Registered, result
17 end
18 em :test_for_registered
19
20 def test_for_activated
21 BACKEND_SGX.expect(
22 :registered?,
23 EMPromise.resolve(nil),
24 ["test"]
25 )
26 web_manager = WebRegisterManager.new
27 web_manager["test@example.com"] = "+15555550000"
28 iq = Blather::Stanza::Iq::Command.new
29 iq.from = "test@example.com"
30 result = Registration.for(
31 iq,
32 Customer.new("test", plan_name: "test_usd", expires_at: Time.now + 999),
33 web_manager
34 ).sync
35 assert_kind_of Registration::Finish, result
36 end
37 em :test_for_activated
38
39 def test_for_not_activated_with_customer_id
40 BACKEND_SGX.expect(
41 :registered?,
42 EMPromise.resolve(nil),
43 ["test"]
44 )
45 web_manager = WebRegisterManager.new
46 web_manager["test@example.com"] = "+15555550000"
47 iq = Blather::Stanza::Iq::Command.new
48 iq.from = "test@example.com"
49 result = Registration.for(
50 iq,
51 Customer.new("test"),
52 web_manager
53 ).sync
54 assert_kind_of Registration::Activation, result
55 end
56 em :test_for_not_activated_with_customer_id
57
58 def test_for_not_activated_without_customer_id
59 skip "customer_id creation not implemented yet"
60 iq = Blather::Stanza::Iq::Command.new
61 Registration.for(iq, nil, Minitest::Mock.new).sync
62 end
63 em :test_for_not_activated_without_customer_id
64
65 class ActivationTest < Minitest::Test
66 Registration::Activation::COMMAND_MANAGER = Minitest::Mock.new
67 def setup
68 iq = Blather::Stanza::Iq::Command.new
69 @activation = Registration::Activation.new(iq, "test", "+15555550000")
70 end
71
72 def test_write
73 stub_request(
74 :get,
75 "https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
76 ).to_return(status: 201, body: <<~RESPONSE)
77 <TelephoneNumberResponse>
78 <TelephoneNumber>5555550000</TelephoneNumber>
79 </TelephoneNumberResponse>
80 RESPONSE
81 stub_request(
82 :get,
83 "https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
84 ).to_return(status: 201, body: <<~RESPONSE)
85 <TelephoneNumberResponse>
86 <TelephoneNumberDetails>
87 <State>KE</State>
88 <RateCenter>FA</RateCenter>
89 </TelephoneNumberDetails>
90 </TelephoneNumberResponse>
91 RESPONSE
92 result = Minitest::Mock.new
93 result.expect(:then, result)
94 result.expect(:then, EMPromise.resolve(:test_result))
95 Registration::Activation::COMMAND_MANAGER.expect(
96 :write,
97 result,
98 [Matching.new do |iq|
99 assert_equal :form, iq.form.type
100 assert_equal(
101 "Going to activate +15555550000 (FA, KE)",
102 iq.form.instructions
103 )
104 end]
105 )
106 assert_equal :test_result, @activation.write.sync
107 end
108 em :test_write
109 end
110
111 class PaymentTest < Minitest::Test
112 Customer::BRAINTREE = Minitest::Mock.new
113 Registration::Payment::Bitcoin::ELECTRUM = Minitest::Mock.new
114
115 def test_for_bitcoin
116 Registration::Payment::Bitcoin::ELECTRUM.expect(:createnewaddress, "addr")
117 iq = Blather::Stanza::Iq::Command.new
118 iq.form.fields = [
119 { var: "activation_method", value: "bitcoin" },
120 { var: "plan_name", value: "test_usd" }
121 ]
122 result = Registration::Payment.for(
123 iq,
124 Customer.new("test"),
125 "+15555550000"
126 )
127 assert_kind_of Registration::Payment::Bitcoin, result
128 end
129
130 def test_for_credit_card
131 braintree_customer = Minitest::Mock.new
132 Customer::BRAINTREE.expect(
133 :customer,
134 braintree_customer
135 )
136 braintree_customer.expect(
137 :find,
138 EMPromise.resolve(OpenStruct.new(payment_methods: [])),
139 ["test"]
140 )
141 iq = Blather::Stanza::Iq::Command.new
142 iq.from = "test@example.com"
143 iq.form.fields = [
144 { var: "activation_method", value: "credit_card" },
145 { var: "plan_name", value: "test_usd" }
146 ]
147 result = Registration::Payment.for(
148 iq,
149 Customer.new("test"),
150 "+15555550000"
151 ).sync
152 assert_kind_of Registration::Payment::CreditCard, result
153 end
154 em :test_for_credit_card
155
156 def test_for_code
157 iq = Blather::Stanza::Iq::Command.new
158 iq.form.fields = [
159 { var: "activation_method", value: "code" },
160 { var: "plan_name", value: "test_usd" }
161 ]
162 result = Registration::Payment.for(
163 iq,
164 Customer.new("test"),
165 "+15555550000"
166 )
167 assert_kind_of Registration::Payment::InviteCode, result
168 end
169
170 class BitcoinTest < Minitest::Test
171 Registration::Payment::Bitcoin::ELECTRUM = Minitest::Mock.new
172 Registration::Payment::Bitcoin::REDIS = Minitest::Mock.new
173 Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
174 Registration::Payment::Bitcoin::BLATHER = Minitest::Mock.new
175
176 def setup
177 Registration::Payment::Bitcoin::ELECTRUM.expect(
178 :createnewaddress,
179 EMPromise.resolve("testaddr")
180 )
181 iq = Blather::Stanza::Iq::Command.new
182 @bitcoin = Registration::Payment::Bitcoin.new(
183 iq,
184 Customer.new("test", plan_name: "test_usd"),
185 "+15555550000"
186 )
187 end
188
189 def test_write
190 reply_text = <<~NOTE
191 Activate your account by sending at least 1.000000 BTC to
192 testaddr
193
194 You will receive a notification when your payment is complete.
195 NOTE
196 Registration::Payment::Bitcoin::BLATHER.expect(
197 :<<,
198 nil,
199 [Matching.new do |reply|
200 assert_equal :completed, reply.status
201 assert_equal :info, reply.note_type
202 assert_equal reply_text, reply.note.content
203 true
204 end]
205 )
206 Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
207 :usd,
208 EMPromise.resolve(BigDecimal.new(1))
209 )
210 @bitcoin.stub(:save, EMPromise.resolve(nil)) do
211 @bitcoin.write.sync
212 end
213 Registration::Payment::Bitcoin::BLATHER.verify
214 end
215 em :test_write
216 end
217
218 class CreditCardTest < Minitest::Test
219 def setup
220 @iq = Blather::Stanza::Iq::Command.new
221 @iq.from = "test@example.com"
222 @credit_card = Registration::Payment::CreditCard.new(
223 @iq,
224 Customer.new("test"),
225 "+15555550000"
226 )
227 end
228
229 def test_for
230 customer = Minitest::Mock.new(Customer.new("test"))
231 customer.expect(
232 :payment_methods,
233 EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
234 )
235 assert_kind_of(
236 Registration::Payment::CreditCard::Activate,
237 Registration::Payment::CreditCard.for(
238 @iq,
239 customer,
240 "+15555550000"
241 ).sync
242 )
243 end
244 em :test_for
245
246 def test_reply
247 assert_equal [:execute, :next], @credit_card.reply.allowed_actions
248 assert_equal(
249 "Add credit card, then return here and choose next: " \
250 "http://creditcard.example.com",
251 @credit_card.reply.note.content
252 )
253 end
254 end
255
256 class ActivateTest < Minitest::Test
257 Registration::Payment::CreditCard::Activate::Finish =
258 Minitest::Mock.new
259 Registration::Payment::CreditCard::Activate::Transaction =
260 Minitest::Mock.new
261 Registration::Payment::CreditCard::Activate::COMMAND_MANAGER =
262 Minitest::Mock.new
263
264 def test_write
265 transaction = PromiseMock.new
266 transaction.expect(
267 :insert,
268 EMPromise.resolve(nil)
269 )
270 customer = Minitest::Mock.new(
271 Customer.new("test", plan_name: "test_usd")
272 )
273 Registration::Payment::CreditCard::Activate::Transaction.expect(
274 :sale,
275 transaction,
276 [
277 customer,
278 CONFIG[:activation_amount],
279 :test_default_method
280 ]
281 )
282 iq = Blather::Stanza::Iq::Command.new
283 customer.expect(:bill_plan, nil)
284 Registration::Payment::CreditCard::Activate::Finish.expect(
285 :new,
286 OpenStruct.new(write: nil),
287 [Blather::Stanza::Iq, customer, "+15555550000"]
288 )
289 Registration::Payment::CreditCard::Activate.new(
290 iq,
291 customer,
292 :test_default_method,
293 "+15555550000"
294 ).write.sync
295 Registration::Payment::CreditCard::Activate::Transaction.verify
296 transaction.verify
297 customer.verify
298 Registration::Payment::CreditCard::Activate::Finish.verify
299 end
300 em :test_write
301
302 def test_write_declines
303 customer = Minitest::Mock.new(
304 Customer.new("test", plan_name: "test_usd")
305 )
306 Registration::Payment::CreditCard::Activate::Transaction.expect(
307 :sale,
308 EMPromise.reject("declined"),
309 [
310 customer,
311 CONFIG[:activation_amount],
312 :test_default_method
313 ]
314 )
315 iq = Blather::Stanza::Iq::Command.new
316 iq.from = "test@example.com"
317 result = Minitest::Mock.new
318 result.expect(:then, nil)
319 Registration::Payment::CreditCard::Activate::COMMAND_MANAGER.expect(
320 :write,
321 result,
322 [Matching.new do |reply|
323 assert_equal :error, reply.note_type
324 assert_equal(
325 Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE +
326 ": http://creditcard.example.com",
327 reply.note.content
328 )
329 end]
330 )
331 Registration::Payment::CreditCard::Activate.new(
332 iq,
333 customer,
334 :test_default_method,
335 "+15555550000"
336 ).write.sync
337 Registration::Payment::CreditCard::Activate::Transaction.verify
338 end
339 em :test_write_declines
340 end
341
342 class InviteCodeTest < Minitest::Test
343 Registration::Payment::InviteCode::DB =
344 Minitest::Mock.new
345 Registration::Payment::InviteCode::REDIS =
346 Minitest::Mock.new
347 Registration::Payment::InviteCode::COMMAND_MANAGER =
348 Minitest::Mock.new
349 Registration::Payment::InviteCode::Finish =
350 Minitest::Mock.new
351
352 def test_write
353 customer = Customer.new("test", plan_name: "test_usd")
354 Registration::Payment::InviteCode::REDIS.expect(
355 :get,
356 EMPromise.resolve(0),
357 ["jmp_invite_tries-test"]
358 )
359 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
360 :write,
361 EMPromise.resolve(
362 Blather::Stanza::Iq::Command.new.tap { |iq|
363 iq.form.fields = [{ var: "code", value: "abc" }]
364 }
365 ),
366 [Matching.new do |reply|
367 assert_equal :form, reply.form.type
368 assert_nil reply.form.instructions
369 end]
370 )
371 Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
372 Registration::Payment::InviteCode::Finish.expect(
373 :new,
374 OpenStruct.new(write: nil),
375 [
376 Blather::Stanza::Iq::Command,
377 customer,
378 "+15555550000"
379 ]
380 )
381 iq = Blather::Stanza::Iq::Command.new
382 iq.from = "test@example.com"
383 Registration::Payment::InviteCode.new(
384 iq,
385 customer,
386 "+15555550000"
387 ).write.sync
388 Registration::Payment::InviteCode::COMMAND_MANAGER.verify
389 Registration::Payment::InviteCode::DB.verify
390 Registration::Payment::InviteCode::REDIS.verify
391 Registration::Payment::InviteCode::Finish.verify
392 end
393 em :test_write
394
395 def test_write_bad_code
396 customer = Customer.new("test", plan_name: "test_usd")
397 Registration::Payment::InviteCode::REDIS.expect(
398 :get,
399 EMPromise.resolve(0),
400 ["jmp_invite_tries-test"]
401 )
402 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
403 :write,
404 EMPromise.resolve(
405 Blather::Stanza::Iq::Command.new.tap { |iq|
406 iq.form.fields = [{ var: "code", value: "abc" }]
407 }
408 ),
409 [Matching.new do |reply|
410 assert_equal :form, reply.form.type
411 assert_nil reply.form.instructions
412 end]
413 )
414 Registration::Payment::InviteCode::DB.expect(:transaction, []) do
415 raise Registration::Payment::InviteCode::Invalid, "wut"
416 end
417 Registration::Payment::InviteCode::REDIS.expect(
418 :incr,
419 EMPromise.resolve(nil),
420 ["jmp_invite_tries-test"]
421 )
422 Registration::Payment::InviteCode::REDIS.expect(
423 :expire,
424 EMPromise.resolve(nil),
425 ["jmp_invite_tries-test", 60 * 60]
426 )
427 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
428 :write,
429 EMPromise.reject(Promise::Error.new),
430 [Matching.new do |reply|
431 assert_equal :form, reply.form.type
432 assert_equal "wut", reply.form.instructions
433 end]
434 )
435 iq = Blather::Stanza::Iq::Command.new
436 iq.from = "test@example.com"
437 assert_raises Promise::Error do
438 Registration::Payment::InviteCode.new(
439 iq,
440 customer,
441 "+15555550000"
442 ).write.sync
443 end
444 Registration::Payment::InviteCode::COMMAND_MANAGER.verify
445 Registration::Payment::InviteCode::DB.verify
446 Registration::Payment::InviteCode::REDIS.verify
447 end
448 em :test_write_bad_code
449
450 def test_write_bad_code_over_limit
451 customer = Customer.new("test", plan_name: "test_usd")
452 Registration::Payment::InviteCode::REDIS.expect(
453 :get,
454 EMPromise.resolve(11),
455 ["jmp_invite_tries-test"]
456 )
457 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
458 :write,
459 EMPromise.resolve(
460 Blather::Stanza::Iq::Command.new.tap { |iq|
461 iq.form.fields = [{ var: "code", value: "abc" }]
462 }
463 ),
464 [Matching.new do |reply|
465 assert_equal :form, reply.form.type
466 assert_nil reply.form.instructions
467 end]
468 )
469 Registration::Payment::InviteCode::REDIS.expect(
470 :incr,
471 EMPromise.resolve(nil),
472 ["jmp_invite_tries-test"]
473 )
474 Registration::Payment::InviteCode::REDIS.expect(
475 :expire,
476 EMPromise.resolve(nil),
477 ["jmp_invite_tries-test", 60 * 60]
478 )
479 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
480 :write,
481 EMPromise.reject(Promise::Error.new),
482 [Matching.new do |reply|
483 assert_equal :form, reply.form.type
484 assert_equal "Too many wrong attempts", reply.form.instructions
485 end]
486 )
487 iq = Blather::Stanza::Iq::Command.new
488 iq.from = "test@example.com"
489 assert_raises Promise::Error do
490 Registration::Payment::InviteCode.new(
491 iq,
492 customer,
493 "+15555550000"
494 ).write.sync
495 end
496 Registration::Payment::InviteCode::COMMAND_MANAGER.verify
497 Registration::Payment::InviteCode::REDIS.verify
498 end
499 em :test_write_bad_code_over_limit
500 end
501 end
502
503 class FinishTest < Minitest::Test
504 Registration::Finish::BLATHER = Minitest::Mock.new
505 Registration::Finish::REDIS = Minitest::Mock.new
506
507 def setup
508 iq = Blather::Stanza::Iq::Command.new
509 iq.from = "test\\40example.com@cheogram.com"
510 @finish = Registration::Finish.new(
511 iq,
512 Customer.new("test"),
513 "+15555550000"
514 )
515 end
516
517 def test_write
518 create_order = stub_request(
519 :post,
520 "https://dashboard.bandwidth.com/v1.0/accounts//orders"
521 ).to_return(status: 201, body: <<~RESPONSE)
522 <OrderResponse>
523 <Order>
524 <id>test_order</id>
525 </Order>
526 </OrderResponse>
527 RESPONSE
528 stub_request(
529 :get,
530 "https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
531 ).to_return(status: 201, body: <<~RESPONSE)
532 <OrderResponse>
533 <OrderStatus>COMPLETE</OrderStatus>
534 <CompletedNumbers>
535 <TelephoneNumber>
536 <FullNumber>5555550000</FullNumber>
537 </TelephoneNumber>
538 </CompletedNumbers>
539 </OrderResponse>
540 RESPONSE
541 stub_request(
542 :post,
543 "https://api.catapult.inetwork.com/v1/users/catapult_user/phoneNumbers"
544 ).with(
545 body: open(__dir__ + "/data/catapult_import_body.json").read.chomp,
546 headers: {
547 "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0",
548 "Content-Type" => "application/json"
549 }
550 ).to_return(status: 201)
551 BACKEND_SGX.expect(
552 :register!,
553 EMPromise.resolve(OpenStruct.new(error?: false)),
554 ["test", "+15555550000"]
555 )
556 Registration::Finish::REDIS.expect(
557 :set,
558 nil,
559 [
560 "catapult_fwd-+15555550000",
561 "sip:test%5C40example.com%40cheogram.com@sip.cheogram.com"
562 ]
563 )
564 Registration::Finish::REDIS.expect(
565 :set,
566 nil,
567 ["catapult_fwd_timeout-test\\40example.com@cheogram.com", 25]
568 )
569 Registration::Finish::BLATHER.expect(
570 :<<,
571 nil,
572 [Matching.new do |reply|
573 assert_equal :completed, reply.status
574 assert_equal :info, reply.note_type
575 assert_equal(
576 "Your JMP account has been activated as +15555550000",
577 reply.note.content
578 )
579 end]
580 )
581 @finish.write.sync
582 assert_requested create_order
583 BACKEND_SGX.verify
584 Registration::Finish::REDIS.verify
585 Registration::Finish::BLATHER.verify
586 end
587 em :test_write
588
589 def test_write_tn_fail
590 create_order = stub_request(
591 :post,
592 "https://dashboard.bandwidth.com/v1.0/accounts//orders"
593 ).to_return(status: 201, body: <<~RESPONSE)
594 <OrderResponse>
595 <Order>
596 <id>test_order</id>
597 </Order>
598 </OrderResponse>
599 RESPONSE
600 stub_request(
601 :get,
602 "https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
603 ).to_return(status: 201, body: <<~RESPONSE)
604 <OrderResponse>
605 <OrderStatus>FAILED</OrderStatus>
606 </OrderResponse>
607 RESPONSE
608 Registration::Finish::BLATHER.expect(
609 :<<,
610 nil,
611 [Matching.new do |reply|
612 assert_equal :completed, reply.status
613 assert_equal :error, reply.note_type
614 assert_equal(
615 "The JMP number +15555550000 is no longer available, " \
616 "please visit https://jmp.chat and choose another.",
617 reply.note.content
618 )
619 end]
620 )
621 @finish.write.sync
622 assert_requested create_order
623 Registration::Finish::BLATHER.verify
624 end
625 em :test_write_tn_fail
626 end
627end