test_registration.rb

   1# frozen_string_literal: true
   2
   3require "test_helper"
   4require "customer"
   5require "registration"
   6
   7BandwidthTnReservationRepo::REDIS = FakeRedis.new
   8
   9class RegistrationTest < Minitest::Test
  10	def test_for_registered
  11		sgx = OpenStruct.new(
  12			registered?: OpenStruct.new(phone: "+15555550000")
  13		)
  14		iq = Blather::Stanza::Iq::Command.new
  15		iq.from = "test@example.com"
  16		result = execute_command(iq) do
  17			Registration.for(
  18				customer(sgx: sgx),
  19				nil,
  20				Minitest::Mock.new
  21			)
  22		end
  23		assert_kind_of Registration::Registered, result
  24	end
  25	em :test_for_registered
  26
  27	def test_for_activated
  28		reservation_req = stub_request(
  29			:post,
  30			"https://dashboard.bandwidth.com/v1.0/accounts//tnreservation"
  31		)
  32		web_manager = TelSelections.new(redis: FakeRedis.new)
  33		web_manager.set("test@example.net", "+15555550000")
  34		result = execute_command do
  35			sgx = OpenStruct.new(registered?: false)
  36			Registration.for(
  37				customer(
  38					plan_name: "test_usd",
  39					expires_at: Time.now + 999,
  40					sgx: sgx
  41				),
  42				nil,
  43				web_manager
  44			)
  45		end
  46		assert_kind_of Registration::Finish, result
  47		assert_requested reservation_req
  48	end
  49	em :test_for_activated
  50
  51	def test_for_not_activated_approved
  52		sgx = OpenStruct.new(registered?: false)
  53		web_manager = TelSelections.new(redis: FakeRedis.new)
  54		web_manager.set("test\\40approved.example.com@component", "+15555550000")
  55		iq = Blather::Stanza::Iq::Command.new
  56		iq.from = "test@approved.example.com"
  57		result = execute_command(iq) do
  58			Registration::Activation.for(
  59				customer(
  60					sgx: sgx,
  61					jid: Blather::JID.new("test\\40approved.example.com@component")
  62				),
  63				nil,
  64				web_manager
  65			)
  66		end
  67		assert_kind_of Registration::Activation::Allow, result
  68	end
  69	em :test_for_not_activated_approved
  70
  71	def test_for_not_activated_googleplay
  72		sgx = OpenStruct.new(registered?: false)
  73		web_manager = TelSelections.new(redis: FakeRedis.new)
  74		web_manager.set("test@example.net", "+15555550000")
  75		iq = Blather::Stanza::Iq::Command.new
  76		iq.from = "test@approved.example.com"
  77		result = execute_command(iq) do
  78			Registration::Activation.for(
  79				customer(sgx: sgx),
  80				"GARBLEDYGOOK==",
  81				web_manager
  82			)
  83		end
  84		assert_kind_of Registration::Activation::GooglePlay, result
  85	end
  86	em :test_for_not_activated_googleplay
  87
  88	def test_for_not_activated_with_customer_id
  89		sgx = OpenStruct.new(registered?: false)
  90		web_manager = TelSelections.new(redis: FakeRedis.new)
  91		web_manager.set("test@example.net", "+15555550000")
  92		iq = Blather::Stanza::Iq::Command.new
  93		iq.from = "test@example.com"
  94		result = execute_command(iq) do
  95			Registration::Activation.for(
  96				customer(sgx: sgx),
  97				nil,
  98				web_manager
  99			)
 100		end
 101		assert_kind_of Registration::Activation, result
 102	end
 103	em :test_for_not_activated_with_customer_id
 104
 105	class ActivationTest < Minitest::Test
 106		Registration::Activation::DB = Minitest::Mock.new
 107		Registration::Activation::REDIS = FakeRedis.new
 108		Registration::Activation::Payment = Minitest::Mock.new
 109		Registration::Activation::Finish = Minitest::Mock.new
 110		Command::COMMAND_MANAGER = Minitest::Mock.new
 111
 112		def setup
 113			@customer = Minitest::Mock.new(customer)
 114			@activation = Registration::Activation.new(@customer, "+15555550000")
 115		end
 116
 117		def test_write
 118			Command::COMMAND_MANAGER.expect(
 119				:write,
 120				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 121					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 122				}),
 123				[Matching.new do |iq|
 124					assert_equal :form, iq.form.type
 125					assert_equal(
 126						"You've selected +15555550000 as your JMP number.",
 127						iq.form.instructions.lines.first.chomp
 128					)
 129				end]
 130			)
 131			@customer.expect(:with_plan, @customer, ["test_usd"])
 132			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 133			Registration::Activation::Payment.expect(
 134				:for,
 135				EMPromise.reject(:test_result),
 136				[Blather::Stanza::Iq, @customer, "+15555550000"]
 137			)
 138			assert_equal(
 139				:test_result,
 140				execute_command { @activation.write.catch { |e| e } }
 141			)
 142			assert_mock Command::COMMAND_MANAGER
 143			assert_mock @customer
 144			assert_mock Registration::Activation::Payment
 145		end
 146		em :test_write
 147
 148		def test_write_with_code
 149			Command::COMMAND_MANAGER.expect(
 150				:write,
 151				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 152					iq.form.fields = [
 153						{ var: "plan_name", value: "test_usd" },
 154						{ var: "code", value: "123" }
 155					]
 156				}),
 157				[Matching.new do |iq|
 158					assert_equal :form, iq.form.type
 159					assert_equal(
 160						"You've selected +15555550000 as your JMP number.",
 161						iq.form.instructions.lines.first.chomp
 162					)
 163				end]
 164			)
 165			@customer.expect(:with_plan, @customer, ["test_usd"])
 166			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 167			@customer.expect(:activate_plan_starting_now, EMPromise.resolve(nil), [])
 168			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 169			Registration::Activation::DB.expect(
 170				:exec,
 171				OpenStruct.new(cmd_tuples: 1),
 172				[String, ["test", "123"]]
 173			)
 174			Registration::Activation::Finish.expect(
 175				:new,
 176				OpenStruct.new(write: EMPromise.reject(:test_result)),
 177				[@customer, "+15555550000"]
 178			)
 179			assert_equal(
 180				:test_result,
 181				execute_command { @activation.write.catch { |e| e } }
 182			)
 183			assert_mock Command::COMMAND_MANAGER
 184			assert_mock @customer
 185			assert_mock Registration::Activation::Payment
 186			assert_mock Registration::Activation::DB
 187		end
 188		em :test_write_with_code
 189
 190		def test_write_with_group_code
 191			Command::COMMAND_MANAGER.expect(
 192				:write,
 193				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 194					iq.form.fields = [
 195						{ var: "plan_name", value: "test_usd" },
 196						{ var: "code", value: "123" }
 197					]
 198				}),
 199				[Matching.new do |iq|
 200					assert_equal :form, iq.form.type
 201					assert_equal(
 202						"You've selected +15555550000 as your JMP number.",
 203						iq.form.instructions.lines.first.chomp
 204					)
 205				end]
 206			)
 207			@customer.expect(:with_plan, @customer, ["test_usd"])
 208			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 209			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 210			Registration::Activation::DB.expect(
 211				:exec,
 212				OpenStruct.new(cmd_tuples: 0),
 213				[String, ["test", "123"]]
 214			)
 215			Registration::Activation::Payment.expect(
 216				:for,
 217				EMPromise.reject(:test_result),
 218				[Blather::Stanza::Iq, @customer, "+15555550000"]
 219			)
 220			assert_equal(
 221				:test_result,
 222				execute_command { @activation.write.catch { |e| e } }
 223			)
 224			assert_equal(
 225				"123",
 226				Registration::Activation::REDIS.get(
 227					"jmp_customer_pending_invite-test"
 228				).sync
 229			)
 230			assert_mock Command::COMMAND_MANAGER
 231			assert_mock @customer
 232			assert_mock Registration::Activation::Payment
 233			assert_mock Registration::Activation::DB
 234		end
 235		em :test_write_with_group_code
 236	end
 237
 238	class AllowTest < Minitest::Test
 239		Command::COMMAND_MANAGER = Minitest::Mock.new
 240		Registration::Activation::Allow::DB = Minitest::Mock.new
 241
 242		def test_write_credit_to_nil
 243			cust = Minitest::Mock.new(customer("test"))
 244			allow = Registration::Activation::Allow.new(cust, "+15555550000", nil)
 245
 246			Command::COMMAND_MANAGER.expect(
 247				:write,
 248				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 249					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 250				}),
 251				[Matching.new do |iq|
 252					assert_equal :form, iq.form.type
 253					assert_equal(
 254						"You've selected +15555550000 as your JMP number.",
 255						iq.form.instructions.lines.first.chomp
 256					)
 257					assert_equal 1, iq.form.fields.length
 258				end]
 259			)
 260			Registration::Activation::Allow::DB.expect(
 261				:transaction,
 262				EMPromise.reject(:test_result)
 263			) do |&blk|
 264				blk.call
 265				true
 266			end
 267			cust.expect(:with_plan, cust, ["test_usd"])
 268			cust.expect(:activate_plan_starting_now, nil)
 269			assert_equal(
 270				:test_result,
 271				execute_command { allow.write.catch { |e| e } }
 272			)
 273			assert_mock Command::COMMAND_MANAGER
 274		end
 275		em :test_write_credit_to_nil
 276
 277		def test_write_credit_to_refercust
 278			cust = Minitest::Mock.new(customer("test"))
 279			allow = Registration::Activation::Allow.new(
 280				cust, "+15555550000", "refercust"
 281			)
 282
 283			Command::COMMAND_MANAGER.expect(
 284				:write,
 285				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 286					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 287				}),
 288				[Matching.new do |iq|
 289					assert_equal :form, iq.form.type
 290					assert_equal(
 291						"You've selected +15555550000 as your JMP number.",
 292						iq.form.instructions.lines.first.chomp
 293					)
 294					assert_equal 1, iq.form.fields.length
 295				end]
 296			)
 297			Registration::Activation::Allow::DB.expect(
 298				:transaction,
 299				EMPromise.reject(:test_result)
 300			) do |&blk|
 301				blk.call
 302				true
 303			end
 304			Registration::Activation::Allow::DB.expect(
 305				:exec,
 306				nil,
 307				[String, ["refercust", "test"]]
 308			)
 309			cust.expect(:with_plan, cust, ["test_usd"])
 310			cust.expect(:activate_plan_starting_now, nil)
 311			assert_equal(
 312				:test_result,
 313				execute_command { allow.write.catch { |e| e } }
 314			)
 315			assert_mock Command::COMMAND_MANAGER
 316		end
 317		em :test_write_credit_to_refercust
 318	end
 319
 320	class GooglePlayTest < Minitest::Test
 321		CustomerPlan::DB = Minitest::Mock.new
 322		Registration::Activation::GooglePlay::Finish = Minitest::Mock.new
 323
 324		def setup
 325			@customer = customer
 326			@google_play = Registration::Activation::GooglePlay.new(
 327				@customer,
 328				"abcd",
 329				"+15555550000"
 330			)
 331		end
 332
 333		def test_write
 334			Command::COMMAND_MANAGER.expect(
 335				:write,
 336				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 337					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 338				}),
 339				[Matching.new do |iq|
 340					assert_equal :form, iq.form.type
 341					assert_equal(
 342						"You've selected +15555550000 as your JMP number.",
 343						iq.form.instructions.lines.first.chomp
 344					)
 345				end]
 346			)
 347			CustomerPlan::DB.expect(
 348				:exec,
 349				OpenStruct.new(cmd_tuples: 1),
 350				[String, ["test", "test_usd", nil]]
 351			)
 352			CustomerPlan::DB.expect(
 353				:exec,
 354				OpenStruct.new(cmd_tuples: 0),
 355				[String, ["test"]]
 356			)
 357			Registration::Activation::GooglePlay::Finish.expect(
 358				:new,
 359				OpenStruct.new(write: EMPromise.reject(:test_result)),
 360				[Customer, "+15555550000"]
 361			)
 362			result = execute_command { @google_play.write.catch { |e| e } }
 363			assert_equal :test_result, result
 364			assert_mock Command::COMMAND_MANAGER
 365			assert_mock CustomerPlan::DB
 366			assert_mock Registration::Activation::GooglePlay::Finish
 367		end
 368		em :test_write
 369	end
 370
 371	class PaymentTest < Minitest::Test
 372		CustomerFinancials::BRAINTREE = Minitest::Mock.new
 373
 374		def test_for_bitcoin
 375			iq = Blather::Stanza::Iq::Command.new
 376			iq.form.fields = [
 377				{ var: "activation_method", value: "bitcoin" },
 378				{ var: "plan_name", value: "test_usd" }
 379			]
 380			result = Registration::Payment.for(iq, customer, "+15555550000")
 381			assert_kind_of Registration::Payment::Bitcoin, result
 382		end
 383
 384		def test_for_credit_card
 385			braintree_customer = Minitest::Mock.new
 386			CustomerFinancials::BRAINTREE.expect(
 387				:customer,
 388				braintree_customer
 389			)
 390			CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
 391			braintree_customer.expect(
 392				:find,
 393				EMPromise.resolve(OpenStruct.new(payment_methods: [])),
 394				["test"]
 395			)
 396			iq = Blather::Stanza::Iq::Command.new
 397			iq.from = "test@example.com"
 398			iq.form.fields = [
 399				{ var: "activation_method", value: "credit_card" },
 400				{ var: "plan_name", value: "test_usd" }
 401			]
 402			cust = customer
 403			result = execute_command do
 404				Command.execution.customer_repo.expect(:find, cust, ["test"])
 405				Registration::Payment.for(
 406					iq,
 407					cust,
 408					""
 409				).sync
 410			end
 411			assert_kind_of Registration::Payment::CreditCard, result
 412		end
 413		em :test_for_credit_card
 414
 415		def test_for_code
 416			iq = Blather::Stanza::Iq::Command.new
 417			iq.form.fields = [
 418				{ var: "activation_method", value: "code" },
 419				{ var: "plan_name", value: "test_usd" }
 420			]
 421			result = Registration::Payment.for(
 422				iq,
 423				customer,
 424				"+15555550000"
 425			)
 426			assert_kind_of Registration::Payment::InviteCode, result
 427		end
 428
 429		class BitcoinTest < Minitest::Test
 430			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
 431			CustomerFinancials::REDIS = Minitest::Mock.new
 432
 433			def setup
 434				@customer = Minitest::Mock.new(
 435					customer(plan_name: "test_usd")
 436				)
 437				@customer.expect(
 438					:add_btc_address,
 439					EMPromise.resolve("testaddr")
 440				)
 441				@bitcoin = Registration::Payment::Bitcoin.new(
 442					@customer,
 443					"+15555550000"
 444				)
 445			end
 446
 447			def test_write
 448				CustomerFinancials::REDIS.expect(
 449					:smembers,
 450					EMPromise.resolve([]),
 451					["jmp_customer_btc_addresses-test"]
 452				)
 453				blather = Minitest::Mock.new
 454				Command::COMMAND_MANAGER.expect(
 455					:write,
 456					EMPromise.reject(SessionManager::Timeout.new),
 457					[Matching.new do |reply|
 458						assert_equal :canceled, reply.status
 459						assert_equal "1.000000", reply.form.field("amount").value
 460						assert_equal "testaddr", reply.form.field("btc_addresses").value
 461						true
 462					end]
 463				)
 464				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
 465					:usd,
 466					EMPromise.resolve(BigDecimal(1))
 467				)
 468				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
 469					execute_command(blather: blather) do
 470						@bitcoin.write
 471					end
 472				end
 473				assert_mock blather
 474			end
 475			em :test_write
 476		end
 477
 478		class CreditCardTest < Minitest::Test
 479			def setup
 480				@credit_card = Registration::Payment::CreditCard.new(
 481					customer,
 482					"+15555550000"
 483				)
 484			end
 485
 486			def test_for
 487				cust = Minitest::Mock.new(customer)
 488				cust.expect(
 489					:payment_methods,
 490					EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
 491				)
 492				execute_command do
 493					Command.execution.customer_repo.expect(:find, cust, ["test"])
 494					assert_kind_of(
 495						Registration::Payment::CreditCard::Activate,
 496						Registration::Payment::CreditCard.for(
 497							cust,
 498							"+15555550000"
 499						).sync
 500					)
 501				end
 502			end
 503			em :test_for
 504
 505			def test_for_has_balance
 506				cust = Minitest::Mock.new(customer)
 507				cust.expect(:balance, 100)
 508				cust.expect(:payment_methods, EMPromise.resolve(nil))
 509				execute_command do
 510					Command.execution.customer_repo.expect(:find, cust, ["test"])
 511					assert_kind_of(
 512						Registration::BillPlan,
 513						Registration::Payment::CreditCard.for(
 514							cust,
 515							"+15555550000"
 516						).sync
 517					)
 518				end
 519			end
 520			em :test_for_has_balance
 521
 522			def test_write
 523				result = execute_command do
 524					Command::COMMAND_MANAGER.expect(
 525						:write,
 526						EMPromise.reject(:test_result),
 527						[Matching.new do |reply|
 528							assert_equal [:execute, :next, :prev], reply.allowed_actions
 529							assert_equal(
 530								"Add credit card, save, then next here to continue: " \
 531								"http://creditcard.example.com?&amount=1",
 532								reply.note.content
 533							)
 534						end]
 535					)
 536
 537					@credit_card.write.catch { |e| e }
 538				end
 539
 540				assert_equal :test_result, result
 541			end
 542			em :test_write
 543		end
 544
 545		class MailTest < Minitest::Test
 546			def setup
 547				@mail = Registration::Payment::Mail.new(
 548					customer(plan_name: "test_cad"),
 549					"+15555550000"
 550				)
 551			end
 552
 553			def test_write
 554				result = execute_command do
 555					Command::COMMAND_MANAGER.expect(
 556						:write,
 557						EMPromise.reject(:test_result),
 558						[Matching.new do |reply|
 559							assert_equal [:execute, :prev], reply.allowed_actions
 560							refute reply.form.instructions.empty?
 561							assert_equal(
 562								"A Mailing Address",
 563								reply.form.field("adr").value
 564							)
 565							assert_equal(
 566								"interac@example.com",
 567								reply.form.field("interac_email").value
 568							)
 569						end]
 570					)
 571
 572					@mail.write.catch { |e| e }
 573				end
 574
 575				assert_equal :test_result, result
 576			end
 577			em :test_write
 578		end
 579
 580		class ActivateTest < Minitest::Test
 581			Registration::Payment::CreditCard::Activate::Finish =
 582				Minitest::Mock.new
 583			Registration::Payment::CreditCard::Activate::CreditCardSale =
 584				Minitest::Mock.new
 585			Command::COMMAND_MANAGER = Minitest::Mock.new
 586
 587			def test_write
 588				customer = Minitest::Mock.new(
 589					customer(plan_name: "test_usd")
 590				)
 591				Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
 592					:create,
 593					EMPromise.resolve(nil)
 594				) do |acustomer, amount:, payment_method:|
 595					assert_operator customer, :===, acustomer
 596					assert_equal CONFIG[:activation_amount], amount
 597					assert_equal :test_default_method, payment_method
 598				end
 599				customer.expect(
 600					:bill_plan,
 601					nil,
 602					note: "Bill +15555550000 for first month"
 603				)
 604				Registration::Payment::CreditCard::Activate::Finish.expect(
 605					:new,
 606					OpenStruct.new(write: nil),
 607					[customer, "+15555550000"]
 608				)
 609				execute_command do
 610					Registration::Payment::CreditCard::Activate.new(
 611						customer,
 612						:test_default_method,
 613						"+15555550000"
 614					).write
 615				end
 616				Registration::Payment::CreditCard::Activate::CreditCardSale.verify
 617				customer.verify
 618				Registration::Payment::CreditCard::Activate::Finish.verify
 619			end
 620			em :test_write
 621
 622			def test_write_declines
 623				customer = Minitest::Mock.new(
 624					customer(plan_name: "test_usd")
 625				)
 626				iq = Blather::Stanza::Iq::Command.new
 627				iq.from = "test@example.com"
 628				msg = Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE
 629				Command::COMMAND_MANAGER.expect(
 630					:write,
 631					EMPromise.reject(:test_result),
 632					[Matching.new do |reply|
 633						assert_equal :error, reply.note_type
 634						assert_equal(
 635							"#{msg}: http://creditcard.example.com?&amount=1",
 636							reply.note.content
 637						)
 638					end]
 639				)
 640				result = execute_command do
 641					Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
 642						:create,
 643						EMPromise.reject("declined")
 644					) do |acustomer, amount:, payment_method:|
 645						assert_operator customer, :===, acustomer
 646						assert_equal CONFIG[:activation_amount], amount
 647						assert_equal :test_default_method, payment_method
 648					end
 649
 650					Registration::Payment::CreditCard::Activate.new(
 651						customer,
 652						:test_default_method,
 653						"+15555550000"
 654					).write.catch { |e| e }
 655				end
 656				assert_equal :test_result, result
 657				Registration::Payment::CreditCard::Activate::CreditCardSale.verify
 658			end
 659			em :test_write_declines
 660		end
 661
 662		class InviteCodeTest < Minitest::Test
 663			Registration::Payment::InviteCode::DB =
 664				Minitest::Mock.new
 665			Registration::Payment::InviteCode::REDIS =
 666				Minitest::Mock.new
 667			Command::COMMAND_MANAGER = Minitest::Mock.new
 668			Registration::Payment::InviteCode::Finish =
 669				Minitest::Mock.new
 670			def test_write
 671				customer = customer(plan_name: "test_usd")
 672				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 673				Registration::Payment::InviteCode::Finish.expect(
 674					:new,
 675					OpenStruct.new(write: nil),
 676					[
 677						customer,
 678						"+15555550000"
 679					]
 680				)
 681				execute_command do
 682					Registration::Payment::InviteCode::REDIS.expect(
 683						:get,
 684						EMPromise.resolve(nil),
 685						["jmp_invite_tries-test"]
 686					)
 687					Command::COMMAND_MANAGER.expect(
 688						:write,
 689						EMPromise.resolve(
 690							Blather::Stanza::Iq::Command.new.tap { |iq|
 691								iq.form.fields = [{ var: "code", value: "abc" }]
 692							}
 693						),
 694						[Matching.new do |reply|
 695							assert_equal :form, reply.form.type
 696							assert_nil reply.form.instructions
 697						end]
 698					)
 699
 700					Registration::Payment::InviteCode.new(
 701						customer,
 702						"+15555550000"
 703					).write
 704				end
 705				assert_mock Command::COMMAND_MANAGER
 706				assert_mock Registration::Payment::InviteCode::DB
 707				assert_mock Registration::Payment::InviteCode::REDIS
 708				assert_mock Registration::Payment::InviteCode::Finish
 709			end
 710			em :test_write
 711
 712			def test_write_bad_code
 713				result = execute_command do
 714					customer = customer(plan_name: "test_usd")
 715					Registration::Payment::InviteCode::REDIS.expect(
 716						:get,
 717						EMPromise.resolve(0),
 718						["jmp_invite_tries-test"]
 719					)
 720					Registration::Payment::InviteCode::DB.expect(
 721						:transaction,
 722						[]
 723					) { |&blk| blk.call }
 724					Registration::Payment::InviteCode::DB.expect(
 725						:exec,
 726						OpenStruct.new(cmd_tuples: 0),
 727						[String, ["test", "abc"]]
 728					)
 729					Registration::Payment::InviteCode::REDIS.expect(
 730						:incr,
 731						EMPromise.resolve(nil),
 732						["jmp_invite_tries-test"]
 733					)
 734					Registration::Payment::InviteCode::REDIS.expect(
 735						:expire,
 736						EMPromise.resolve(nil),
 737						["jmp_invite_tries-test", 60 * 60]
 738					)
 739					Command::COMMAND_MANAGER.expect(
 740						:write,
 741						EMPromise.resolve(
 742							Blather::Stanza::Iq::Command.new.tap { |iq|
 743								iq.form.fields = [{ var: "code", value: "abc" }]
 744							}
 745						),
 746						[Matching.new do |reply|
 747							assert_equal :form, reply.form.type
 748							assert_nil reply.form.instructions
 749						end]
 750					)
 751					Command::COMMAND_MANAGER.expect(
 752						:write,
 753						EMPromise.reject(:test_result),
 754						[Matching.new do |reply|
 755							assert_equal :form, reply.form.type
 756							assert_equal(
 757								"Not a valid invite code: abc",
 758								reply.form.instructions
 759							)
 760						end]
 761					)
 762
 763					Registration::Payment::InviteCode.new(
 764						customer,
 765						"+15555550000"
 766					).write.catch { |e| e }
 767				end
 768				assert_equal :test_result, result
 769				assert_mock Command::COMMAND_MANAGER
 770				assert_mock Registration::Payment::InviteCode::DB
 771				assert_mock Registration::Payment::InviteCode::REDIS
 772			end
 773			em :test_write_bad_code
 774
 775			def test_write_bad_code_over_limit
 776				result = execute_command do
 777					customer = customer(plan_name: "test_usd")
 778					Registration::Payment::InviteCode::REDIS.expect(
 779						:get,
 780						EMPromise.resolve(11),
 781						["jmp_invite_tries-test"]
 782					)
 783					Command::COMMAND_MANAGER.expect(
 784						:write,
 785						EMPromise.resolve(
 786							Blather::Stanza::Iq::Command.new.tap { |iq|
 787								iq.form.fields = [{ var: "code", value: "abc" }]
 788							}
 789						),
 790						[Matching.new do |reply|
 791							assert_equal :form, reply.form.type
 792							assert_nil reply.form.instructions
 793						end]
 794					)
 795					Command::COMMAND_MANAGER.expect(
 796						:write,
 797						EMPromise.reject(:test_result),
 798						[Matching.new do |reply|
 799							assert_equal :form, reply.form.type
 800							assert_equal "Too many wrong attempts", reply.form.instructions
 801						end]
 802					)
 803					Registration::Payment::InviteCode.new(
 804						customer,
 805						"+15555550000"
 806					).write.catch { |e| e }
 807				end
 808				assert_equal :test_result, result
 809				assert_mock Command::COMMAND_MANAGER
 810				assert_mock Registration::Payment::InviteCode::REDIS
 811			end
 812			em :test_write_bad_code_over_limit
 813		end
 814	end
 815
 816	class FinishTest < Minitest::Test
 817		Customer::BLATHER = Minitest::Mock.new
 818		Command::COMMAND_MANAGER = Minitest::Mock.new
 819		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
 820		Registration::Finish::REDIS = Minitest::Mock.new
 821		Registration::Finish::DB = Minitest::Mock.new
 822		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
 823		Registration::FinishOnboarding::DB = FakeDB.new
 824		Transaction::DB = Minitest::Mock.new
 825
 826		def setup
 827			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
 828			iq = Blather::Stanza::Iq::Command.new
 829			iq.from = "test\\40example.com@cheogram.com"
 830			@finish = Registration::Finish.new(
 831				customer(sgx: @sgx, plan_name: "test_usd"),
 832				"+15555550000"
 833			)
 834		end
 835
 836		def test_write
 837			create_order = stub_request(
 838				:post,
 839				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 840			).to_return(status: 201, body: <<~RESPONSE)
 841				<OrderResponse>
 842					<Order>
 843						<id>test_order</id>
 844					</Order>
 845				</OrderResponse>
 846			RESPONSE
 847			stub_request(
 848				:get,
 849				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 850			).to_return(status: 201, body: <<~RESPONSE)
 851				<OrderResponse>
 852					<OrderStatus>COMPLETE</OrderStatus>
 853					<CompletedNumbers>
 854						<TelephoneNumber>
 855							<FullNumber>5555550000</FullNumber>
 856						</TelephoneNumber>
 857					</CompletedNumbers>
 858				</OrderResponse>
 859			RESPONSE
 860			stub_request(
 861				:post,
 862				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
 863			)
 864			Registration::Finish::REDIS.expect(
 865				:del,
 866				nil,
 867				["pending_tel_for-test@example.net"]
 868			)
 869			Registration::Finish::REDIS.expect(
 870				:get,
 871				nil,
 872				["jmp_customer_pending_invite-test"]
 873			)
 874			Registration::Finish::REDIS.expect(
 875				:del,
 876				nil,
 877				["jmp_customer_pending_invite-test"]
 878			)
 879			Registration::Finish::REDIS.expect(
 880				:hget,
 881				nil,
 882				["jmp_group_codes", nil]
 883			)
 884			Bwmsgsv2Repo::REDIS.expect(
 885				:set,
 886				nil,
 887				[
 888					"catapult_fwd-+15555550000",
 889					"xmpp:test@example.net"
 890				]
 891			)
 892			Bwmsgsv2Repo::REDIS.expect(
 893				:set,
 894				nil,
 895				["catapult_fwd_timeout-customer_test@component", 25]
 896			)
 897			Customer::BLATHER.expect(
 898				:<<,
 899				nil,
 900				[Matching.new do |m|
 901					assert_equal :chat, m.type
 902					assert m.body =~ /^Welcome to JMP/
 903				end]
 904			)
 905			blather = Minitest::Mock.new
 906			blather.expect(
 907				:<<,
 908				nil,
 909				[Matching.new do |reply|
 910					assert_equal :completed, reply.status
 911					assert_equal :info, reply.note_type
 912					assert_equal(
 913						"Your JMP account has been activated as +15555550000",
 914						reply.note.content
 915					)
 916				end]
 917			)
 918			execute_command(blather: blather) do
 919				@sgx.expect(
 920					:register!,
 921					EMPromise.resolve(@sgx.with(
 922						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
 923							ibr.phone = "+15555550000"
 924						end
 925					)),
 926					["+15555550000"]
 927				)
 928
 929				@finish.write
 930			end
 931			assert_requested create_order
 932			assert_mock @sgx
 933			assert_mock Registration::Finish::REDIS
 934			assert_mock Bwmsgsv2Repo::REDIS
 935			assert_mock Customer::BLATHER
 936			assert_mock blather
 937		end
 938		em :test_write
 939
 940		def test_write_with_pending_code
 941			create_order = stub_request(
 942				:post,
 943				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 944			).to_return(status: 201, body: <<~RESPONSE)
 945				<OrderResponse>
 946					<Order>
 947						<id>test_order</id>
 948					</Order>
 949				</OrderResponse>
 950			RESPONSE
 951			stub_request(
 952				:get,
 953				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 954			).to_return(status: 201, body: <<~RESPONSE)
 955				<OrderResponse>
 956					<OrderStatus>COMPLETE</OrderStatus>
 957					<CompletedNumbers>
 958						<TelephoneNumber>
 959							<FullNumber>5555550000</FullNumber>
 960						</TelephoneNumber>
 961					</CompletedNumbers>
 962				</OrderResponse>
 963			RESPONSE
 964			stub_request(
 965				:post,
 966				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
 967			)
 968			Registration::Finish::REDIS.expect(
 969				:del,
 970				nil,
 971				["pending_tel_for-test@example.net"]
 972			)
 973			Registration::Finish::REDIS.expect(
 974				:get,
 975				EMPromise.resolve("123"),
 976				["jmp_customer_pending_invite-test"]
 977			)
 978			Registration::Finish::REDIS.expect(
 979				:del,
 980				nil,
 981				["jmp_customer_pending_invite-test"]
 982			)
 983			Registration::Finish::REDIS.expect(
 984				:hget,
 985				EMPromise.resolve("test-inviter"),
 986				["jmp_group_codes", "123"]
 987			)
 988			Registration::Finish::DB.expect(
 989				:exec,
 990				EMPromise.resolve(nil),
 991				[String, ["test-inviter", "test"]]
 992			)
 993			Transaction::DB.expect(:transaction, nil) do |&blk|
 994				blk.call
 995				true
 996			end
 997			Transaction::DB.expect(
 998				:exec,
 999				nil,
1000				[String, Matching.new { |params|
1001					assert_equal "test", params[0]
1002					assert params[1].start_with?("referral_")
1003					assert_equal 1, params[4]
1004					assert_equal "Referral Bonus", params[5]
1005				}]
1006			)
1007			Bwmsgsv2Repo::REDIS.expect(
1008				:set,
1009				nil,
1010				[
1011					"catapult_fwd-+15555550000",
1012					"xmpp:test@example.net"
1013				]
1014			)
1015			Bwmsgsv2Repo::REDIS.expect(
1016				:set,
1017				nil,
1018				["catapult_fwd_timeout-customer_test@component", 25]
1019			)
1020			Customer::BLATHER.expect(
1021				:<<,
1022				nil,
1023				[Matching.new do |m|
1024					assert_equal :chat, m.type
1025					assert m.body =~ /^Welcome to JMP/
1026				end]
1027			)
1028			blather = Minitest::Mock.new
1029			blather.expect(
1030				:<<,
1031				nil,
1032				[Matching.new do |reply|
1033					assert_equal :completed, reply.status
1034					assert_equal :info, reply.note_type
1035					assert_equal(
1036						"Your JMP account has been activated as +15555550000",
1037						reply.note.content
1038					)
1039				end]
1040			)
1041			execute_command(blather: blather) do
1042				@sgx.expect(
1043					:register!,
1044					EMPromise.resolve(@sgx.with(
1045						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1046							ibr.phone = "+15555550000"
1047						end
1048					)),
1049					["+15555550000"]
1050				)
1051
1052				@finish.write
1053			end
1054			assert_requested create_order
1055			assert_mock @sgx
1056			assert_mock Registration::Finish::REDIS
1057			assert_mock Bwmsgsv2Repo::REDIS
1058			assert_mock Customer::BLATHER
1059			assert_mock blather
1060			assert_mock Transaction::DB
1061		end
1062		em :test_write_with_pending_code
1063
1064		def test_write_onboarding
1065			create_order = stub_request(
1066				:post,
1067				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1068			).to_return(status: 201, body: <<~RESPONSE)
1069				<OrderResponse>
1070					<Order>
1071						<id>test_order</id>
1072					</Order>
1073				</OrderResponse>
1074			RESPONSE
1075			stub_request(
1076				:get,
1077				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1078			).to_return(status: 201, body: <<~RESPONSE)
1079				<OrderResponse>
1080					<OrderStatus>COMPLETE</OrderStatus>
1081					<CompletedNumbers>
1082						<TelephoneNumber>
1083							<FullNumber>5555550000</FullNumber>
1084						</TelephoneNumber>
1085					</CompletedNumbers>
1086				</OrderResponse>
1087			RESPONSE
1088			stub_request(
1089				:post,
1090				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1091			)
1092			Registration::Finish::REDIS.expect(
1093				:del,
1094				nil,
1095				["pending_tel_for-test\\40onboarding.example.com@proxy"]
1096			)
1097			Registration::Finish::REDIS.expect(
1098				:get,
1099				nil,
1100				["jmp_customer_pending_invite-test"]
1101			)
1102			Registration::Finish::REDIS.expect(
1103				:del,
1104				nil,
1105				["jmp_customer_pending_invite-test"]
1106			)
1107			Registration::Finish::REDIS.expect(
1108				:hget,
1109				nil,
1110				["jmp_group_codes", nil]
1111			)
1112			Bwmsgsv2Repo::REDIS.expect(
1113				:set,
1114				nil,
1115				[
1116					"catapult_fwd-+15555550000",
1117					"xmpp:test\\40onboarding.example.com@proxy"
1118				]
1119			)
1120			Bwmsgsv2Repo::REDIS.expect(
1121				:set,
1122				nil,
1123				["catapult_fwd_timeout-customer_test@component", 25]
1124			)
1125			result = execute_command do
1126				@sgx.expect(
1127					:register!,
1128					EMPromise.resolve(@sgx.with(
1129						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1130							ibr.phone = "+15555550000"
1131						end
1132					)),
1133					["+15555550000"]
1134				)
1135
1136				Command::COMMAND_MANAGER.expect(
1137					:write,
1138					EMPromise.reject(:test_result),
1139					[Matching.new do |iq|
1140						assert_equal :form, iq.form.type
1141						assert iq.form.field("subdomain")
1142					end]
1143				)
1144
1145				Registration::Finish.new(
1146					customer(
1147						sgx: @sgx,
1148						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1149					),
1150					"+15555550000"
1151				).write.catch { |e| e }
1152			end
1153			assert_equal :test_result, result
1154			assert_requested create_order
1155			assert_mock @sgx
1156			assert_mock Registration::Finish::REDIS
1157			assert_mock Bwmsgsv2Repo::REDIS
1158			assert_mock Command::COMMAND_MANAGER
1159		end
1160		em :test_write_onboarding
1161
1162		def test_write_tn_fail
1163			create_order = stub_request(
1164				:post,
1165				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1166			).to_return(status: 201, body: <<~RESPONSE)
1167				<OrderResponse>
1168					<Order>
1169						<id>test_order</id>
1170					</Order>
1171				</OrderResponse>
1172			RESPONSE
1173			stub_request(
1174				:get,
1175				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1176			).to_return(status: 201, body: <<~RESPONSE)
1177				<OrderResponse>
1178					<OrderStatus>FAILED</OrderStatus>
1179				</OrderResponse>
1180			RESPONSE
1181
1182			result = execute_command do
1183				Command::COMMAND_MANAGER.expect(
1184					:write,
1185					EMPromise.reject(:test_result),
1186					[Matching.new do |iq|
1187						assert_equal :form, iq.form.type
1188						assert_equal(
1189							"The JMP number +15555550000 is no longer available.",
1190							iq.form.instructions
1191						)
1192					end]
1193				)
1194
1195				@finish.write.catch { |e| e }
1196			end
1197
1198			assert_equal :test_result, result
1199			assert_mock Command::COMMAND_MANAGER
1200			assert_instance_of(
1201				TelSelections::ChooseTel,
1202				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1203			)
1204			assert_requested create_order
1205		end
1206		em :test_write_tn_fail
1207	end
1208
1209	class SnikketTest < Minitest::Test
1210		Command::COMMAND_MANAGER = Minitest::Mock.new
1211		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1212
1213		def setup
1214			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
1215			@snikket = Registration::FinishOnboarding::Snikket.new(
1216				customer,
1217				"+15555550000",
1218				db: FakeDB.new
1219			)
1220		end
1221
1222		def test_write
1223			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1224
1225			subdomain_form = Blather::Stanza::Iq::Command.new
1226			subdomain_form.form.fields = [
1227				{ var: "subdomain", value: "test" }
1228			]
1229
1230			launched = Snikket::Launched.new
1231			launched << Niceogiri::XML::Node.new(
1232				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1233			).tap { |inner|
1234				inner << Niceogiri::XML::Node.new(
1235					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1236				).tap { |id|
1237					id.content = "si-1234"
1238				}
1239				inner << Niceogiri::XML::Node.new(
1240					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1241				).tap { |bootstrap|
1242					bootstrap << Niceogiri::XML::Node.new(
1243						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1244					).tap { |token|
1245						token.content = "TOKEN"
1246					}
1247				}
1248			}
1249
1250			blather = Minitest::Mock.new
1251			blather.expect(
1252				:<<,
1253				nil,
1254				[Matching.new do |reply|
1255					assert_equal :completed, reply.status
1256					assert_equal(
1257						xmpp_uri,
1258						OOB.find_or_create(reply.command).url
1259					)
1260				end]
1261			)
1262
1263			execute_command(blather: blather) do
1264				Command::COMMAND_MANAGER.expect(
1265					:write,
1266					EMPromise.resolve(subdomain_form),
1267					[Matching.new do |iq|
1268						assert_equal :form, iq.form.type
1269						assert iq.form.field("subdomain")
1270					end]
1271				)
1272
1273				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1274					:write,
1275					EMPromise.resolve(launched),
1276					[Matching.new do |iq|
1277						assert_equal :set, iq.type
1278						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1279						assert_equal(
1280							"test.snikket.chat",
1281							iq.xpath(
1282								"./ns:launch/ns:domain",
1283								ns: "xmpp:snikket.org/hosting/v1"
1284							).text
1285						)
1286					end]
1287				)
1288
1289				# Webmock doesn't support redirects properly, but they work live
1290				stub_request(
1291					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1292				).to_return(
1293					status: 200,
1294					headers: {
1295						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1296					}
1297				)
1298
1299				@snikket.write
1300			end
1301
1302			assert_mock Command::COMMAND_MANAGER
1303			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1304			assert_mock blather
1305		end
1306		em :test_write
1307
1308		def test_write_not_yet
1309			subdomain_form = Blather::Stanza::Iq::Command.new
1310			subdomain_form.form.fields = [
1311				{ var: "subdomain", value: "test" }
1312			]
1313
1314			launched = Snikket::Launched.new
1315			launched << Niceogiri::XML::Node.new(
1316				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1317			).tap { |inner|
1318				inner << Niceogiri::XML::Node.new(
1319					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1320				).tap { |id|
1321					id.content = "si-1234"
1322				}
1323				inner << Niceogiri::XML::Node.new(
1324					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1325				).tap { |bootstrap|
1326					bootstrap << Niceogiri::XML::Node.new(
1327						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1328					).tap { |token|
1329						token.content = "TOKEN"
1330					}
1331				}
1332			}
1333
1334			result = execute_command do
1335				Command::COMMAND_MANAGER.expect(
1336					:write,
1337					EMPromise.resolve(subdomain_form),
1338					[Matching.new do |iq|
1339						assert_equal :form, iq.form.type
1340						assert iq.form.field("subdomain")
1341					end]
1342				)
1343
1344				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1345					:write,
1346					EMPromise.resolve(launched),
1347					[Matching.new do |iq|
1348						assert_equal :set, iq.type
1349						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1350						assert_equal(
1351							"test.snikket.chat",
1352							iq.xpath(
1353								"./ns:launch/ns:domain",
1354								ns: "xmpp:snikket.org/hosting/v1"
1355							).text
1356						)
1357					end]
1358				)
1359
1360				stub_request(
1361					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1362				).to_timeout
1363
1364				Command::COMMAND_MANAGER.expect(
1365					:write,
1366					EMPromise.reject(:test_result),
1367					[Matching.new do |iq|
1368						assert_equal :result, iq.form.type
1369						assert iq.form.instructions =~ / test\.snikket\.chat /
1370						assert_equal "jid-single", iq.form.field("support").type
1371					end]
1372				)
1373
1374				@snikket.write.catch { |e| e }
1375			end
1376
1377			assert_equal :test_result, result
1378			assert_mock Command::COMMAND_MANAGER
1379			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1380		end
1381		em :test_write_not_yet
1382
1383		def test_write_already_taken
1384			subdomain_form = Blather::Stanza::Iq::Command.new
1385			subdomain_form.form.fields = [
1386				{ var: "subdomain", value: "test" }
1387			]
1388
1389			launched = Snikket::Launched.new.as_error(
1390				"internal-server-error",
1391				:wait,
1392				"This is an error"
1393			)
1394
1395			result = execute_command do
1396				Command::COMMAND_MANAGER.expect(
1397					:write,
1398					EMPromise.resolve(subdomain_form),
1399					[Matching.new do |iq|
1400						assert_equal :form, iq.form.type
1401						assert iq.form.field("subdomain")
1402					end]
1403				)
1404
1405				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1406					:write,
1407					EMPromise.reject(launched),
1408					[Matching.new do |iq|
1409						assert_equal :set, iq.type
1410						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1411						assert_equal(
1412							"test.snikket.chat",
1413							iq.xpath(
1414								"./ns:launch/ns:domain",
1415								ns: "xmpp:snikket.org/hosting/v1"
1416							).text
1417						)
1418					end]
1419				)
1420
1421				stub_request(
1422					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1423				).to_timeout
1424
1425				Command::COMMAND_MANAGER.expect(
1426					:write,
1427					EMPromise.reject(:test_result),
1428					[Matching.new do |iq|
1429						assert iq.executing?
1430						assert_equal(
1431							"This is an error",
1432							iq.form.field("subdomain").desc
1433						)
1434					end]
1435				)
1436
1437				@snikket.write.catch { |e| e }
1438			end
1439
1440			assert_equal :test_result, result
1441			assert_mock Command::COMMAND_MANAGER
1442			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1443		end
1444		em :test_write_already_taken
1445	end
1446end