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