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