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(
  33			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  34		)
  35		web_manager.set("test@example.net", "+15555550000")
  36		result = execute_command do
  37			sgx = OpenStruct.new(registered?: false)
  38			Registration.for(
  39				customer(
  40					plan_name: "test_usd",
  41					expires_at: Time.now + 999,
  42					sgx: sgx
  43				),
  44				nil,
  45				web_manager
  46			)
  47		end
  48		assert_kind_of Registration::Finish, result
  49		assert_requested reservation_req
  50	end
  51	em :test_for_activated
  52
  53	def test_for_not_activated_approved
  54		sgx = OpenStruct.new(registered?: false)
  55		web_manager = TelSelections.new(
  56			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  57		)
  58		web_manager.set("test\\40approved.example.com@component", "+15555550000")
  59		iq = Blather::Stanza::Iq::Command.new
  60		iq.from = "test@approved.example.com"
  61		result = execute_command(iq) do
  62			Registration::Activation.for(
  63				customer(
  64					sgx: sgx,
  65					jid: Blather::JID.new("test\\40approved.example.com@component")
  66				),
  67				nil,
  68				web_manager
  69			)
  70		end
  71		assert_kind_of Registration::Activation::Allow, result
  72	end
  73	em :test_for_not_activated_approved
  74
  75	def test_for_not_activated_googleplay
  76		sgx = OpenStruct.new(registered?: false)
  77		web_manager = TelSelections.new(
  78			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  79		)
  80		web_manager.set("test@example.net", "+15555550000")
  81		iq = Blather::Stanza::Iq::Command.new
  82		iq.from = "test@approved.example.com"
  83		result = execute_command(iq) do
  84			Registration::Activation.for(
  85				customer(sgx: sgx),
  86				"GARBLEDYGOOK==",
  87				web_manager
  88			)
  89		end
  90		assert_kind_of Registration::Activation::GooglePlay, result
  91	end
  92	em :test_for_not_activated_googleplay
  93
  94	def test_for_not_activated_with_customer_id
  95		sgx = OpenStruct.new(registered?: false)
  96		web_manager = TelSelections.new(
  97			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  98		)
  99		web_manager.set("test@example.net", "+15555550000")
 100		iq = Blather::Stanza::Iq::Command.new
 101		iq.from = "test@example.com"
 102		result = execute_command(iq) do
 103			Registration::Activation.for(
 104				customer(sgx: sgx),
 105				nil,
 106				web_manager
 107			)
 108		end
 109		assert_kind_of Registration::Activation, result
 110	end
 111	em :test_for_not_activated_with_customer_id
 112
 113	class ActivationTest < Minitest::Test
 114		Registration::Activation::DB = Minitest::Mock.new
 115		Registration::Activation::REDIS = FakeRedis.new(
 116			"jmp_parent_codes" => {
 117				"PARENT_CODE" => "1",
 118				"PARENT_TOMB" => "2",
 119				"PARENT_MANY_SUBACCOUNTS" => "many_subaccounts"
 120			},
 121			"jmp_customer_trust_level-2" => "Tomb"
 122		)
 123		Registration::Activation::Payment = Minitest::Mock.new
 124		Registration::Activation::Finish = Minitest::Mock.new
 125		Command::COMMAND_MANAGER = Minitest::Mock.new
 126
 127		def setup
 128			@customer = Minitest::Mock.new(customer)
 129			@activation = Registration::Activation.new(@customer, "+15555550000")
 130		end
 131
 132		def test_write
 133			Command::COMMAND_MANAGER.expect(
 134				:write,
 135				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 136					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 137				}),
 138				[Matching.new do |iq|
 139					assert_equal :form, iq.form.type
 140					assert_equal(
 141						"You've selected +15555550000 as your JMP number.",
 142						iq.form.instructions.lines.first.chomp
 143					)
 144				end]
 145			)
 146			@customer.expect(:with_plan, @customer) do |*args, **|
 147				assert_equal ["test_usd"], args
 148			end
 149			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 150			Registration::Activation::Payment.expect(
 151				:for,
 152				EMPromise.reject(:test_result),
 153				[Blather::Stanza::Iq, @customer, "+15555550000"]
 154			)
 155			assert_equal(
 156				:test_result,
 157				execute_command { @activation.write.catch { |e| e } }
 158			)
 159			assert_mock Command::COMMAND_MANAGER
 160			assert_mock @customer
 161			assert_mock Registration::Activation::Payment
 162		end
 163		em :test_write
 164
 165		def test_write_bad_plan
 166			Command::COMMAND_MANAGER.expect(
 167				:write,
 168				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 169					iq.form.fields = [{ var: "plan_name", value: "test_usd_no_register" }]
 170				}),
 171				[Matching.new do |iq|
 172					assert_equal :form, iq.form.type
 173					assert_equal(
 174						"You've selected +15555550000 as your JMP number.",
 175						iq.form.instructions.lines.first.chomp
 176					)
 177				end]
 178			)
 179			assert_equal(
 180				"No registration plan by that name",
 181				execute_command { @activation.write.catch { |e| e } }.message
 182			)
 183			assert_mock Command::COMMAND_MANAGER
 184			assert_mock @customer
 185		end
 186		em :test_write_bad_plan
 187
 188		def test_write_with_code
 189			Command::COMMAND_MANAGER.expect(
 190				:write,
 191				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 192					iq.form.fields = [
 193						{ var: "plan_name", value: "test_usd" },
 194						{ var: "code", value: "123" }
 195					]
 196				}),
 197				[Matching.new do |iq|
 198					assert_equal :form, iq.form.type
 199					assert_equal(
 200						"You've selected +15555550000 as your JMP number.",
 201						iq.form.instructions.lines.first.chomp
 202					)
 203				end]
 204			)
 205			@customer.expect(:with_plan, @customer) do |*args, **|
 206				assert_equal ["test_usd"], args
 207			end
 208			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 209			@customer.expect(:activate_plan_starting_now, EMPromise.resolve(nil), [])
 210			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 211			Registration::Activation::DB.expect(
 212				:exec,
 213				OpenStruct.new(cmd_tuples: 1),
 214				[String, ["test", "123"]]
 215			)
 216			Registration::Activation::Finish.expect(
 217				:new,
 218				OpenStruct.new(write: EMPromise.reject(:test_result)),
 219				[@customer, "+15555550000"]
 220			)
 221			assert_equal(
 222				:test_result,
 223				execute_command { @activation.write.catch { |e| e } }
 224			)
 225			assert_mock Command::COMMAND_MANAGER
 226			assert_mock @customer
 227			assert_mock Registration::Activation::Payment
 228			assert_mock Registration::Activation::DB
 229		end
 230		em :test_write_with_code
 231
 232		def test_write_with_group_code
 233			Command::COMMAND_MANAGER.expect(
 234				:write,
 235				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 236					iq.form.fields = [
 237						{ var: "plan_name", value: "test_usd" },
 238						{ var: "code", value: "123" }
 239					]
 240				}),
 241				[Matching.new do |iq|
 242					assert_equal :form, iq.form.type
 243					assert_equal(
 244						"You've selected +15555550000 as your JMP number.",
 245						iq.form.instructions.lines.first.chomp
 246					)
 247				end]
 248			)
 249			@customer.expect(:with_plan, @customer) do |*args, **|
 250				assert_equal ["test_usd"], args
 251			end
 252			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 253			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 254			Registration::Activation::DB.expect(
 255				:exec,
 256				OpenStruct.new(cmd_tuples: 0),
 257				[String, ["test", "123"]]
 258			)
 259			Registration::Activation::Payment.expect(
 260				:for,
 261				EMPromise.reject(:test_result),
 262				[Blather::Stanza::Iq, @customer, "+15555550000"]
 263			)
 264			assert_equal(
 265				:test_result,
 266				execute_command { @activation.write.catch { |e| e } }
 267			)
 268			assert_equal(
 269				"123",
 270				Registration::Activation::REDIS.get(
 271					"jmp_customer_pending_invite-test"
 272				).sync
 273			)
 274			assert_mock Command::COMMAND_MANAGER
 275			assert_mock @customer
 276			assert_mock Registration::Activation::Payment
 277			assert_mock Registration::Activation::DB
 278		end
 279		em :test_write_with_group_code
 280
 281		def test_write_with_parent_code
 282			Command::COMMAND_MANAGER.expect(
 283				:write,
 284				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 285					iq.form.fields = [
 286						{ var: "plan_name", value: "test_usd" },
 287						{ var: "code", value: "PARENT_CODE" }
 288					]
 289				}),
 290				[Matching.new do |iq|
 291					assert_equal :form, iq.form.type
 292					assert_equal(
 293						"You've selected +15555550000 as your JMP number.",
 294						iq.form.instructions.lines.first.chomp
 295					)
 296				end]
 297			)
 298			Registration::Activation::DB.expect(
 299				:query_one, {}, [String, "1"], default: {}
 300			)
 301			Registration::Activation::DB.expect(
 302				:query_one, { c: 0 }, [String, "1"], default: { c: 0 }
 303			)
 304			@customer.expect(:with_plan, @customer) do |*args, **kwargs|
 305				assert_equal ["test_usd"], args
 306				assert_equal({ parent_customer_id: "1" }, kwargs)
 307			end
 308			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 309			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 310			Registration::Activation::DB.expect(
 311				:exec,
 312				OpenStruct.new(cmd_tuples: 0),
 313				[String, ["test", "PARENT_CODE"]]
 314			)
 315			Registration::Activation::Payment.expect(
 316				:for,
 317				EMPromise.reject(:test_result),
 318				[Blather::Stanza::Iq, @customer, "+15555550000"]
 319			)
 320			assert_equal(
 321				:test_result,
 322				execute_command { @activation.write.catch { |e| e } }
 323			)
 324			assert_mock Command::COMMAND_MANAGER
 325			assert_mock @customer
 326			assert_mock Registration::Activation::Payment
 327			assert_mock Registration::Activation::DB
 328		end
 329		em :test_write_with_parent_code
 330
 331		def test_write_with_parent_code_tombed_parent
 332			Command::COMMAND_MANAGER.expect(
 333				:write,
 334				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 335					iq.form.fields = [
 336						{ var: "plan_name", value: "test_usd" },
 337						{ var: "code", value: "PARENT_TOMB" }
 338					]
 339				}),
 340				[Matching.new do |iq|
 341					assert_equal :form, iq.form.type
 342					assert_equal(
 343						"You've selected +15555550000 as your JMP number.",
 344						iq.form.instructions.lines.first.chomp
 345					)
 346				end]
 347			)
 348			Registration::Activation::DB.expect(
 349				:query_one, {}, [String, "2"], default: {}
 350			)
 351			Registration::Activation::DB.expect(
 352				:query_one, { c: 0 }, [String, "2"], default: { c: 0 }
 353			)
 354			assert_equal(
 355				"Please contact support to create a subaccount",
 356				execute_command { @activation.write.catch(&:to_s) }
 357			)
 358			assert_mock Command::COMMAND_MANAGER
 359			assert_mock @customer
 360			assert_mock Registration::Activation::Payment
 361			assert_mock Registration::Activation::DB
 362		end
 363		em :test_write_with_parent_code_tombed_parent
 364
 365		def test_write_with_parent_code_too_many
 366			Command::COMMAND_MANAGER.expect(
 367				:write,
 368				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 369					iq.form.fields = [
 370						{ var: "plan_name", value: "test_usd" },
 371						{ var: "code", value: "PARENT_MANY_SUBACCOUNTS" }
 372					]
 373				}),
 374				[Matching.new do |iq|
 375					assert_equal :form, iq.form.type
 376					assert_equal(
 377						"You've selected +15555550000 as your JMP number.",
 378						iq.form.instructions.lines.first.chomp
 379					)
 380				end]
 381			)
 382			Registration::Activation::DB.expect(
 383				:query_one, {}, [String, "many_subaccounts"], default: {}
 384			)
 385			Registration::Activation::DB.expect(
 386				:query_one, { c: 2 }, [String, "many_subaccounts"], default: { c: 0 }
 387			)
 388			assert_equal(
 389				"Please contact support to create a subaccount",
 390				execute_command { @activation.write.catch(&:to_s) }
 391			)
 392			assert_mock Command::COMMAND_MANAGER
 393			assert_mock @customer
 394			assert_mock Registration::Activation::Payment
 395			assert_mock Registration::Activation::DB
 396		end
 397		em :test_write_with_parent_code_too_many
 398	end
 399
 400	class AllowTest < Minitest::Test
 401		Command::COMMAND_MANAGER = Minitest::Mock.new
 402		Registration::Activation::Allow::DB = Minitest::Mock.new
 403
 404		def test_write_credit_to_nil
 405			cust = Minitest::Mock.new(customer("test"))
 406			allow = Registration::Activation::Allow.new(cust, "+15555550000", nil)
 407
 408			Command::COMMAND_MANAGER.expect(
 409				:write,
 410				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 411					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 412				}),
 413				[Matching.new do |iq|
 414					assert_equal :form, iq.form.type
 415					assert_equal(
 416						"You've selected +15555550000 as your JMP number.",
 417						iq.form.instructions.lines.first.chomp
 418					)
 419					assert_equal 1, iq.form.fields.length
 420				end]
 421			)
 422			Registration::Activation::Allow::DB.expect(
 423				:transaction,
 424				EMPromise.reject(:test_result)
 425			) do |&blk|
 426				blk.call
 427				true
 428			end
 429			cust.expect(:with_plan, cust, ["test_usd"])
 430			cust.expect(:activate_plan_starting_now, nil)
 431			assert_equal(
 432				:test_result,
 433				execute_command { allow.write.catch { |e| e } }
 434			)
 435			assert_mock Command::COMMAND_MANAGER
 436		end
 437		em :test_write_credit_to_nil
 438
 439		def test_write_credit_to_refercust
 440			cust = Minitest::Mock.new(customer("test"))
 441			allow = Registration::Activation::Allow.new(
 442				cust, "+15555550000", "refercust"
 443			)
 444
 445			Command::COMMAND_MANAGER.expect(
 446				:write,
 447				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 448					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 449				}),
 450				[Matching.new do |iq|
 451					assert_equal :form, iq.form.type
 452					assert_equal(
 453						"You've selected +15555550000 as your JMP number.",
 454						iq.form.instructions.lines.first.chomp
 455					)
 456					assert_equal 1, iq.form.fields.length
 457				end]
 458			)
 459			Registration::Activation::Allow::DB.expect(
 460				:transaction,
 461				EMPromise.reject(:test_result)
 462			) do |&blk|
 463				blk.call
 464				true
 465			end
 466			Registration::Activation::Allow::DB.expect(
 467				:exec,
 468				nil,
 469				[String, ["refercust", "test"]]
 470			)
 471			cust.expect(:with_plan, cust, ["test_usd"])
 472			cust.expect(:activate_plan_starting_now, nil)
 473			assert_equal(
 474				:test_result,
 475				execute_command { allow.write.catch { |e| e } }
 476			)
 477			assert_mock Command::COMMAND_MANAGER
 478		end
 479		em :test_write_credit_to_refercust
 480	end
 481
 482	class GooglePlayTest < Minitest::Test
 483		CustomerPlan::DB = Minitest::Mock.new
 484		Registration::Activation::GooglePlay::Finish = Minitest::Mock.new
 485
 486		def setup
 487			@customer = customer
 488			@google_play = Registration::Activation::GooglePlay.new(
 489				@customer,
 490				"abcd",
 491				"+15555550000"
 492			)
 493		end
 494
 495		def test_write
 496			Command::COMMAND_MANAGER.expect(
 497				:write,
 498				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 499					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 500				}),
 501				[Matching.new do |iq|
 502					assert_equal :form, iq.form.type
 503					assert_equal(
 504						"You've selected +15555550000 as your JMP number.",
 505						iq.form.instructions.lines.first.chomp
 506					)
 507				end]
 508			)
 509			CustomerPlan::DB.expect(
 510				:exec,
 511				OpenStruct.new(cmd_tuples: 1),
 512				[String, ["test", "test_usd", nil]]
 513			)
 514			CustomerPlan::DB.expect(
 515				:exec,
 516				OpenStruct.new(cmd_tuples: 0),
 517				[String, ["test"]]
 518			)
 519			Registration::Activation::GooglePlay::Finish.expect(
 520				:new,
 521				OpenStruct.new(write: EMPromise.reject(:test_result)),
 522				[Customer, "+15555550000"]
 523			)
 524			result = execute_command { @google_play.write.catch { |e| e } }
 525			assert_equal :test_result, result
 526			assert_mock Command::COMMAND_MANAGER
 527			assert_mock CustomerPlan::DB
 528			assert_mock Registration::Activation::GooglePlay::Finish
 529		end
 530		em :test_write
 531	end
 532
 533	class PaymentTest < Minitest::Test
 534		CustomerFinancials::BRAINTREE = Minitest::Mock.new
 535
 536		def test_for_bitcoin
 537			iq = Blather::Stanza::Iq::Command.new
 538			iq.form.fields = [
 539				{ var: "activation_method", value: "bitcoin" },
 540				{ var: "plan_name", value: "test_usd" }
 541			]
 542			result = Registration::Payment.for(iq, customer, "+15555550000")
 543			assert_kind_of Registration::Payment::Bitcoin, result
 544		end
 545
 546		def test_for_credit_card
 547			braintree_customer = Minitest::Mock.new
 548			CustomerFinancials::BRAINTREE.expect(
 549				:customer,
 550				braintree_customer
 551			)
 552			CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
 553			braintree_customer.expect(
 554				:find,
 555				EMPromise.resolve(OpenStruct.new(payment_methods: [])),
 556				["test"]
 557			)
 558			iq = Blather::Stanza::Iq::Command.new
 559			iq.from = "test@example.com"
 560			iq.form.fields = [
 561				{ var: "activation_method", value: "credit_card" },
 562				{ var: "plan_name", value: "test_usd" }
 563			]
 564			cust = customer
 565			result = execute_command do
 566				Command.execution.customer_repo.expect(:find, cust, ["test"])
 567				Registration::Payment.for(
 568					iq,
 569					cust,
 570					""
 571				).sync
 572			end
 573			assert_kind_of Registration::Payment::CreditCard, result
 574		end
 575		em :test_for_credit_card
 576
 577		def test_for_code
 578			iq = Blather::Stanza::Iq::Command.new
 579			iq.form.fields = [
 580				{ var: "activation_method", value: "code" },
 581				{ var: "plan_name", value: "test_usd" }
 582			]
 583			cust = customer
 584			result = execute_command do
 585				Command.execution.customer_repo.expect(:find, cust, ["test"])
 586				Registration::Payment.for(
 587					iq,
 588					cust,
 589					"+15555550000"
 590				)
 591			end
 592			assert_kind_of Registration::Payment::InviteCode, result
 593		end
 594		em :test_for_code
 595
 596		class BitcoinTest < Minitest::Test
 597			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
 598			CustomerFinancials::REDIS = Minitest::Mock.new
 599
 600			def setup
 601				@customer = Minitest::Mock.new(
 602					customer(plan_name: "test_usd")
 603				)
 604				@customer.expect(
 605					:add_btc_address,
 606					EMPromise.resolve("testaddr")
 607				)
 608				@bitcoin = Registration::Payment::Bitcoin.new(
 609					@customer,
 610					"+15555550000"
 611				)
 612			end
 613
 614			def test_write
 615				CustomerFinancials::REDIS.expect(
 616					:smembers,
 617					EMPromise.resolve([]),
 618					["jmp_customer_btc_addresses-test"]
 619				)
 620				blather = Minitest::Mock.new
 621				Command::COMMAND_MANAGER.expect(
 622					:write,
 623					EMPromise.reject(SessionManager::Timeout.new),
 624					[Matching.new do |reply|
 625						assert_equal :canceled, reply.status
 626						assert_equal "1.000000", reply.form.field("amount").value
 627						assert_equal "testaddr", reply.form.field("btc_addresses").value
 628						true
 629					end]
 630				)
 631				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
 632					:usd,
 633					EMPromise.resolve(BigDecimal(1))
 634				)
 635				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
 636					execute_command(blather: blather) do
 637						@bitcoin.write
 638					end
 639				end
 640				assert_mock blather
 641			end
 642			em :test_write
 643		end
 644
 645		class CreditCardTest < Minitest::Test
 646			def setup
 647				@credit_card = Registration::Payment::CreditCard.new(
 648					customer,
 649					"+15555550000"
 650				)
 651			end
 652
 653			def test_for
 654				cust = Minitest::Mock.new(customer)
 655				cust.expect(
 656					:payment_methods,
 657					EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
 658				)
 659				execute_command do
 660					Command.execution.customer_repo.expect(:find, cust, ["test"])
 661					assert_kind_of(
 662						Registration::Payment::CreditCard::Activate,
 663						Registration::Payment::CreditCard.for(
 664							cust,
 665							"+15555550000"
 666						).sync
 667					)
 668				end
 669			end
 670			em :test_for
 671
 672			def test_for_has_balance
 673				cust = Minitest::Mock.new(customer)
 674				cust.expect(:balance, 100)
 675				cust.expect(:payment_methods, EMPromise.resolve(nil))
 676				execute_command do
 677					Command.execution.customer_repo.expect(:find, cust, ["test"])
 678					assert_kind_of(
 679						Registration::BillPlan,
 680						Registration::Payment::CreditCard.for(
 681							cust,
 682							"+15555550000"
 683						).sync
 684					)
 685				end
 686			end
 687			em :test_for_has_balance
 688
 689			def test_write
 690				result = execute_command do
 691					Command::COMMAND_MANAGER.expect(
 692						:write,
 693						EMPromise.reject(:test_result),
 694						[Matching.new do |reply|
 695							assert_equal [:execute, :next, :prev], reply.allowed_actions
 696							assert_equal(
 697								"Add credit card, save, then next here to continue: " \
 698								"http://creditcard.example.com?&amount=1",
 699								reply.note.content
 700							)
 701						end]
 702					)
 703
 704					@credit_card.write.catch { |e| e }
 705				end
 706
 707				assert_equal :test_result, result
 708			end
 709			em :test_write
 710		end
 711
 712		class MailTest < Minitest::Test
 713			def setup
 714				@mail = Registration::Payment::Mail.new(
 715					customer(plan_name: "test_cad"),
 716					"+15555550000"
 717				)
 718			end
 719
 720			def test_write
 721				result = execute_command do
 722					Command::COMMAND_MANAGER.expect(
 723						:write,
 724						EMPromise.reject(:test_result),
 725						[Matching.new do |reply|
 726							assert_equal [:execute, :prev], reply.allowed_actions
 727							refute reply.form.instructions.empty?
 728							assert_equal(
 729								"A Mailing Address",
 730								reply.form.field("adr").value
 731							)
 732							assert_equal(
 733								"interac@example.com",
 734								reply.form.field("interac_email").value
 735							)
 736						end]
 737					)
 738
 739					@mail.write.catch { |e| e }
 740				end
 741
 742				assert_equal :test_result, result
 743			end
 744			em :test_write
 745		end
 746
 747		class ActivateTest < Minitest::Test
 748			Registration::Payment::CreditCard::Activate::Finish =
 749				Minitest::Mock.new
 750			Registration::Payment::CreditCard::Activate::CreditCardSale =
 751				Minitest::Mock.new
 752			Command::COMMAND_MANAGER = Minitest::Mock.new
 753
 754			def test_write
 755				customer = Minitest::Mock.new(
 756					customer(plan_name: "test_usd")
 757				)
 758				Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
 759					:create,
 760					EMPromise.resolve(nil)
 761				) do |acustomer, amount:, payment_method:|
 762					assert_operator customer, :===, acustomer
 763					assert_equal CONFIG[:activation_amount], amount
 764					assert_equal :test_default_method, payment_method
 765				end
 766				customer.expect(
 767					:bill_plan,
 768					nil,
 769					note: "Bill +15555550000 for first month"
 770				)
 771				Registration::Payment::CreditCard::Activate::Finish.expect(
 772					:new,
 773					OpenStruct.new(write: nil),
 774					[customer, "+15555550000"]
 775				)
 776				execute_command do
 777					Registration::Payment::CreditCard::Activate.new(
 778						customer,
 779						:test_default_method,
 780						"+15555550000"
 781					).write
 782				end
 783				Registration::Payment::CreditCard::Activate::CreditCardSale.verify
 784				customer.verify
 785				Registration::Payment::CreditCard::Activate::Finish.verify
 786			end
 787			em :test_write
 788
 789			def test_write_declines
 790				customer = Minitest::Mock.new(
 791					customer(plan_name: "test_usd")
 792				)
 793				iq = Blather::Stanza::Iq::Command.new
 794				iq.from = "test@example.com"
 795				msg = Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE
 796				Command::COMMAND_MANAGER.expect(
 797					:write,
 798					EMPromise.reject(:test_result),
 799					[Matching.new do |reply|
 800						assert_equal :error, reply.note_type
 801						assert_equal(
 802							"#{msg}: http://creditcard.example.com?&amount=1",
 803							reply.note.content
 804						)
 805					end]
 806				)
 807				result = execute_command do
 808					Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
 809						:create,
 810						EMPromise.reject("declined")
 811					) do |acustomer, amount:, payment_method:|
 812						assert_operator customer, :===, acustomer
 813						assert_equal CONFIG[:activation_amount], amount
 814						assert_equal :test_default_method, payment_method
 815					end
 816
 817					Registration::Payment::CreditCard::Activate.new(
 818						customer,
 819						:test_default_method,
 820						"+15555550000"
 821					).write.catch { |e| e }
 822				end
 823				assert_equal :test_result, result
 824				Registration::Payment::CreditCard::Activate::CreditCardSale.verify
 825			end
 826			em :test_write_declines
 827		end
 828
 829		class InviteCodeTest < Minitest::Test
 830			Registration::Payment::InviteCode::DB =
 831				Minitest::Mock.new
 832			Registration::Payment::InviteCode::REDIS =
 833				Minitest::Mock.new
 834			Command::COMMAND_MANAGER = Minitest::Mock.new
 835			Registration::Payment::InviteCode::Finish =
 836				Minitest::Mock.new
 837			Registration::Payment::InviteCode::BillPlan =
 838				Minitest::Mock.new
 839
 840			def test_write
 841				customer = customer(plan_name: "test_usd")
 842				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 843				Registration::Payment::InviteCode::Finish.expect(
 844					:new,
 845					OpenStruct.new(write: nil),
 846					[
 847						customer,
 848						"+15555550000"
 849					]
 850				)
 851				execute_command do
 852					Registration::Payment::InviteCode::REDIS.expect(
 853						:get,
 854						EMPromise.resolve(nil),
 855						["jmp_invite_tries-test"]
 856					)
 857					Registration::Payment::InviteCode::REDIS.expect(
 858						:hget,
 859						EMPromise.resolve(nil),
 860						["jmp_parent_codes", "abc"]
 861					)
 862					Command::COMMAND_MANAGER.expect(
 863						:write,
 864						EMPromise.resolve(
 865							Blather::Stanza::Iq::Command.new.tap { |iq|
 866								iq.form.fields = [{ var: "code", value: "abc" }]
 867							}
 868						),
 869						[Matching.new do |reply|
 870							assert_equal :form, reply.form.type
 871							assert_nil reply.form.instructions
 872						end]
 873					)
 874
 875					Registration::Payment::InviteCode.new(
 876						customer,
 877						"+15555550000"
 878					).write
 879				end
 880				assert_mock Command::COMMAND_MANAGER
 881				assert_mock Registration::Payment::InviteCode::DB
 882				assert_mock Registration::Payment::InviteCode::REDIS
 883				assert_mock Registration::Payment::InviteCode::Finish
 884			end
 885			em :test_write
 886
 887			def test_write_parent_code
 888				customer = customer(plan_name: "test_usd")
 889				Registration::Payment::InviteCode::BillPlan.expect(
 890					:new,
 891					OpenStruct.new(write: nil)
 892				) { |*| true }
 893				Registration::Payment::InviteCode::DB.expect(
 894					:query_one, {}, [String, "parent_customer"], default: {}
 895				)
 896				Registration::Payment::InviteCode::DB.expect(
 897					:query_one, { c: 0 }, [String, "parent_customer"], default: { c: 0 }
 898				)
 899				execute_command do
 900					Registration::Payment::InviteCode::REDIS.expect(
 901						:hget,
 902						EMPromise.resolve("parent_customer"),
 903						["jmp_parent_codes", "pabc"]
 904					)
 905					Registration::Payment::InviteCode::REDIS.expect(
 906						:get,
 907						EMPromise.resolve(nil),
 908						["jmp_customer_trust_level-parent_customer"]
 909					)
 910					CustomerPlan::DB.expect(
 911						:query,
 912						[{ "plan_name" => "test_usd" }],
 913						[String, ["parent_customer"]]
 914					)
 915					CustomerPlan::DB.expect(
 916						:exec_defer,
 917						EMPromise.resolve(nil),
 918						[String, ["test", "test_usd", "parent_customer"]]
 919					)
 920					Command.execution.customer_repo.expect(
 921						:find,
 922						customer.with_balance(10000),
 923						["test"]
 924					)
 925					Command::COMMAND_MANAGER.expect(
 926						:write,
 927						EMPromise.resolve(
 928							Blather::Stanza::Iq::Command.new.tap { |iq|
 929								iq.form.fields = [{ var: "code", value: "pabc" }]
 930							}
 931						),
 932						[Matching.new do |reply|
 933							assert_equal :form, reply.form.type
 934							assert_nil reply.form.instructions
 935						end]
 936					)
 937
 938					Registration::Payment::InviteCode.new(
 939						customer,
 940						"+15555550000"
 941					).write
 942				end
 943				assert_mock Command::COMMAND_MANAGER
 944				assert_mock Registration::Payment::InviteCode::DB
 945				assert_mock Registration::Payment::InviteCode::REDIS
 946				assert_mock Registration::Payment::InviteCode::BillPlan
 947			end
 948			em :test_write_parent_code
 949
 950			def test_write_bad_code
 951				result = execute_command do
 952					customer = customer(plan_name: "test_usd")
 953					Registration::Payment::InviteCode::REDIS.expect(
 954						:get,
 955						EMPromise.resolve(0),
 956						["jmp_invite_tries-test"]
 957					)
 958					Registration::Payment::InviteCode::REDIS.expect(
 959						:hget,
 960						EMPromise.resolve(nil),
 961						["jmp_parent_codes", "abc"]
 962					)
 963					Registration::Payment::InviteCode::DB.expect(
 964						:transaction,
 965						[]
 966					) { |&blk| blk.call }
 967					Registration::Payment::InviteCode::DB.expect(
 968						:exec,
 969						OpenStruct.new(cmd_tuples: 0),
 970						[String, ["test", "abc"]]
 971					)
 972					Registration::Payment::InviteCode::REDIS.expect(
 973						:incr,
 974						EMPromise.resolve(nil),
 975						["jmp_invite_tries-test"]
 976					)
 977					Registration::Payment::InviteCode::REDIS.expect(
 978						:expire,
 979						EMPromise.resolve(nil),
 980						["jmp_invite_tries-test", 60 * 60]
 981					)
 982					Registration::Payment::InviteCode::REDIS.expect(
 983						:hexists,
 984						EMPromise.resolve(0),
 985						["jmp_group_codes", "abc"]
 986					)
 987					Command::COMMAND_MANAGER.expect(
 988						:write,
 989						EMPromise.resolve(
 990							Blather::Stanza::Iq::Command.new.tap { |iq|
 991								iq.form.fields = [{ var: "code", value: "abc" }]
 992							}
 993						),
 994						[Matching.new do |reply|
 995							assert_equal :form, reply.form.type
 996							assert_nil reply.form.instructions
 997						end]
 998					)
 999					Command::COMMAND_MANAGER.expect(
1000						:write,
1001						EMPromise.reject(:test_result),
1002						[Matching.new do |reply|
1003							assert_equal :form, reply.form.type
1004							assert_equal(
1005								"Not a valid invite code: abc",
1006								reply.form.instructions
1007							)
1008						end]
1009					)
1010
1011					Registration::Payment::InviteCode.new(
1012						customer,
1013						"+15555550000"
1014					).write.catch { |e| e }
1015				end
1016				assert_equal :test_result, result
1017				assert_mock Command::COMMAND_MANAGER
1018				assert_mock Registration::Payment::InviteCode::DB
1019				assert_mock Registration::Payment::InviteCode::REDIS
1020			end
1021			em :test_write_bad_code
1022
1023			def test_write_group_code
1024				result = execute_command do
1025					customer = customer(plan_name: "test_usd")
1026					Registration::Payment::InviteCode::REDIS.expect(
1027						:get,
1028						EMPromise.resolve(0),
1029						["jmp_invite_tries-test"]
1030					)
1031					Registration::Payment::InviteCode::REDIS.expect(
1032						:hget,
1033						EMPromise.resolve(nil),
1034						["jmp_parent_codes", "abc"]
1035					)
1036					Registration::Payment::InviteCode::DB.expect(
1037						:transaction,
1038						[]
1039					) { |&blk| blk.call }
1040					Registration::Payment::InviteCode::DB.expect(
1041						:exec,
1042						OpenStruct.new(cmd_tuples: 0),
1043						[String, ["test", "abc"]]
1044					)
1045					Registration::Payment::InviteCode::REDIS.expect(
1046						:incr,
1047						EMPromise.resolve(nil),
1048						["jmp_invite_tries-test"]
1049					)
1050					Registration::Payment::InviteCode::REDIS.expect(
1051						:expire,
1052						EMPromise.resolve(nil),
1053						["jmp_invite_tries-test", 60 * 60]
1054					)
1055					Registration::Payment::InviteCode::REDIS.expect(
1056						:hexists,
1057						EMPromise.resolve(1),
1058						["jmp_group_codes", "abc"]
1059					)
1060					Command::COMMAND_MANAGER.expect(
1061						:write,
1062						EMPromise.resolve(
1063							Blather::Stanza::Iq::Command.new.tap { |iq|
1064								iq.form.fields = [{ var: "code", value: "abc" }]
1065							}
1066						),
1067						[Matching.new do |reply|
1068							assert_equal :form, reply.form.type
1069							assert_nil reply.form.instructions
1070						end]
1071					)
1072					Command::COMMAND_MANAGER.expect(
1073						:write,
1074						EMPromise.reject(:test_result),
1075						[Matching.new do |reply|
1076							assert_equal :form, reply.form.type
1077							assert_equal(
1078								"abc is a post-payment referral",
1079								reply.form.instructions
1080							)
1081						end]
1082					)
1083
1084					Registration::Payment::InviteCode.new(
1085						customer,
1086						"+15555550000"
1087					).write.catch { |e| e }
1088				end
1089				assert_equal :test_result, result
1090				assert_mock Command::COMMAND_MANAGER
1091				assert_mock Registration::Payment::InviteCode::DB
1092				assert_mock Registration::Payment::InviteCode::REDIS
1093			end
1094			em :test_write_group_code
1095
1096			def test_write_bad_code_over_limit
1097				result = execute_command do
1098					customer = customer(plan_name: "test_usd")
1099					Registration::Payment::InviteCode::REDIS.expect(
1100						:get,
1101						EMPromise.resolve(11),
1102						["jmp_invite_tries-test"]
1103					)
1104					Registration::Payment::InviteCode::REDIS.expect(
1105						:hget,
1106						EMPromise.resolve(nil),
1107						["jmp_parent_codes", "abc"]
1108					)
1109					Command::COMMAND_MANAGER.expect(
1110						:write,
1111						EMPromise.resolve(
1112							Blather::Stanza::Iq::Command.new.tap { |iq|
1113								iq.form.fields = [{ var: "code", value: "abc" }]
1114							}
1115						),
1116						[Matching.new do |reply|
1117							assert_equal :form, reply.form.type
1118							assert_nil reply.form.instructions
1119						end]
1120					)
1121					Command::COMMAND_MANAGER.expect(
1122						:write,
1123						EMPromise.reject(:test_result),
1124						[Matching.new do |reply|
1125							assert_equal :form, reply.form.type
1126							assert_equal "Too many wrong attempts", reply.form.instructions
1127						end]
1128					)
1129					Registration::Payment::InviteCode.new(
1130						customer,
1131						"+15555550000"
1132					).write.catch { |e| e }
1133				end
1134				assert_equal :test_result, result
1135				assert_mock Command::COMMAND_MANAGER
1136				assert_mock Registration::Payment::InviteCode::REDIS
1137			end
1138			em :test_write_bad_code_over_limit
1139		end
1140	end
1141
1142	class FinishTest < Minitest::Test
1143		Customer::BLATHER = Minitest::Mock.new
1144		Command::COMMAND_MANAGER = Minitest::Mock.new
1145		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
1146		Registration::Finish::REDIS = Minitest::Mock.new
1147		Registration::Finish::DB = Minitest::Mock.new
1148		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
1149		Registration::FinishOnboarding::DB = FakeDB.new
1150		Transaction::DB = Minitest::Mock.new
1151
1152		def setup
1153			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
1154			iq = Blather::Stanza::Iq::Command.new
1155			iq.from = "test\\40example.com@cheogram.com"
1156			@finish = Registration::Finish.new(
1157				customer(sgx: @sgx, plan_name: "test_usd"),
1158				"+15555550000"
1159			)
1160		end
1161
1162		def test_write
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>COMPLETE</OrderStatus>
1179					<CompletedNumbers>
1180						<TelephoneNumber>
1181							<FullNumber>5555550000</FullNumber>
1182						</TelephoneNumber>
1183					</CompletedNumbers>
1184				</OrderResponse>
1185			RESPONSE
1186			stub_request(
1187				:post,
1188				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1189			)
1190			Registration::Finish::REDIS.expect(
1191				:del,
1192				nil,
1193				["pending_tel_for-test@example.net"]
1194			)
1195			Registration::Finish::REDIS.expect(
1196				:get,
1197				nil,
1198				["jmp_customer_pending_invite-test"]
1199			)
1200			Registration::Finish::REDIS.expect(
1201				:del,
1202				nil,
1203				["jmp_customer_pending_invite-test"]
1204			)
1205			Registration::Finish::REDIS.expect(
1206				:hget,
1207				nil,
1208				["jmp_group_codes", nil]
1209			)
1210			Bwmsgsv2Repo::REDIS.expect(
1211				:set,
1212				nil,
1213				[
1214					"catapult_fwd-+15555550000",
1215					"xmpp:test@example.net"
1216				]
1217			)
1218			Bwmsgsv2Repo::REDIS.expect(
1219				:set,
1220				nil,
1221				["catapult_fwd_timeout-customer_test@component", 25]
1222			)
1223			Customer::BLATHER.expect(
1224				:<<,
1225				nil,
1226				[Matching.new do |m|
1227					assert_equal :chat, m.type
1228					assert m.body =~ /^Welcome to JMP/
1229				end]
1230			)
1231			blather = Minitest::Mock.new
1232			blather.expect(
1233				:<<,
1234				nil,
1235				[Matching.new do |reply|
1236					assert_equal :completed, reply.status
1237					assert_equal :info, reply.note_type
1238					assert_equal(
1239						"Your JMP account has been activated as +15555550000",
1240						reply.note.content
1241					)
1242				end]
1243			)
1244			execute_command(blather: blather) do
1245				@sgx.expect(
1246					:register!,
1247					EMPromise.resolve(@sgx.with(
1248						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1249							ibr.phone = "+15555550000"
1250						end
1251					)),
1252					["+15555550000"]
1253				)
1254
1255				@finish.write
1256			end
1257			assert_requested create_order
1258			assert_mock @sgx
1259			assert_mock Registration::Finish::REDIS
1260			assert_mock Bwmsgsv2Repo::REDIS
1261			assert_mock Customer::BLATHER
1262			assert_mock blather
1263		end
1264		em :test_write
1265
1266		def test_write_with_pending_code
1267			create_order = stub_request(
1268				:post,
1269				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1270			).to_return(status: 201, body: <<~RESPONSE)
1271				<OrderResponse>
1272					<Order>
1273						<id>test_order</id>
1274					</Order>
1275				</OrderResponse>
1276			RESPONSE
1277			stub_request(
1278				:get,
1279				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1280			).to_return(status: 201, body: <<~RESPONSE)
1281				<OrderResponse>
1282					<OrderStatus>COMPLETE</OrderStatus>
1283					<CompletedNumbers>
1284						<TelephoneNumber>
1285							<FullNumber>5555550000</FullNumber>
1286						</TelephoneNumber>
1287					</CompletedNumbers>
1288				</OrderResponse>
1289			RESPONSE
1290			stub_request(
1291				:post,
1292				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1293			)
1294			Registration::Finish::REDIS.expect(
1295				:del,
1296				nil,
1297				["pending_tel_for-test@example.net"]
1298			)
1299			Registration::Finish::REDIS.expect(
1300				:get,
1301				EMPromise.resolve("123"),
1302				["jmp_customer_pending_invite-test"]
1303			)
1304			Registration::Finish::REDIS.expect(
1305				:del,
1306				nil,
1307				["jmp_customer_pending_invite-test"]
1308			)
1309			Registration::Finish::REDIS.expect(
1310				:hget,
1311				EMPromise.resolve("test-inviter"),
1312				["jmp_group_codes", "123"]
1313			)
1314			Registration::Finish::DB.expect(
1315				:exec,
1316				EMPromise.resolve(nil),
1317				[String, ["test-inviter", "test"]]
1318			)
1319			Transaction::DB.expect(:transaction, nil) do |&blk|
1320				blk.call
1321				true
1322			end
1323			Transaction::DB.expect(
1324				:exec,
1325				nil,
1326				[String, Matching.new { |params|
1327					assert_equal "test", params[0]
1328					assert params[1].start_with?("referral_")
1329					assert_equal 1, params[4]
1330					assert_equal "Referral Bonus", params[5]
1331				}]
1332			)
1333			Bwmsgsv2Repo::REDIS.expect(
1334				:set,
1335				nil,
1336				[
1337					"catapult_fwd-+15555550000",
1338					"xmpp:test@example.net"
1339				]
1340			)
1341			Bwmsgsv2Repo::REDIS.expect(
1342				:set,
1343				nil,
1344				["catapult_fwd_timeout-customer_test@component", 25]
1345			)
1346			Customer::BLATHER.expect(
1347				:<<,
1348				nil,
1349				[Matching.new do |m|
1350					assert_equal :chat, m.type
1351					assert m.body =~ /^Welcome to JMP/
1352				end]
1353			)
1354			blather = Minitest::Mock.new
1355			blather.expect(
1356				:<<,
1357				nil,
1358				[Matching.new do |reply|
1359					assert_equal :completed, reply.status
1360					assert_equal :info, reply.note_type
1361					assert_equal(
1362						"Your JMP account has been activated as +15555550000",
1363						reply.note.content
1364					)
1365				end]
1366			)
1367			execute_command(blather: blather) do
1368				@sgx.expect(
1369					:register!,
1370					EMPromise.resolve(@sgx.with(
1371						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1372							ibr.phone = "+15555550000"
1373						end
1374					)),
1375					["+15555550000"]
1376				)
1377
1378				@finish.write
1379			end
1380			assert_requested create_order
1381			assert_mock @sgx
1382			assert_mock Registration::Finish::REDIS
1383			assert_mock Bwmsgsv2Repo::REDIS
1384			assert_mock Customer::BLATHER
1385			assert_mock blather
1386			assert_mock Transaction::DB
1387		end
1388		em :test_write_with_pending_code
1389
1390		def test_write_onboarding
1391			create_order = stub_request(
1392				:post,
1393				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1394			).to_return(status: 201, body: <<~RESPONSE)
1395				<OrderResponse>
1396					<Order>
1397						<id>test_order</id>
1398					</Order>
1399				</OrderResponse>
1400			RESPONSE
1401			stub_request(
1402				:get,
1403				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1404			).to_return(status: 201, body: <<~RESPONSE)
1405				<OrderResponse>
1406					<OrderStatus>COMPLETE</OrderStatus>
1407					<CompletedNumbers>
1408						<TelephoneNumber>
1409							<FullNumber>5555550000</FullNumber>
1410						</TelephoneNumber>
1411					</CompletedNumbers>
1412				</OrderResponse>
1413			RESPONSE
1414			stub_request(
1415				:post,
1416				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1417			)
1418			Registration::Finish::REDIS.expect(
1419				:del,
1420				nil,
1421				["pending_tel_for-test\\40onboarding.example.com@proxy"]
1422			)
1423			Registration::Finish::REDIS.expect(
1424				:get,
1425				nil,
1426				["jmp_customer_pending_invite-test"]
1427			)
1428			Registration::Finish::REDIS.expect(
1429				:del,
1430				nil,
1431				["jmp_customer_pending_invite-test"]
1432			)
1433			Registration::Finish::REDIS.expect(
1434				:hget,
1435				nil,
1436				["jmp_group_codes", nil]
1437			)
1438			Bwmsgsv2Repo::REDIS.expect(
1439				:set,
1440				nil,
1441				[
1442					"catapult_fwd-+15555550000",
1443					"xmpp:test\\40onboarding.example.com@proxy"
1444				]
1445			)
1446			Bwmsgsv2Repo::REDIS.expect(
1447				:set,
1448				nil,
1449				["catapult_fwd_timeout-customer_test@component", 25]
1450			)
1451			result = execute_command do
1452				@sgx.expect(
1453					:register!,
1454					EMPromise.resolve(@sgx.with(
1455						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1456							ibr.phone = "+15555550000"
1457						end
1458					)),
1459					["+15555550000"]
1460				)
1461
1462				Command::COMMAND_MANAGER.expect(
1463					:write,
1464					EMPromise.reject(:test_result),
1465					[Matching.new do |iq|
1466						assert_equal :form, iq.form.type
1467						assert iq.form.field("subdomain")
1468					end]
1469				)
1470
1471				Registration::Finish.new(
1472					customer(
1473						sgx: @sgx,
1474						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1475					),
1476					"+15555550000"
1477				).write.catch { |e| e }
1478			end
1479			assert_equal :test_result, result
1480			assert_requested create_order
1481			assert_mock @sgx
1482			assert_mock Registration::Finish::REDIS
1483			assert_mock Bwmsgsv2Repo::REDIS
1484			assert_mock Command::COMMAND_MANAGER
1485		end
1486		em :test_write_onboarding
1487
1488		def test_write_tn_fail
1489			create_order = stub_request(
1490				:post,
1491				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1492			).to_return(status: 201, body: <<~RESPONSE)
1493				<OrderResponse>
1494					<Order>
1495						<id>test_order</id>
1496					</Order>
1497				</OrderResponse>
1498			RESPONSE
1499			stub_request(
1500				:get,
1501				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1502			).to_return(status: 201, body: <<~RESPONSE)
1503				<OrderResponse>
1504					<OrderStatus>FAILED</OrderStatus>
1505				</OrderResponse>
1506			RESPONSE
1507
1508			result = execute_command do
1509				Command::COMMAND_MANAGER.expect(
1510					:write,
1511					EMPromise.reject(:test_result),
1512					[Matching.new do |iq|
1513						assert_equal :form, iq.form.type
1514						assert_equal(
1515							"The JMP number +15555550000 is no longer available.",
1516							iq.form.instructions
1517						)
1518					end]
1519				)
1520
1521				@finish.write.catch { |e| e }
1522			end
1523
1524			assert_equal :test_result, result
1525			assert_mock Command::COMMAND_MANAGER
1526			assert_instance_of(
1527				TelSelections::ChooseTel,
1528				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1529			)
1530			assert_requested create_order
1531		end
1532		em :test_write_tn_fail
1533	end
1534
1535	class SnikketTest < Minitest::Test
1536		Command::COMMAND_MANAGER = Minitest::Mock.new
1537		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1538
1539		def setup
1540			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
1541			@snikket = Registration::FinishOnboarding::Snikket.new(
1542				customer,
1543				"+15555550000",
1544				db: FakeDB.new
1545			)
1546		end
1547
1548		def test_write
1549			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1550
1551			subdomain_form = Blather::Stanza::Iq::Command.new
1552			subdomain_form.form.fields = [
1553				{ var: "subdomain", value: "test" }
1554			]
1555
1556			launched = Snikket::Launched.new
1557			launched << Niceogiri::XML::Node.new(
1558				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1559			).tap { |inner|
1560				inner << Niceogiri::XML::Node.new(
1561					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1562				).tap { |id|
1563					id.content = "si-1234"
1564				}
1565				inner << Niceogiri::XML::Node.new(
1566					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1567				).tap { |bootstrap|
1568					bootstrap << Niceogiri::XML::Node.new(
1569						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1570					).tap { |token|
1571						token.content = "TOKEN"
1572					}
1573				}
1574			}
1575
1576			blather = Minitest::Mock.new
1577			blather.expect(
1578				:<<,
1579				nil,
1580				[Matching.new do |reply|
1581					assert_equal :completed, reply.status
1582					assert_equal(
1583						xmpp_uri,
1584						OOB.find_or_create(reply.command).url
1585					)
1586				end]
1587			)
1588
1589			execute_command(blather: blather) do
1590				Command::COMMAND_MANAGER.expect(
1591					:write,
1592					EMPromise.resolve(subdomain_form),
1593					[Matching.new do |iq|
1594						assert_equal :form, iq.form.type
1595						assert iq.form.field("subdomain")
1596					end]
1597				)
1598
1599				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1600					:write,
1601					EMPromise.resolve(launched),
1602					[Matching.new do |iq|
1603						assert_equal :set, iq.type
1604						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1605						assert_equal(
1606							"test.snikket.chat",
1607							iq.xpath(
1608								"./ns:launch/ns:domain",
1609								ns: "xmpp:snikket.org/hosting/v1"
1610							).text
1611						)
1612					end]
1613				)
1614
1615				# Webmock doesn't support redirects properly, but they work live
1616				stub_request(
1617					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1618				).to_return(
1619					status: 200,
1620					headers: {
1621						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1622					}
1623				)
1624
1625				@snikket.write
1626			end
1627
1628			assert_mock Command::COMMAND_MANAGER
1629			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1630			assert_mock blather
1631		end
1632		em :test_write
1633
1634		def test_write_not_yet
1635			subdomain_form = Blather::Stanza::Iq::Command.new
1636			subdomain_form.form.fields = [
1637				{ var: "subdomain", value: "test" }
1638			]
1639
1640			launched = Snikket::Launched.new
1641			launched << Niceogiri::XML::Node.new(
1642				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1643			).tap { |inner|
1644				inner << Niceogiri::XML::Node.new(
1645					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1646				).tap { |id|
1647					id.content = "si-1234"
1648				}
1649				inner << Niceogiri::XML::Node.new(
1650					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1651				).tap { |bootstrap|
1652					bootstrap << Niceogiri::XML::Node.new(
1653						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1654					).tap { |token|
1655						token.content = "TOKEN"
1656					}
1657				}
1658			}
1659
1660			result = execute_command do
1661				Command::COMMAND_MANAGER.expect(
1662					:write,
1663					EMPromise.resolve(subdomain_form),
1664					[Matching.new do |iq|
1665						assert_equal :form, iq.form.type
1666						assert iq.form.field("subdomain")
1667					end]
1668				)
1669
1670				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1671					:write,
1672					EMPromise.resolve(launched),
1673					[Matching.new do |iq|
1674						assert_equal :set, iq.type
1675						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1676						assert_equal(
1677							"test.snikket.chat",
1678							iq.xpath(
1679								"./ns:launch/ns:domain",
1680								ns: "xmpp:snikket.org/hosting/v1"
1681							).text
1682						)
1683					end]
1684				)
1685
1686				stub_request(
1687					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1688				).to_timeout
1689
1690				Command::COMMAND_MANAGER.expect(
1691					:write,
1692					EMPromise.reject(:test_result),
1693					[Matching.new do |iq|
1694						assert_equal :result, iq.form.type
1695						assert iq.form.instructions =~ / test\.snikket\.chat /
1696						assert_equal "jid-single", iq.form.field("support").type
1697					end]
1698				)
1699
1700				@snikket.write.catch { |e| e }
1701			end
1702
1703			assert_equal :test_result, result
1704			assert_mock Command::COMMAND_MANAGER
1705			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1706		end
1707		em :test_write_not_yet
1708
1709		def test_write_already_taken
1710			subdomain_form = Blather::Stanza::Iq::Command.new
1711			subdomain_form.form.fields = [
1712				{ var: "subdomain", value: "test" }
1713			]
1714
1715			launched = Snikket::Launched.new.as_error(
1716				"internal-server-error",
1717				:wait,
1718				"This is an error"
1719			)
1720
1721			result = execute_command do
1722				Command::COMMAND_MANAGER.expect(
1723					:write,
1724					EMPromise.resolve(subdomain_form),
1725					[Matching.new do |iq|
1726						assert_equal :form, iq.form.type
1727						assert iq.form.field("subdomain")
1728					end]
1729				)
1730
1731				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1732					:write,
1733					EMPromise.reject(launched),
1734					[Matching.new do |iq|
1735						assert_equal :set, iq.type
1736						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1737						assert_equal(
1738							"test.snikket.chat",
1739							iq.xpath(
1740								"./ns:launch/ns:domain",
1741								ns: "xmpp:snikket.org/hosting/v1"
1742							).text
1743						)
1744					end]
1745				)
1746
1747				stub_request(
1748					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1749				).to_timeout
1750
1751				Command::COMMAND_MANAGER.expect(
1752					:write,
1753					EMPromise.reject(:test_result),
1754					[Matching.new do |iq|
1755						assert iq.executing?
1756						assert_equal(
1757							"This is an error",
1758							iq.form.field("subdomain").desc
1759						)
1760					end]
1761				)
1762
1763				@snikket.write.catch { |e| e }
1764			end
1765
1766			assert_equal :test_result, result
1767			assert_mock Command::COMMAND_MANAGER
1768			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1769		end
1770		em :test_write_already_taken
1771	end
1772
1773	class SnikketCustomDomainTest < Minitest::Test
1774		def setup
1775			@snikket = Registration::FinishOnboarding::CustomDomain.new(
1776				customer,
1777				"+15555550000",
1778				db: FakeDB.new
1779			)
1780		end
1781
1782		def test_write_needs_dns
1783			domain_form = Blather::Stanza::Iq::Command.new
1784			domain_form.form.fields = [
1785				{ var: "domain", value: "snikket.example.com" }
1786			]
1787
1788			launched = Snikket::Launched.new
1789			launched << Niceogiri::XML::Node.new(
1790				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1791			).tap { |inner|
1792				inner << Niceogiri::XML::Node.new(
1793					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1794				).tap { |id|
1795					id.content = "si-1234"
1796				}
1797				inner << Niceogiri::XML::Node.new(
1798					:status, launched.document, "xmpp:snikket.org/hosting/v1"
1799				).tap { |id|
1800					id.content = "needs_dns"
1801				}
1802				inner << Niceogiri::XML::Node.new(
1803					:records, launched.document, "xmpp:snikket.org/hosting/v1"
1804				).tap { |records|
1805					records << Niceogiri::XML::Node.new(
1806						:record, launched.document, "xmpp:snikket.org/hosting/v1"
1807					).tap { |record|
1808						record << Niceogiri::XML::Node.new(
1809							:name, launched.document, "xmpp:snikket.org/hosting/v1"
1810						).tap { |name| name.content = "snikket.example.com" }
1811						record << Niceogiri::XML::Node.new(
1812							:type, launched.document, "xmpp:snikket.org/hosting/v1"
1813						).tap { |type| type.content = "AAAA" }
1814						record << Niceogiri::XML::Node.new(
1815							:status, launched.document, "xmpp:snikket.org/hosting/v1"
1816						).tap { |type| type.content = "incorrect" }
1817						record << Niceogiri::XML::Node.new(
1818							:expected, launched.document, "xmpp:snikket.org/hosting/v1"
1819						).tap { |expected|
1820							expected << Niceogiri::XML::Node.new(
1821								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1822							).tap { |value| value.content = "1::2" }
1823						}
1824						record << Niceogiri::XML::Node.new(
1825							:found, launched.document, "xmpp:snikket.org/hosting/v1"
1826						).tap { |found|
1827							found << Niceogiri::XML::Node.new(
1828								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1829							).tap { |value| value.content = "0::0" }
1830						}
1831					}
1832				}
1833			}
1834
1835			result = execute_command do
1836				Command::COMMAND_MANAGER.expect(
1837					:write,
1838					EMPromise.resolve(domain_form),
1839					[Matching.new do |iq|
1840						assert_equal :form, iq.form.type
1841						assert iq.form.field("domain")
1842					end]
1843				)
1844
1845				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1846					:write,
1847					EMPromise.resolve(launched),
1848					[Matching.new do |iq|
1849						assert_equal :set, iq.type
1850						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1851						assert_equal(
1852							"snikket.example.com",
1853							iq.xpath(
1854								"./ns:launch/ns:domain",
1855								ns: "xmpp:snikket.org/hosting/v1"
1856							).text
1857						)
1858					end]
1859				)
1860
1861				Command::COMMAND_MANAGER.expect(
1862					:write,
1863					EMPromise.reject(:test_result),
1864					[Matching.new do |iq|
1865						assert_equal :form, iq.form.type
1866						assert_equal(
1867							["snikket.example.com"],
1868							iq.form.xpath(
1869								"./ns:item/ns:field[@var='name']/ns:value",
1870								ns: "jabber:x:data"
1871							).map(&:content)
1872						)
1873						assert_equal(
1874							["1::2"],
1875							iq.form.xpath(
1876								"./ns:item/ns:field[@var='expected']/ns:value",
1877								ns: "jabber:x:data"
1878							).map(&:content)
1879						)
1880					end]
1881				)
1882
1883				@snikket.write.catch { |e| e }
1884			end
1885
1886			assert_equal :test_result, result
1887			assert_mock Command::COMMAND_MANAGER
1888			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1889		end
1890		em :test_write_needs_dns
1891	end
1892end