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			def test_write
 736				customer = customer(plan_name: "test_usd")
 737				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 738				Registration::Payment::InviteCode::Finish.expect(
 739					:new,
 740					OpenStruct.new(write: nil),
 741					[
 742						customer,
 743						"+15555550000"
 744					]
 745				)
 746				execute_command do
 747					Registration::Payment::InviteCode::REDIS.expect(
 748						:get,
 749						EMPromise.resolve(nil),
 750						["jmp_invite_tries-test"]
 751					)
 752					Registration::Payment::InviteCode::REDIS.expect(
 753						:hget,
 754						EMPromise.resolve(nil),
 755						["jmp_parent_codes", "abc"]
 756					)
 757					Command::COMMAND_MANAGER.expect(
 758						:write,
 759						EMPromise.resolve(
 760							Blather::Stanza::Iq::Command.new.tap { |iq|
 761								iq.form.fields = [{ var: "code", value: "abc" }]
 762							}
 763						),
 764						[Matching.new do |reply|
 765							assert_equal :form, reply.form.type
 766							assert_nil reply.form.instructions
 767						end]
 768					)
 769
 770					Registration::Payment::InviteCode.new(
 771						customer,
 772						"+15555550000"
 773					).write
 774				end
 775				assert_mock Command::COMMAND_MANAGER
 776				assert_mock Registration::Payment::InviteCode::DB
 777				assert_mock Registration::Payment::InviteCode::REDIS
 778				assert_mock Registration::Payment::InviteCode::Finish
 779			end
 780			em :test_write
 781
 782			def test_write_bad_code
 783				result = execute_command do
 784					customer = customer(plan_name: "test_usd")
 785					Registration::Payment::InviteCode::REDIS.expect(
 786						:get,
 787						EMPromise.resolve(0),
 788						["jmp_invite_tries-test"]
 789					)
 790					Registration::Payment::InviteCode::REDIS.expect(
 791						:hget,
 792						EMPromise.resolve(nil),
 793						["jmp_parent_codes", "abc"]
 794					)
 795					Registration::Payment::InviteCode::DB.expect(
 796						:transaction,
 797						[]
 798					) { |&blk| blk.call }
 799					Registration::Payment::InviteCode::DB.expect(
 800						:exec,
 801						OpenStruct.new(cmd_tuples: 0),
 802						[String, ["test", "abc"]]
 803					)
 804					Registration::Payment::InviteCode::REDIS.expect(
 805						:incr,
 806						EMPromise.resolve(nil),
 807						["jmp_invite_tries-test"]
 808					)
 809					Registration::Payment::InviteCode::REDIS.expect(
 810						:expire,
 811						EMPromise.resolve(nil),
 812						["jmp_invite_tries-test", 60 * 60]
 813					)
 814					Registration::Payment::InviteCode::REDIS.expect(
 815						:hexists,
 816						EMPromise.resolve(0),
 817						["jmp_group_codes", "abc"]
 818					)
 819					Command::COMMAND_MANAGER.expect(
 820						:write,
 821						EMPromise.resolve(
 822							Blather::Stanza::Iq::Command.new.tap { |iq|
 823								iq.form.fields = [{ var: "code", value: "abc" }]
 824							}
 825						),
 826						[Matching.new do |reply|
 827							assert_equal :form, reply.form.type
 828							assert_nil reply.form.instructions
 829						end]
 830					)
 831					Command::COMMAND_MANAGER.expect(
 832						:write,
 833						EMPromise.reject(:test_result),
 834						[Matching.new do |reply|
 835							assert_equal :form, reply.form.type
 836							assert_equal(
 837								"Not a valid invite code: abc",
 838								reply.form.instructions
 839							)
 840						end]
 841					)
 842
 843					Registration::Payment::InviteCode.new(
 844						customer,
 845						"+15555550000"
 846					).write.catch { |e| e }
 847				end
 848				assert_equal :test_result, result
 849				assert_mock Command::COMMAND_MANAGER
 850				assert_mock Registration::Payment::InviteCode::DB
 851				assert_mock Registration::Payment::InviteCode::REDIS
 852			end
 853			em :test_write_bad_code
 854
 855			def test_write_group_code
 856				result = execute_command do
 857					customer = customer(plan_name: "test_usd")
 858					Registration::Payment::InviteCode::REDIS.expect(
 859						:get,
 860						EMPromise.resolve(0),
 861						["jmp_invite_tries-test"]
 862					)
 863					Registration::Payment::InviteCode::REDIS.expect(
 864						:hget,
 865						EMPromise.resolve(nil),
 866						["jmp_parent_codes", "abc"]
 867					)
 868					Registration::Payment::InviteCode::DB.expect(
 869						:transaction,
 870						[]
 871					) { |&blk| blk.call }
 872					Registration::Payment::InviteCode::DB.expect(
 873						:exec,
 874						OpenStruct.new(cmd_tuples: 0),
 875						[String, ["test", "abc"]]
 876					)
 877					Registration::Payment::InviteCode::REDIS.expect(
 878						:incr,
 879						EMPromise.resolve(nil),
 880						["jmp_invite_tries-test"]
 881					)
 882					Registration::Payment::InviteCode::REDIS.expect(
 883						:expire,
 884						EMPromise.resolve(nil),
 885						["jmp_invite_tries-test", 60 * 60]
 886					)
 887					Registration::Payment::InviteCode::REDIS.expect(
 888						:hexists,
 889						EMPromise.resolve(1),
 890						["jmp_group_codes", "abc"]
 891					)
 892					Command::COMMAND_MANAGER.expect(
 893						:write,
 894						EMPromise.resolve(
 895							Blather::Stanza::Iq::Command.new.tap { |iq|
 896								iq.form.fields = [{ var: "code", value: "abc" }]
 897							}
 898						),
 899						[Matching.new do |reply|
 900							assert_equal :form, reply.form.type
 901							assert_nil reply.form.instructions
 902						end]
 903					)
 904					Command::COMMAND_MANAGER.expect(
 905						:write,
 906						EMPromise.reject(:test_result),
 907						[Matching.new do |reply|
 908							assert_equal :form, reply.form.type
 909							assert_equal(
 910								"abc is a post-payment referral",
 911								reply.form.instructions
 912							)
 913						end]
 914					)
 915
 916					Registration::Payment::InviteCode.new(
 917						customer,
 918						"+15555550000"
 919					).write.catch { |e| e }
 920				end
 921				assert_equal :test_result, result
 922				assert_mock Command::COMMAND_MANAGER
 923				assert_mock Registration::Payment::InviteCode::DB
 924				assert_mock Registration::Payment::InviteCode::REDIS
 925			end
 926			em :test_write_group_code
 927
 928			def test_write_bad_code_over_limit
 929				result = execute_command do
 930					customer = customer(plan_name: "test_usd")
 931					Registration::Payment::InviteCode::REDIS.expect(
 932						:get,
 933						EMPromise.resolve(11),
 934						["jmp_invite_tries-test"]
 935					)
 936					Registration::Payment::InviteCode::REDIS.expect(
 937						:hget,
 938						EMPromise.resolve(nil),
 939						["jmp_parent_codes", "abc"]
 940					)
 941					Command::COMMAND_MANAGER.expect(
 942						:write,
 943						EMPromise.resolve(
 944							Blather::Stanza::Iq::Command.new.tap { |iq|
 945								iq.form.fields = [{ var: "code", value: "abc" }]
 946							}
 947						),
 948						[Matching.new do |reply|
 949							assert_equal :form, reply.form.type
 950							assert_nil reply.form.instructions
 951						end]
 952					)
 953					Command::COMMAND_MANAGER.expect(
 954						:write,
 955						EMPromise.reject(:test_result),
 956						[Matching.new do |reply|
 957							assert_equal :form, reply.form.type
 958							assert_equal "Too many wrong attempts", reply.form.instructions
 959						end]
 960					)
 961					Registration::Payment::InviteCode.new(
 962						customer,
 963						"+15555550000"
 964					).write.catch { |e| e }
 965				end
 966				assert_equal :test_result, result
 967				assert_mock Command::COMMAND_MANAGER
 968				assert_mock Registration::Payment::InviteCode::REDIS
 969			end
 970			em :test_write_bad_code_over_limit
 971		end
 972	end
 973
 974	class FinishTest < Minitest::Test
 975		Customer::BLATHER = Minitest::Mock.new
 976		Command::COMMAND_MANAGER = Minitest::Mock.new
 977		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
 978		Registration::Finish::REDIS = Minitest::Mock.new
 979		Registration::Finish::DB = Minitest::Mock.new
 980		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
 981		Registration::FinishOnboarding::DB = FakeDB.new
 982		Transaction::DB = Minitest::Mock.new
 983
 984		def setup
 985			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
 986			iq = Blather::Stanza::Iq::Command.new
 987			iq.from = "test\\40example.com@cheogram.com"
 988			@finish = Registration::Finish.new(
 989				customer(sgx: @sgx, plan_name: "test_usd"),
 990				"+15555550000"
 991			)
 992		end
 993
 994		def test_write
 995			create_order = stub_request(
 996				:post,
 997				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 998			).to_return(status: 201, body: <<~RESPONSE)
 999				<OrderResponse>
