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