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 [
269 customer,
270 CONFIG[:activation_amount],
271 :test_default_method
272 ]
273 )
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 [
302 customer,
303 CONFIG[:activation_amount],
304 :test_default_method
305 ]
306 )
307 iq = Blather::Stanza::Iq::Command.new
308 iq.from = "test@example.com"
309 result = Minitest::Mock.new
310 result.expect(:then, nil)
311 Registration::Payment::CreditCard::Activate::COMMAND_MANAGER.expect(
312 :write,
313 result,
314 [Matching.new do |reply|
315 assert_equal :error, reply.note_type
316 assert_equal(
317 Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE +
318 ": http://creditcard.example.com",
319 reply.note.content
320 )
321 end]
322 )
323 Registration::Payment::CreditCard::Activate.new(
324 iq,
325 customer,
326 :test_default_method,
327 "+15555550000"
328 ).write.sync
329 Registration::Payment::CreditCard::Activate::Transaction.verify
330 end
331 em :test_write_declines
332 end
333
334 class InviteCodeTest < Minitest::Test
335 Registration::Payment::InviteCode::DB =
336 Minitest::Mock.new
337 Registration::Payment::InviteCode::REDIS =
338 Minitest::Mock.new
339 Registration::Payment::InviteCode::COMMAND_MANAGER =
340 Minitest::Mock.new
341 Registration::Payment::InviteCode::Finish =
342 Minitest::Mock.new
343
344 def test_write
345 customer = Customer.new("test", plan_name: "test_usd")
346 Registration::Payment::InviteCode::REDIS.expect(
347 :get,
348 EMPromise.resolve(0),
349 ["jmp_invite_tries-test"]
350 )
351 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
352 :write,
353 EMPromise.resolve(
354 Blather::Stanza::Iq::Command.new.tap { |iq|
355 iq.form.fields = [{ var: "code", value: "abc" }]
356 }
357 ),
358 [Matching.new do |reply|
359 assert_equal :form, reply.form.type
360 assert_nil reply.form.instructions
361 end]
362 )
363 Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
364 Registration::Payment::InviteCode::Finish.expect(
365 :new,
366 OpenStruct.new(write: nil),
367 [
368 Blather::Stanza::Iq::Command,
369 customer,
370 "+15555550000"
371 ]
372 )
373 iq = Blather::Stanza::Iq::Command.new
374 iq.from = "test@example.com"
375 Registration::Payment::InviteCode.new(
376 iq,
377 customer,
378 "+15555550000"
379 ).write.sync
380 Registration::Payment::InviteCode::COMMAND_MANAGER.verify
381 Registration::Payment::InviteCode::DB.verify
382 Registration::Payment::InviteCode::REDIS.verify
383 Registration::Payment::InviteCode::Finish.verify
384 end
385 em :test_write
386
387 def test_write_bad_code
388 customer = Customer.new("test", plan_name: "test_usd")
389 Registration::Payment::InviteCode::REDIS.expect(
390 :get,
391 EMPromise.resolve(0),
392 ["jmp_invite_tries-test"]
393 )
394 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
395 :write,
396 EMPromise.resolve(
397 Blather::Stanza::Iq::Command.new.tap { |iq|
398 iq.form.fields = [{ var: "code", value: "abc" }]
399 }
400 ),
401 [Matching.new do |reply|
402 assert_equal :form, reply.form.type
403 assert_nil reply.form.instructions
404 end]
405 )
406 Registration::Payment::InviteCode::DB.expect(:transaction, []) do
407 raise Registration::Payment::InviteCode::Invalid, "wut"
408 end
409 Registration::Payment::InviteCode::REDIS.expect(
410 :incr,
411 EMPromise.resolve(nil),
412 ["jmp_invite_tries-test"]
413 )
414 Registration::Payment::InviteCode::REDIS.expect(
415 :expire,
416 EMPromise.resolve(nil),
417 ["jmp_invite_tries-test", 60 * 60]
418 )
419 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
420 :write,
421 EMPromise.reject(Promise::Error.new),
422 [Matching.new do |reply|
423 assert_equal :form, reply.form.type
424 assert_equal "wut", reply.form.instructions
425 end]
426 )
427 iq = Blather::Stanza::Iq::Command.new
428 iq.from = "test@example.com"
429 assert_raises Promise::Error do
430 Registration::Payment::InviteCode.new(
431 iq,
432 customer,
433 "+15555550000"
434 ).write.sync
435 end
436 Registration::Payment::InviteCode::COMMAND_MANAGER.verify
437 Registration::Payment::InviteCode::DB.verify
438 Registration::Payment::InviteCode::REDIS.verify
439 end
440 em :test_write_bad_code
441
442 def test_write_bad_code_over_limit
443 customer = Customer.new("test", plan_name: "test_usd")
444 Registration::Payment::InviteCode::REDIS.expect(
445 :get,
446 EMPromise.resolve(11),
447 ["jmp_invite_tries-test"]
448 )
449 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
450 :write,
451 EMPromise.resolve(
452 Blather::Stanza::Iq::Command.new.tap { |iq|
453 iq.form.fields = [{ var: "code", value: "abc" }]
454 }
455 ),
456 [Matching.new do |reply|
457 assert_equal :form, reply.form.type
458 assert_nil reply.form.instructions
459 end]
460 )
461 Registration::Payment::InviteCode::REDIS.expect(
462 :incr,
463 EMPromise.resolve(nil),
464 ["jmp_invite_tries-test"]
465 )
466 Registration::Payment::InviteCode::REDIS.expect(
467 :expire,
468 EMPromise.resolve(nil),
469 ["jmp_invite_tries-test", 60 * 60]
470 )
471 Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
472 :write,
473 EMPromise.reject(Promise::Error.new),
474 [Matching.new do |reply|
475 assert_equal :form, reply.form.type
476 assert_equal "Too many wrong attempts", reply.form.instructions
477 end]
478 )
479 iq = Blather::Stanza::Iq::Command.new
480 iq.from = "test@example.com"
481 assert_raises Promise::Error do
482 Registration::Payment::InviteCode.new(
483 iq,
484 customer,
485 "+15555550000"
486 ).write.sync
487 end
488 Registration::Payment::InviteCode::COMMAND_MANAGER.verify
489 Registration::Payment::InviteCode::REDIS.verify
490 end
491 em :test_write_bad_code_over_limit
492 end
493 end
494
495 class FinishTest < Minitest::Test
496 Registration::Finish::BLATHER = Minitest::Mock.new
497 Registration::Finish::REDIS = Minitest::Mock.new
498
499 def setup
500 @sgx = Minitest::Mock.new(BackendSgx.new("test"))
501 iq = Blather::Stanza::Iq::Command.new
502 iq.from = "test\\40example.com@cheogram.com"
503 @finish = Registration::Finish.new(
504 iq,
505 Customer.new("test", sgx: @sgx),
506 "+15555550000"
507 )
508 end
509
510 def test_write
511 create_order = stub_request(
512 :post,
513 "https://dashboard.bandwidth.com/v1.0/accounts//orders"
514 ).to_return(status: 201, body: <<~RESPONSE)
515 <OrderResponse>
516 <Order>
517 <id>test_order</id>
518 </Order>
519 </OrderResponse>
520 RESPONSE
521 stub_request(
522 :get,
523 "https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
524 ).to_return(status: 201, body: <<~RESPONSE)
525 <OrderResponse>
526 <OrderStatus>COMPLETE</OrderStatus>
527 <CompletedNumbers>
528 <TelephoneNumber>
529 <FullNumber>5555550000</FullNumber>
530 </TelephoneNumber>
531 </CompletedNumbers>
532 </OrderResponse>
533 RESPONSE
534 stub_request(
535 :post,
536 "https://api.catapult.inetwork.com/v1/users/catapult_user/phoneNumbers"
537 ).with(
538 body: open(__dir__ + "/data/catapult_import_body.json").read.chomp,
539 headers: {
540 "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0",
541 "Content-Type" => "application/json"
542 }
543 ).to_return(status: 201)
544 @sgx.expect(
545 :register!,
546 EMPromise.resolve(OpenStruct.new(error?: false)),
547 ["+15555550000"]
548 )
549 Registration::Finish::REDIS.expect(
550 :set,
551 nil,
552 [
553 "catapult_fwd-+15555550000",
554 "sip:test%5C40example.com%40cheogram.com@sip.cheogram.com"
555 ]
556 )
557 Registration::Finish::REDIS.expect(
558 :set,
559 nil,
560 ["catapult_fwd_timeout-test\\40example.com@cheogram.com", 25]
561 )
562 Registration::Finish::BLATHER.expect(
563 :<<,
564 nil,
565 [Matching.new do |reply|
566 assert_equal :completed, reply.status
567 assert_equal :info, reply.note_type
568 assert_equal(
569 "Your JMP account has been activated as +15555550000",
570 reply.note.content
571 )
572 end]
573 )
574 @finish.write.sync
575 assert_requested create_order
576 @sgx.verify
577 Registration::Finish::REDIS.verify
578 Registration::Finish::BLATHER.verify
579 end
580 em :test_write
581
582 def test_write_tn_fail
583 create_order = stub_request(
584 :post,
585 "https://dashboard.bandwidth.com/v1.0/accounts//orders"
586 ).to_return(status: 201, body: <<~RESPONSE)
587 <OrderResponse>
588 <Order>
589 <id>test_order</id>
590 </Order>
591 </OrderResponse>
592 RESPONSE
593 stub_request(
594 :get,
595 "https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
596 ).to_return(status: 201, body: <<~RESPONSE)
597 <OrderResponse>
598 <OrderStatus>FAILED</OrderStatus>
599 </OrderResponse>
600 RESPONSE
601 Registration::Finish::BLATHER.expect(
602 :<<,
603 nil,
604 [Matching.new do |reply|
605 assert_equal :completed, reply.status
606 assert_equal :error, reply.note_type
607 assert_equal(
608 "The JMP number +15555550000 is no longer available, " \
609 "please visit https://jmp.chat and choose another.",
610 reply.note.content
611 )
612 end]
613 )
614 @finish.write.sync
615 assert_requested create_order
616 Registration::Finish::BLATHER.verify
617 end
618 em :test_write_tn_fail
619 end
620end