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