test_registration.rb

  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