1000					<Order>
1001						<id>test_order</id>
1002					</Order>
1003				</OrderResponse>
1004			RESPONSE
1005			stub_request(
1006				:get,
1007				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1008			).to_return(status: 201, body: <<~RESPONSE)
1009				<OrderResponse>
1010					<OrderStatus>COMPLETE</OrderStatus>
1011					<CompletedNumbers>
1012						<TelephoneNumber>
1013							<FullNumber>5555550000</FullNumber>
1014						</TelephoneNumber>
1015					</CompletedNumbers>
1016				</OrderResponse>
1017			RESPONSE
1018			stub_request(
1019				:post,
1020				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1021			)
1022			Registration::Finish::REDIS.expect(
1023				:del,
1024				nil,
1025				["pending_tel_for-test@example.net"]
1026			)
1027			Registration::Finish::REDIS.expect(
1028				:get,
1029				nil,
1030				["jmp_customer_pending_invite-test"]
1031			)
1032			Registration::Finish::REDIS.expect(
1033				:del,
1034				nil,
1035				["jmp_customer_pending_invite-test"]
1036			)
1037			Registration::Finish::REDIS.expect(
1038				:hget,
1039				nil,
1040				["jmp_group_codes", nil]
1041			)
1042			Bwmsgsv2Repo::REDIS.expect(
1043				:set,
1044				nil,
1045				[
1046					"catapult_fwd-+15555550000",
1047					"xmpp:test@example.net"
1048				]
1049			)
1050			Bwmsgsv2Repo::REDIS.expect(
1051				:set,
1052				nil,
1053				["catapult_fwd_timeout-customer_test@component", 25]
1054			)
1055			Customer::BLATHER.expect(
1056				:<<,
1057				nil,
1058				[Matching.new do |m|
1059					assert_equal :chat, m.type
1060					assert m.body =~ /^Welcome to JMP/
1061				end]
1062			)
1063			blather = Minitest::Mock.new
1064			blather.expect(
1065				:<<,
1066				nil,
1067				[Matching.new do |reply|
1068					assert_equal :completed, reply.status
1069					assert_equal :info, reply.note_type
1070					assert_equal(
1071						"Your JMP account has been activated as +15555550000",
1072						reply.note.content
1073					)
1074				end]
1075			)
1076			execute_command(blather: blather) do
1077				@sgx.expect(
1078					:register!,
1079					EMPromise.resolve(@sgx.with(
1080						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1081							ibr.phone = "+15555550000"
1082						end
1083					)),
1084					["+15555550000"]
1085				)
1086
1087				@finish.write
1088			end
1089			assert_requested create_order
1090			assert_mock @sgx
1091			assert_mock Registration::Finish::REDIS
1092			assert_mock Bwmsgsv2Repo::REDIS
1093			assert_mock Customer::BLATHER
1094			assert_mock blather
1095		end
1096		em :test_write
1097
1098		def test_write_with_pending_code
1099			create_order = stub_request(
1100				:post,
1101				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1102			).to_return(status: 201, body: <<~RESPONSE)
1103				<OrderResponse>
1104					<Order>
1105						<id>test_order</id>
1106					</Order>
1107				</OrderResponse>
1108			RESPONSE
1109			stub_request(
1110				:get,
1111				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1112			).to_return(status: 201, body: <<~RESPONSE)
1113				<OrderResponse>
1114					<OrderStatus>COMPLETE</OrderStatus>
1115					<CompletedNumbers>
1116						<TelephoneNumber>
1117							<FullNumber>5555550000</FullNumber>
1118						</TelephoneNumber>
1119					</CompletedNumbers>
1120				</OrderResponse>
1121			RESPONSE
1122			stub_request(
1123				:post,
1124				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1125			)
1126			Registration::Finish::REDIS.expect(
1127				:del,
1128				nil,
1129				["pending_tel_for-test@example.net"]
1130			)
1131			Registration::Finish::REDIS.expect(
1132				:get,
1133				EMPromise.resolve("123"),
1134				["jmp_customer_pending_invite-test"]
1135			)
1136			Registration::Finish::REDIS.expect(
1137				:del,
1138				nil,
1139				["jmp_customer_pending_invite-test"]
1140			)
1141			Registration::Finish::REDIS.expect(
1142				:hget,
1143				EMPromise.resolve("test-inviter"),
1144				["jmp_group_codes", "123"]
1145			)
1146			Registration::Finish::DB.expect(
1147				:exec,
1148				EMPromise.resolve(nil),
1149				[String, ["test-inviter", "test"]]
1150			)
1151			Transaction::DB.expect(:transaction, nil) do |&blk|
1152				blk.call
1153				true
1154			end
1155			Transaction::DB.expect(
1156				:exec,
1157				nil,
1158				[String, Matching.new { |params|
1159					assert_equal "test", params[0]
1160					assert params[1].start_with?("referral_")
1161					assert_equal 1, params[4]
1162					assert_equal "Referral Bonus", params[5]
1163				}]
1164			)
1165			Bwmsgsv2Repo::REDIS.expect(
1166				:set,
1167				nil,
1168				[
1169					"catapult_fwd-+15555550000",
1170					"xmpp:test@example.net"
1171				]
1172			)
1173			Bwmsgsv2Repo::REDIS.expect(
1174				:set,
1175				nil,
1176				["catapult_fwd_timeout-customer_test@component", 25]
1177			)
1178			Customer::BLATHER.expect(
1179				:<<,
1180				nil,
1181				[Matching.new do |m|
1182					assert_equal :chat, m.type
1183					assert m.body =~ /^Welcome to JMP/
1184				end]
1185			)
1186			blather = Minitest::Mock.new
1187			blather.expect(
1188				:<<,
1189				nil,
1190				[Matching.new do |reply|
1191					assert_equal :completed, reply.status
1192					assert_equal :info, reply.note_type
1193					assert_equal(
1194						"Your JMP account has been activated as +15555550000",
1195						reply.note.content
1196					)
1197				end]
1198			)
1199			execute_command(blather: blather) do
1200				@sgx.expect(
1201					:register!,
1202					EMPromise.resolve(@sgx.with(
1203						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1204							ibr.phone = "+15555550000"
1205						end
1206					)),
1207					["+15555550000"]
1208				)
1209
1210				@finish.write
1211			end
1212			assert_requested create_order
1213			assert_mock @sgx
1214			assert_mock Registration::Finish::REDIS
1215			assert_mock Bwmsgsv2Repo::REDIS
1216			assert_mock Customer::BLATHER
1217			assert_mock blather
1218			assert_mock Transaction::DB
1219		end
1220		em :test_write_with_pending_code
1221
1222		def test_write_onboarding
1223			create_order = stub_request(
1224				:post,
1225				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1226			).to_return(status: 201, body: <<~RESPONSE)
1227				<OrderResponse>
1228					<Order>
1229						<id>test_order</id>
1230					</Order>
1231				</OrderResponse>
1232			RESPONSE
1233			stub_request(
1234				:get,
1235				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1236			).to_return(status: 201, body: <<~RESPONSE)
1237				<OrderResponse>
1238					<OrderStatus>COMPLETE</OrderStatus>
1239					<CompletedNumbers>
1240						<TelephoneNumber>
1241							<FullNumber>5555550000</FullNumber>
1242						</TelephoneNumber>
1243					</CompletedNumbers>
1244				</OrderResponse>
1245			RESPONSE
1246			stub_request(
1247				:post,
1248				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1249			)
1250			Registration::Finish::REDIS.expect(
1251				:del,
1252				nil,
1253				["pending_tel_for-test\\40onboarding.example.com@proxy"]
1254			)
1255			Registration::Finish::REDIS.expect(
1256				:get,
1257				nil,
1258				["jmp_customer_pending_invite-test"]
1259			)
1260			Registration::Finish::REDIS.expect(
1261				:del,
1262				nil,
1263				["jmp_customer_pending_invite-test"]
1264			)
1265			Registration::Finish::REDIS.expect(
1266				:hget,
1267				nil,
1268				["jmp_group_codes", nil]
1269			)
1270			Bwmsgsv2Repo::REDIS.expect(
1271				:set,
1272				nil,
1273				[
1274					"catapult_fwd-+15555550000",
1275					"xmpp:test\\40onboarding.example.com@proxy"
1276				]
1277			)
1278			Bwmsgsv2Repo::REDIS.expect(
1279				:set,
1280				nil,
1281				["catapult_fwd_timeout-customer_test@component", 25]
1282			)
1283			result = execute_command do
1284				@sgx.expect(
1285					:register!,
1286					EMPromise.resolve(@sgx.with(
1287						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1288							ibr.phone = "+15555550000"
1289						end
1290					)),
1291					["+15555550000"]
1292				)
1293
1294				Command::COMMAND_MANAGER.expect(
1295					:write,
1296					EMPromise.reject(:test_result),
1297					[Matching.new do |iq|
1298						assert_equal :form, iq.form.type
1299						assert iq.form.field("subdomain")
1300					end]
1301				)
1302
1303				Registration::Finish.new(
1304					customer(
1305						sgx: @sgx,
1306						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1307					),
1308					"+15555550000"
1309				).write.catch { |e| e }
1310			end
1311			assert_equal :test_result, result
1312			assert_requested create_order
1313			assert_mock @sgx
1314			assert_mock Registration::Finish::REDIS
1315			assert_mock Bwmsgsv2Repo::REDIS
1316			assert_mock Command::COMMAND_MANAGER
1317		end
1318		em :test_write_onboarding
1319
1320		def test_write_tn_fail
1321			create_order = stub_request(
1322				:post,
1323				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1324			).to_return(status: 201, body: <<~RESPONSE)
1325				<OrderResponse>
1326					<Order>
1327						<id>test_order</id>
1328					</Order>
1329				</OrderResponse>
1330			RESPONSE
1331			stub_request(
1332				:get,
1333				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1334			).to_return(status: 201, body: <<~RESPONSE)
1335				<OrderResponse>
1336					<OrderStatus>FAILED</OrderStatus>
1337				</OrderResponse>
1338			RESPONSE
1339
1340			result = execute_command do
1341				Command::COMMAND_MANAGER.expect(
1342					:write,
1343					EMPromise.reject(:test_result),
1344					[Matching.new do |iq|
1345						assert_equal :form, iq.form.type
1346						assert_equal(
1347							"The JMP number +15555550000 is no longer available.",
1348							iq.form.instructions
1349						)
1350					end]
1351				)
1352
1353				@finish.write.catch { |e| e }
1354			end
1355
1356			assert_equal :test_result, result
1357			assert_mock Command::COMMAND_MANAGER
1358			assert_instance_of(
1359				TelSelections::ChooseTel,
1360				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1361			)
1362			assert_requested create_order
1363		end
1364		em :test_write_tn_fail
1365	end
1366
1367	class SnikketTest < Minitest::Test
1368		Command::COMMAND_MANAGER = Minitest::Mock.new
1369		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1370
1371		def setup
1372			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
1373			@snikket = Registration::FinishOnboarding::Snikket.new(
1374				customer,
1375				"+15555550000",
1376				db: FakeDB.new
1377			)
1378		end
1379
1380		def test_write
1381			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1382
1383			subdomain_form = Blather::Stanza::Iq::Command.new
1384			subdomain_form.form.fields = [
1385				{ var: "subdomain", value: "test" }
1386			]
1387
1388			launched = Snikket::Launched.new
1389			launched << Niceogiri::XML::Node.new(
1390				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1391			).tap { |inner|
1392				inner << Niceogiri::XML::Node.new(
1393					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1394				).tap { |id|
1395					id.content = "si-1234"
1396				}
1397				inner << Niceogiri::XML::Node.new(
1398					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1399				).tap { |bootstrap|
1400					bootstrap << Niceogiri::XML::Node.new(
1401						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1402					).tap { |token|
1403						token.content = "TOKEN"
1404					}
1405				}
1406			}
1407
1408			blather = Minitest::Mock.new
1409			blather.expect(
1410				:<<,
1411				nil,
1412				[Matching.new do |reply|
1413					assert_equal :completed, reply.status
1414					assert_equal(
1415						xmpp_uri,
1416						OOB.find_or_create(reply.command).url
1417					)
1418				end]
1419			)
1420
1421			execute_command(blather: blather) do
1422				Command::COMMAND_MANAGER.expect(
1423					:write,
1424					EMPromise.resolve(subdomain_form),
1425					[Matching.new do |iq|
1426						assert_equal :form, iq.form.type
1427						assert iq.form.field("subdomain")
1428					end]
1429				)
1430
1431				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1432					:write,
1433					EMPromise.resolve(launched),
1434					[Matching.new do |iq|
1435						assert_equal :set, iq.type
1436						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1437						assert_equal(
1438							"test.snikket.chat",
1439							iq.xpath(
1440								"./ns:launch/ns:domain",
1441								ns: "xmpp:snikket.org/hosting/v1"
1442							).text
1443						)
1444					end]
1445				)
1446
1447				# Webmock doesn't support redirects properly, but they work live
1448				stub_request(
1449					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1450				).to_return(
1451					status: 200,
1452					headers: {
1453						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1454					}
1455				)
1456
1457				@snikket.write
1458			end
1459
1460			assert_mock Command::COMMAND_MANAGER
1461			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1462			assert_mock blather
1463		end
1464		em :test_write
1465
1466		def test_write_not_yet
1467			subdomain_form = Blather::Stanza::Iq::Command.new
1468			subdomain_form.form.fields = [
1469				{ var: "subdomain", value: "test" }
1470			]
1471
1472			launched = Snikket::Launched.new
1473			launched << Niceogiri::XML::Node.new(
1474				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1475			).tap { |inner|
1476				inner << Niceogiri::XML::Node.new(
1477					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1478				).tap { |id|
1479					id.content = "si-1234"
1480				}
1481				inner << Niceogiri::XML::Node.new(
1482					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1483				).tap { |bootstrap|
1484					bootstrap << Niceogiri::XML::Node.new(
1485						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1486					).tap { |token|
1487						token.content = "TOKEN"
1488					}
1489				}
1490			}
1491
1492			result = execute_command do
1493				Command::COMMAND_MANAGER.expect(
1494					:write,
1495					EMPromise.resolve(subdomain_form),
1496					[Matching.new do |iq|
1497						assert_equal :form, iq.form.type
1498						assert iq.form.field("subdomain")
1499					end]
1500				)
1501
1502				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1503					:write,
1504					EMPromise.resolve(launched),
1505					[Matching.new do |iq|
1506						assert_equal :set, iq.type
1507						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1508						assert_equal(
1509							"test.snikket.chat",
1510							iq.xpath(
1511								"./ns:launch/ns:domain",
1512								ns: "xmpp:snikket.org/hosting/v1"
1513							).text
1514						)
1515					end]
1516				)
1517
1518				stub_request(
1519					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1520				).to_timeout
1521
1522				Command::COMMAND_MANAGER.expect(
1523					:write,
1524					EMPromise.reject(:test_result),
1525					[Matching.new do |iq|
1526						assert_equal :result, iq.form.type
1527						assert iq.form.instructions =~ / test\.snikket\.chat /
1528						assert_equal "jid-single", iq.form.field("support").type
1529					end]
1530				)
1531
1532				@snikket.write.catch { |e| e }
1533			end
1534
1535			assert_equal :test_result, result
1536			assert_mock Command::COMMAND_MANAGER
1537			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1538		end
1539		em :test_write_not_yet
1540
1541		def test_write_already_taken
1542			subdomain_form = Blather::Stanza::Iq::Command.new
1543			subdomain_form.form.fields = [
1544				{ var: "subdomain", value: "test" }
1545			]
1546
1547			launched = Snikket::Launched.new.as_error(
1548				"internal-server-error",
1549				:wait,
1550				"This is an error"
1551			)
1552
1553			result = execute_command do
1554				Command::COMMAND_MANAGER.expect(
1555					:write,
1556					EMPromise.resolve(subdomain_form),
1557					[Matching.new do |iq|
1558						assert_equal :form, iq.form.type
1559						assert iq.form.field("subdomain")
1560					end]
1561				)
1562
1563				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1564					:write,
1565					EMPromise.reject(launched),
1566					[Matching.new do |iq|
1567						assert_equal :set, iq.type
1568						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1569						assert_equal(
1570							"test.snikket.chat",
1571							iq.xpath(
1572								"./ns:launch/ns:domain",
1573								ns: "xmpp:snikket.org/hosting/v1"
1574							).text
1575						)
1576					end]
1577				)
1578
1579				stub_request(
1580					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1581				).to_timeout
1582
1583				Command::COMMAND_MANAGER.expect(
1584					:write,
1585					EMPromise.reject(:test_result),
1586					[Matching.new do |iq|
1587						assert iq.executing?
1588						assert_equal(
1589							"This is an error",
1590							iq.form.field("subdomain").desc
1591						)
1592					end]
1593				)
1594
1595				@snikket.write.catch { |e| e }
1596			end
1597
1598			assert_equal :test_result, result
1599			assert_mock Command::COMMAND_MANAGER
1600			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1601		end
1602		em :test_write_already_taken
1603	end
1604
1605	class SnikketCustomDomainTest < Minitest::Test
1606		def setup
1607			@snikket = Registration::FinishOnboarding::CustomDomain.new(
1608				customer,
1609				"+15555550000",
1610				db: FakeDB.new
1611			)
1612		end
1613
1614		def test_write_needs_dns
1615			domain_form = Blather::Stanza::Iq::Command.new
1616			domain_form.form.fields = [
1617				{ var: "domain", value: "snikket.example.com" }
1618			]
1619
1620			launched = Snikket::Launched.new
1621			launched << Niceogiri::XML::Node.new(
1622				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1623			).tap { |inner|
1624				inner << Niceogiri::XML::Node.new(
1625					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1626				).tap { |id|
1627					id.content = "si-1234"
1628				}
1629				inner << Niceogiri::XML::Node.new(
1630					:status, launched.document, "xmpp:snikket.org/hosting/v1"
1631				).tap { |id|
1632					id.content = "needs_dns"
1633				}
1634				inner << Niceogiri::XML::Node.new(
1635					:records, launched.document, "xmpp:snikket.org/hosting/v1"
1636				).tap { |records|
1637					records << Niceogiri::XML::Node.new(
1638						:record, launched.document, "xmpp:snikket.org/hosting/v1"
1639					).tap { |record|
1640						record << Niceogiri::XML::Node.new(
1641							:name, launched.document, "xmpp:snikket.org/hosting/v1"
1642						).tap { |name| name.content = "snikket.example.com" }
1643						record << Niceogiri::XML::Node.new(
1644							:type, launched.document, "xmpp:snikket.org/hosting/v1"
1645						).tap { |type| type.content = "AAAA" }
1646						record << Niceogiri::XML::Node.new(
1647							:status, launched.document, "xmpp:snikket.org/hosting/v1"
1648						).tap { |type| type.content = "incorrect" }
1649						record << Niceogiri::XML::Node.new(
1650							:expected, launched.document, "xmpp:snikket.org/hosting/v1"
1651						).tap { |expected|
1652							expected << Niceogiri::XML::Node.new(
1653								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1654							).tap { |value| value.content = "1::2" }
1655						}
1656						record << Niceogiri::XML::Node.new(
1657							:found, launched.document, "xmpp:snikket.org/hosting/v1"
1658						).tap { |found|
1659							found << Niceogiri::XML::Node.new(
1660								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1661							).tap { |value| value.content = "0::0" }
1662						}
1663					}
1664				}
1665			}
1666
1667			result = execute_command do
1668				Command::COMMAND_MANAGER.expect(
1669					:write,
1670					EMPromise.resolve(domain_form),
1671					[Matching.new do |iq|
1672						assert_equal :form, iq.form.type
1673						assert iq.form.field("domain")
1674					end]
1675				)
1676
1677				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1678					:write,
1679					EMPromise.resolve(launched),
1680					[Matching.new do |iq|
1681						assert_equal :set, iq.type
1682						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1683						assert_equal(
1684							"snikket.example.com",
1685							iq.xpath(
1686								"./ns:launch/ns:domain",
1687								ns: "xmpp:snikket.org/hosting/v1"
1688							).text
1689						)
1690					end]
1691				)
1692
1693				Command::COMMAND_MANAGER.expect(
1694					:write,
1695					EMPromise.reject(:test_result),
1696					[Matching.new do |iq|
1697						assert_equal :form, iq.form.type
1698						assert_equal(
1699							["snikket.example.com"],
1700							iq.form.xpath(
1701								"./ns:item/ns:field[@var='name']/ns:value",
1702								ns: "jabber:x:data"
1703							).map(&:content)
1704						)
1705						assert_equal(
1706							["1::2"],
1707							iq.form.xpath(
1708								"./ns:item/ns:field[@var='expected']/ns:value",
1709								ns: "jabber:x:data"
1710							).map(&:content)
1711						)
1712					end]
1713				)
1714
1715				@snikket.write.catch { |e| e }
1716			end
1717
1718			assert_equal :test_result, result
1719			assert_mock Command::COMMAND_MANAGER
1720			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1721		end
1722		em :test_write_needs_dns
1723	end
1724end