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