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