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				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 881				@mail = Registration::Payment::Mail.new(
 882					customer(plan_name: "test_cad"),
 883					@tel
 884				)
 885			end
 886
 887			def test_write
 888				result = execute_command do
 889					Command::COMMAND_MANAGER.expect(
 890						:write,
 891						EMPromise.reject(:test_result),
 892						[Matching.new do |reply|
 893							assert_equal [:execute, :prev], reply.allowed_actions
 894							refute reply.form.instructions.empty?
 895							assert_equal(
 896								"A Mailing Address",
 897								reply.form.field("adr").value
 898							)
 899							assert_equal(
 900								"interac@example.com",
 901								reply.form.field("interac_email").value
 902							)
 903						end]
 904					)
 905
 906					@mail.write.catch { |e| e }
 907				end
 908
 909				assert_equal :test_result, result
 910			end
 911			em :test_write
 912		end
 913
 914		class InviteCodeTest < Minitest::Test
 915			Registration::Payment::InviteCode::DB =
 916				Minitest::Mock.new
 917			Registration::Payment::InviteCode::REDIS =
 918				Minitest::Mock.new
 919			Command::COMMAND_MANAGER = Minitest::Mock.new
 920			Registration::Payment::InviteCode::Finish =
 921				Minitest::Mock.new
 922			Registration::Payment::MaybeBill::BillPlan =
 923				Minitest::Mock.new
 924
 925			def test_write
 926				customer = customer(plan_name: "test_usd")
 927				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 928				Registration::Payment::InviteCode::Finish.expect(
 929					:new,
 930					OpenStruct.new(write: nil),
 931					[
 932						customer,
 933						"+15555550000"
 934					]
 935				)
 936				execute_command do
 937					Registration::Payment::InviteCode::REDIS.expect(
 938						:get,
 939						EMPromise.resolve(nil),
 940						["jmp_invite_tries-test"]
 941					)
 942					Registration::Payment::InviteCode::REDIS.expect(
 943						:hget,
 944						EMPromise.resolve(nil),
 945						["jmp_parent_codes", "abc"]
 946					)
 947					Command::COMMAND_MANAGER.expect(
 948						:write,
 949						EMPromise.resolve(
 950							Blather::Stanza::Iq::Command.new.tap { |iq|
 951								iq.form.fields = [{ var: "code", value: "abc" }]
 952							}
 953						),
 954						[Matching.new do |reply|
 955							assert_equal :form, reply.form.type
 956							assert_nil reply.form.instructions
 957						end]
 958					)
 959
 960					Registration::Payment::InviteCode.new(
 961						customer,
 962						"+15555550000"
 963					).write
 964				end
 965				assert_mock Command::COMMAND_MANAGER
 966				assert_mock Registration::Payment::InviteCode::DB
 967				assert_mock Registration::Payment::InviteCode::REDIS
 968				assert_mock Registration::Payment::InviteCode::Finish
 969			end
 970			em :test_write
 971
 972			def test_write_parent_code
 973				customer = customer(plan_name: "test_usd")
 974				Registration::Payment::MaybeBill::BillPlan.expect(
 975					:new,
 976					OpenStruct.new(write: nil)
 977				) { |*| true }
 978				Registration::Payment::InviteCode::DB.expect(
 979					:query_one, {}, [String, "parent_customer"], default: {}
 980				)
 981				Registration::Payment::InviteCode::DB.expect(
 982					:query_one, { c: 0 }, [String, "parent_customer"], default: { c: 0 }
 983				)
 984				execute_command do
 985					Registration::Payment::InviteCode::REDIS.expect(
 986						:hget,
 987						EMPromise.resolve("parent_customer"),
 988						["jmp_parent_codes", "pabc"]
 989					)
 990					Registration::Payment::InviteCode::REDIS.expect(
 991						:get,
 992						EMPromise.resolve(nil),
 993						["jmp_customer_trust_level-parent_customer"]
 994					)
 995					CustomerPlan::DB.expect(
 996						:query,
 997						[{ "plan_name" => "test_usd" }],
 998						[String, ["parent_customer"]]
 999					)
1000					CustomerPlan::DB.expect(
1001						:exec_defer,
1002						EMPromise.resolve(nil),
1003						[String, ["test", "test_usd", "parent_customer"]]
1004					)
1005					Command.execution.customer_repo.expect(
1006						:find,
1007						customer.with_balance(10000),
1008						["test"]
1009					)
1010					Command::COMMAND_MANAGER.expect(
1011						:write,
1012						EMPromise.resolve(
1013							Blather::Stanza::Iq::Command.new.tap { |iq|
1014								iq.form.fields = [{ var: "code", value: "pabc" }]
1015							}
1016						),
1017						[Matching.new do |reply|
1018							assert_equal :form, reply.form.type
1019							assert_nil reply.form.instructions
1020						end]
1021					)
1022
1023					Registration::Payment::InviteCode.new(
1024						customer,
1025						"+15555550000"
1026					).write
1027				end
1028				assert_mock Command::COMMAND_MANAGER
1029				assert_mock Registration::Payment::InviteCode::DB
1030				assert_mock Registration::Payment::InviteCode::REDIS
1031				assert_mock Registration::Payment::MaybeBill::BillPlan
1032			end
1033			em :test_write_parent_code
1034
1035			def test_write_bad_code
1036				result = execute_command do
1037					customer = customer(plan_name: "test_usd")
1038					Registration::Payment::InviteCode::REDIS.expect(
1039						:set,
1040						EMPromise.resolve(nil),
1041						["jmp_customer_pending_invite-test", "abc"]
1042					)
1043					Registration::Payment::InviteCode::REDIS.expect(
1044						:get,
1045						EMPromise.resolve(0),
1046						["jmp_invite_tries-test"]
1047					)
1048					Registration::Payment::InviteCode::REDIS.expect(
1049						:hget,
1050						EMPromise.resolve(nil),
1051						["jmp_parent_codes", "abc"]
1052					)
1053					Registration::Payment::InviteCode::DB.expect(
1054						:transaction,
1055						[]
1056					) { |&blk| blk.call }
1057					Registration::Payment::InviteCode::DB.expect(
1058						:exec,
1059						OpenStruct.new(cmd_tuples: 0),
1060						[String, ["test", "abc"]]
1061					)
1062					Registration::Payment::InviteCode::REDIS.expect(
1063						:incr,
1064						EMPromise.resolve(nil),
1065						["jmp_invite_tries-test"]
1066					)
1067					Registration::Payment::InviteCode::REDIS.expect(
1068						:expire,
1069						EMPromise.resolve(nil),
1070						["jmp_invite_tries-test", 60 * 60]
1071					)
1072					Registration::Payment::InviteCode::REDIS.expect(
1073						:hexists,
1074						EMPromise.resolve(0),
1075						["jmp_group_codes", "abc"]
1076					)
1077					Command::COMMAND_MANAGER.expect(
1078						:write,
1079						EMPromise.resolve(
1080							Blather::Stanza::Iq::Command.new.tap { |iq|
1081								iq.form.fields = [{ var: "code", value: "abc" }]
1082							}
1083						),
1084						[Matching.new do |reply|
1085							assert_equal :form, reply.form.type
1086							assert_nil reply.form.instructions
1087						end]
1088					)
1089					Command::COMMAND_MANAGER.expect(
1090						:write,
1091						EMPromise.reject(:test_result),
1092						[Matching.new do |reply|
1093							assert_equal :form, reply.form.type
1094							assert_equal(
1095								"Not a valid invite code: abc",
1096								reply.form.instructions
1097							)
1098						end]
1099					)
1100
1101					Registration::Payment::InviteCode.new(
1102						customer,
1103						"+15555550000"
1104					).write.catch { |e| e }
1105				end
1106				assert_equal :test_result, result
1107				assert_mock Command::COMMAND_MANAGER
1108				assert_mock Registration::Payment::InviteCode::DB
1109				assert_mock Registration::Payment::InviteCode::REDIS
1110			end
1111			em :test_write_bad_code
1112
1113			def test_write_group_code
1114				result = execute_command do
1115					customer = customer(plan_name: "test_usd")
1116					Registration::Payment::InviteCode::REDIS.expect(
1117						:set,
1118						EMPromise.resolve(nil),
1119						["jmp_customer_pending_invite-test", "abc"]
1120					)
1121					Registration::Payment::InviteCode::REDIS.expect(
1122						:get,
1123						EMPromise.resolve(0),
1124						["jmp_invite_tries-test"]
1125					)
1126					Registration::Payment::InviteCode::REDIS.expect(
1127						:hget,
1128						EMPromise.resolve(nil),
1129						["jmp_parent_codes", "abc"]
1130					)
1131					Registration::Payment::InviteCode::DB.expect(
1132						:transaction,
1133						[]
1134					) { |&blk| blk.call }
1135					Registration::Payment::InviteCode::DB.expect(
1136						:exec,
1137						OpenStruct.new(cmd_tuples: 0),
1138						[String, ["test", "abc"]]
1139					)
1140					Registration::Payment::InviteCode::REDIS.expect(
1141						:incr,
1142						EMPromise.resolve(nil),
1143						["jmp_invite_tries-test"]
1144					)
1145					Registration::Payment::InviteCode::REDIS.expect(
1146						:expire,
1147						EMPromise.resolve(nil),
1148						["jmp_invite_tries-test", 60 * 60]
1149					)
1150					Registration::Payment::InviteCode::REDIS.expect(
1151						:hexists,
1152						EMPromise.resolve(1),
1153						["jmp_group_codes", "abc"]
1154					)
1155					Command::COMMAND_MANAGER.expect(
1156						:write,
1157						EMPromise.resolve(
1158							Blather::Stanza::Iq::Command.new.tap { |iq|
1159								iq.form.fields = [{ var: "code", value: "abc" }]
1160							}
1161						),
1162						[Matching.new do |reply|
1163							assert_equal :form, reply.form.type
1164							assert_nil reply.form.instructions
1165						end]
1166					)
1167					Command::COMMAND_MANAGER.expect(
1168						:write,
1169						EMPromise.reject(:test_result),
1170						[Matching.new do |reply|
1171							assert_equal :form, reply.form.type
1172							assert_equal(
1173								"abc is a post-payment referral",
1174								reply.form.instructions
1175							)
1176						end]
1177					)
1178
1179					Registration::Payment::InviteCode.new(
1180						customer,
1181						"+15555550000"
1182					).write.catch { |e| e }
1183				end
1184				assert_equal :test_result, result
1185				assert_mock Command::COMMAND_MANAGER
1186				assert_mock Registration::Payment::InviteCode::DB
1187				assert_mock Registration::Payment::InviteCode::REDIS
1188			end
1189			em :test_write_group_code
1190
1191			def test_write_bad_code_over_limit
1192				result = execute_command do
1193					customer = customer(plan_name: "test_usd")
1194					Registration::Payment::InviteCode::REDIS.expect(
1195						:get,
1196						EMPromise.resolve(11),
1197						["jmp_invite_tries-test"]
1198					)
1199					Registration::Payment::InviteCode::REDIS.expect(
1200						:hget,
1201						EMPromise.resolve(nil),
1202						["jmp_parent_codes", "abc"]
1203					)
1204					Command::COMMAND_MANAGER.expect(
1205						:write,
1206						EMPromise.resolve(
1207							Blather::Stanza::Iq::Command.new.tap { |iq|
1208								iq.form.fields = [{ var: "code", value: "abc" }]
1209							}
1210						),
1211						[Matching.new do |reply|
1212							assert_equal :form, reply.form.type
1213							assert_nil reply.form.instructions
1214						end]
1215					)
1216					Command::COMMAND_MANAGER.expect(
1217						:write,
1218						EMPromise.reject(:test_result),
1219						[Matching.new do |reply|
1220							assert_equal :form, reply.form.type
1221							assert_equal "Too many wrong attempts", reply.form.instructions
1222						end]
1223					)
1224					Registration::Payment::InviteCode.new(
1225						customer,
1226						"+15555550000"
1227					).write.catch { |e| e }
1228				end
1229				assert_equal :test_result, result
1230				assert_mock Command::COMMAND_MANAGER
1231				assert_mock Registration::Payment::InviteCode::REDIS
1232			end
1233			em :test_write_bad_code_over_limit
1234		end
1235	end
1236
1237	class FinishTest < Minitest::Test
1238		Customer::BLATHER = Minitest::Mock.new
1239		Command::COMMAND_MANAGER = Minitest::Mock.new
1240		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
1241		Registration::Finish::REDIS = Minitest::Mock.new
1242		Registration::Finish::DB = Minitest::Mock.new
1243		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
1244		Registration::FinishOnboarding::DB = FakeDB.new
1245		Transaction::DB = Minitest::Mock.new
1246
1247		def setup
1248			@sgx = Minitest::Mock.new(mksgx)
1249			iq = Blather::Stanza::Iq::Command.new
1250			iq.from = "test\\40example.com@cheogram.com"
1251			@finish = Registration::Finish.new(
1252				customer(sgx: @sgx, plan_name: "test_usd"),
1253				TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1254			)
1255		end
1256
1257		def test_write
1258			create_order = stub_request(
1259				:post,
1260				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1261			).to_return(status: 201, body: <<~RESPONSE)
1262				<OrderResponse>
1263					<Order>
1264						<id>test_order</id>
1265					</Order>
1266				</OrderResponse>
1267			RESPONSE
1268			stub_request(
1269				:get,
1270				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1271			).to_return(status: 201, body: <<~RESPONSE)
1272				<OrderResponse>
1273					<OrderStatus>COMPLETE</OrderStatus>
1274					<CompletedNumbers>
1275						<TelephoneNumber>
1276							<FullNumber>5555550000</FullNumber>
1277						</TelephoneNumber>
1278					</CompletedNumbers>
1279				</OrderResponse>
1280			RESPONSE
1281			stub_request(
1282				:post,
1283				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1284			)
1285			Registration::Finish::REDIS.expect(
1286				:get,
1287				nil,
1288				["jmp_customer_pending_invite-test"]
1289			)
1290			Registration::Finish::REDIS.expect(
1291				:del,
1292				nil,
1293				["jmp_customer_pending_invite-test"]
1294			)
1295			Registration::Finish::REDIS.expect(
1296				:hget,
1297				nil,
1298				["jmp_group_codes", nil]
1299			)
1300			Bwmsgsv2Repo::REDIS.expect(
1301				:get,
1302				EMPromise.resolve(nil),
1303				["jmp_customer_backend_sgx-test"]
1304			)
1305			Bwmsgsv2Repo::REDIS.expect(
1306				:set,
1307				nil,
1308				[
1309					"catapult_fwd-+15555550000",
1310					"xmpp:test@example.net"
1311				]
1312			)
1313			Bwmsgsv2Repo::REDIS.expect(
1314				:set,
1315				nil,
1316				["catapult_fwd_timeout-customer_test@component", 25]
1317			)
1318			Customer::BLATHER.expect(
1319				:<<,
1320				nil,
1321				[Matching.new do |m|
1322					assert_equal :chat, m.type
1323					assert m.body =~ /^Welcome to JMP/
1324				end]
1325			)
1326			blather = Minitest::Mock.new
1327			blather.expect(
1328				:<<,
1329				nil,
1330				[Matching.new do |reply|
1331					assert_equal :completed, reply.status
1332					assert_equal :info, reply.note_type
1333					assert_equal(
1334						"Your JMP account has been activated as (555) 555-0000",
1335						reply.note.content
1336					)
1337				end]
1338			)
1339			execute_command(blather: blather) do
1340				@sgx.expect(
1341					:register!,
1342					EMPromise.resolve(@sgx.with(
1343						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1344							ibr.phone = "+15555550000"
1345						end
1346					)),
1347					["+15555550000"]
1348				)
1349
1350				@finish.write
1351			end
1352			assert_requested create_order
1353			assert_mock @sgx
1354			assert_mock Registration::Finish::REDIS
1355			assert_mock Bwmsgsv2Repo::REDIS
1356			assert_mock Customer::BLATHER
1357			assert_mock blather
1358		end
1359		em :test_write
1360
1361		def test_write_with_pending_code
1362			create_order = stub_request(
1363				:post,
1364				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1365			).to_return(status: 201, body: <<~RESPONSE)
1366				<OrderResponse>
1367					<Order>
1368						<id>test_order</id>
1369					</Order>
1370				</OrderResponse>
1371			RESPONSE
1372			stub_request(
1373				:get,
1374				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1375			).to_return(status: 201, body: <<~RESPONSE)
1376				<OrderResponse>
1377					<OrderStatus>COMPLETE</OrderStatus>
1378					<CompletedNumbers>
1379						<TelephoneNumber>
1380							<FullNumber>5555550000</FullNumber>
1381						</TelephoneNumber>
1382					</CompletedNumbers>
1383				</OrderResponse>
1384			RESPONSE
1385			stub_request(
1386				:post,
1387				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1388			)
1389			Registration::Finish::REDIS.expect(
1390				:get,
1391				EMPromise.resolve("123"),
1392				["jmp_customer_pending_invite-test"]
1393			)
1394			Registration::Finish::REDIS.expect(
1395				:del,
1396				nil,
1397				["jmp_customer_pending_invite-test"]
1398			)
1399			Registration::Finish::REDIS.expect(
1400				:hget,
1401				EMPromise.resolve("test-inviter"),
1402				["jmp_group_codes", "123"]
1403			)
1404			Registration::Finish::DB.expect(
1405				:exec,
1406				EMPromise.resolve(nil),
1407				[String, ["test-inviter", "test"]]
1408			)
1409			Transaction::DB.expect(:transaction, nil) do |&blk|
1410				blk.call
1411				true
1412			end
1413			Transaction::DB.expect(
1414				:exec,
1415				nil,
1416				[String, Matching.new { |params|
1417					assert_equal "test", params[0]
1418					assert params[1].start_with?("referral_")
1419					assert_equal 1, params[4]
1420					assert_equal "Referral Bonus", params[5]
1421				}]
1422			)
1423			Bwmsgsv2Repo::REDIS.expect(
1424				:get,
1425				EMPromise.resolve(nil),
1426				["jmp_customer_backend_sgx-test"]
1427			)
1428			Bwmsgsv2Repo::REDIS.expect(
1429				:set,
1430				nil,
1431				[
1432					"catapult_fwd-+15555550000",
1433					"xmpp:test@example.net"
1434				]
1435			)
1436			Bwmsgsv2Repo::REDIS.expect(
1437				:set,
1438				nil,
1439				["catapult_fwd_timeout-customer_test@component", 25]
1440			)
1441			Customer::BLATHER.expect(
1442				:<<,
1443				nil,
1444				[Matching.new do |m|
1445					assert_equal :chat, m.type
1446					assert m.body =~ /^Welcome to JMP/
1447				end]
1448			)
1449			blather = Minitest::Mock.new
1450			blather.expect(
1451				:<<,
1452				nil,
1453				[Matching.new do |reply|
1454					assert_equal :completed, reply.status
1455					assert_equal :info, reply.note_type
1456					assert_equal(
1457						"Your JMP account has been activated as (555) 555-0000",
1458						reply.note.content
1459					)
1460				end]
1461			)
1462			execute_command(blather: blather) do
1463				@sgx.expect(
1464					:register!,
1465					EMPromise.resolve(@sgx.with(
1466						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1467							ibr.phone = "+15555550000"
1468						end
1469					)),
1470					["+15555550000"]
1471				)
1472
1473				@finish.write
1474			end
1475			assert_requested create_order
1476			assert_mock @sgx
1477			assert_mock Registration::Finish::REDIS
1478			assert_mock Bwmsgsv2Repo::REDIS
1479			assert_mock Customer::BLATHER
1480			assert_mock blather
1481			assert_mock Transaction::DB
1482		end
1483		em :test_write_with_pending_code
1484
1485		def test_write_onboarding
1486			create_order = stub_request(
1487				:post,
1488				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1489			).to_return(status: 201, body: <<~RESPONSE)
1490				<OrderResponse>
1491					<Order>
1492						<id>test_order</id>
1493					</Order>
1494				</OrderResponse>
1495			RESPONSE
1496			stub_request(
1497				:get,
1498				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1499			).to_return(status: 201, body: <<~RESPONSE)
1500				<OrderResponse>
1501					<OrderStatus>COMPLETE</OrderStatus>
1502					<CompletedNumbers>
1503						<TelephoneNumber>
1504							<FullNumber>5555550000</FullNumber>
1505						</TelephoneNumber>
1506					</CompletedNumbers>
1507				</OrderResponse>
1508			RESPONSE
1509			stub_request(
1510				:post,
1511				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1512			)
1513			Registration::Finish::REDIS.expect(
1514				:get,
1515				nil,
1516				["jmp_customer_pending_invite-test"]
1517			)
1518			Registration::Finish::REDIS.expect(
1519				:del,
1520				nil,
1521				["jmp_customer_pending_invite-test"]
1522			)
1523			Registration::Finish::REDIS.expect(
1524				:hget,
1525				nil,
1526				["jmp_group_codes", nil]
1527			)
1528			Bwmsgsv2Repo::REDIS.expect(
1529				:get,
1530				EMPromise.resolve(nil),
1531				["jmp_customer_backend_sgx-test"]
1532			)
1533			Bwmsgsv2Repo::REDIS.expect(
1534				:set,
1535				nil,
1536				[
1537					"catapult_fwd-+15555550000",
1538					"xmpp:test\\40onboarding.example.com@proxy"
1539				]
1540			)
1541			Bwmsgsv2Repo::REDIS.expect(
1542				:set,
1543				nil,
1544				["catapult_fwd_timeout-customer_test@component", 25]
1545			)
1546			result = execute_command do
1547				@sgx.expect(
1548					:register!,
1549					EMPromise.resolve(@sgx.with(
1550						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1551							ibr.phone = "+15555550000"
1552						end
1553					)),
1554					["+15555550000"]
1555				)
1556
1557				Command::COMMAND_MANAGER.expect(
1558					:write,
1559					EMPromise.reject(:test_result),
1560					[Matching.new do |iq|
1561						assert_equal :form, iq.form.type
1562						assert iq.form.field("subdomain")
1563					end]
1564				)
1565
1566				Registration::Finish.new(
1567					customer(
1568						sgx: @sgx,
1569						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1570					),
1571					TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1572				).write.catch { |e| e }
1573			end
1574			assert_equal :test_result, result
1575			assert_requested create_order
1576			assert_mock @sgx
1577			assert_mock Registration::Finish::REDIS
1578			assert_mock Bwmsgsv2Repo::REDIS
1579			assert_mock Command::COMMAND_MANAGER
1580		end
1581		em :test_write_onboarding
1582
1583		def test_write_local_inventory
1584			stub_request(
1585				:post,
1586				"https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
1587			).with(
1588				body: {
1589					CustomerOrderId: "test",
1590					SourceAccountId: "bandwidth_account_id",
1591					SiteId: "test_site",
1592					SipPeerId: "test_peer",
1593					TelephoneNumbers: { TelephoneNumber: "5555550000" }
1594				}.to_xml(indent: 0, root: "MoveTnsOrder")
1595			).to_return(status: 200, body: "", headers: {})
1596
1597			Registration::Finish::REDIS.expect(
1598				:get,
1599				nil,
1600				["jmp_customer_pending_invite-test"]
1601			)
1602			Registration::Finish::REDIS.expect(
1603				:del,
1604				nil,
1605				["jmp_customer_pending_invite-test"]
1606			)
1607			Registration::Finish::REDIS.expect(
1608				:hget,
1609				nil,
1610				["jmp_group_codes", nil]
1611			)
1612			Registration::Finish::DB.expect(
1613				:exec_defer,
1614				EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
1615				[String, ["+15555550000"]]
1616			)
1617			Bwmsgsv2Repo::REDIS.expect(
1618				:get,
1619				EMPromise.resolve(nil),
1620				["jmp_customer_backend_sgx-test"]
1621			)
1622			Bwmsgsv2Repo::REDIS.expect(
1623				:set,
1624				nil,
1625				[
1626					"catapult_fwd-+15555550000",
1627					"xmpp:test\\40onboarding.example.com@proxy"
1628				]
1629			)
1630			Bwmsgsv2Repo::REDIS.expect(
1631				:set,
1632				nil,
1633				["catapult_fwd_timeout-customer_test@component", 25]
1634			)
1635			result = execute_command do
1636				@sgx.expect(
1637					:register!,
1638					EMPromise.resolve(@sgx.with(
1639						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1640							ibr.phone = "+15555550000"
1641						end
1642					)),
1643					["+15555550000"]
1644				)
1645
1646				Command::COMMAND_MANAGER.expect(
1647					:write,
1648					EMPromise.reject(:test_result),
1649					[Matching.new do |iq|
1650						assert_equal :form, iq.form.type
1651						assert iq.form.field("subdomain")
1652					end]
1653				)
1654
1655				Registration::Finish.new(
1656					customer(
1657						sgx: @sgx,
1658						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1659					),
1660					TelSelections::ChooseTel::Tn::LocalInventory.new(
1661						TelSelections::ChooseTel::Tn.new("+15555550000"),
1662						"bandwidth_account_id"
1663					)
1664				).write.catch { |e| e }
1665			end
1666			assert_equal :test_result, result
1667			assert_mock @sgx
1668			assert_mock Registration::Finish::REDIS
1669			assert_mock Bwmsgsv2Repo::REDIS
1670			assert_mock Command::COMMAND_MANAGER
1671		end
1672		em :test_write_local_inventory
1673
1674		def test_write_tn_fail
1675			create_order = stub_request(
1676				:post,
1677				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1678			).to_return(status: 201, body: <<~RESPONSE)
1679				<OrderResponse>
1680					<Order>
1681						<id>test_order</id>
1682					</Order>
1683				</OrderResponse>
1684			RESPONSE
1685			stub_request(
1686				:get,
1687				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1688			).to_return(status: 201, body: <<~RESPONSE)
1689				<OrderResponse>
1690					<OrderStatus>FAILED</OrderStatus>
1691				</OrderResponse>
1692			RESPONSE
1693
1694			result = execute_command do
1695				Command::COMMAND_MANAGER.expect(
1696					:write,
1697					EMPromise.reject(:test_result),
1698					[Matching.new do |iq|
1699						assert_equal :form, iq.form.type
1700						assert_equal(
1701							"The JMP number (555) 555-0000 is no longer available.",
1702							iq.form.instructions
1703						)
1704					end]
1705				)
1706
1707				@finish.write.catch { |e| e }
1708			end
1709
1710			assert_equal :test_result, result
1711			assert_mock Command::COMMAND_MANAGER
1712			assert_instance_of(
1713				TelSelections::ChooseTel,
1714				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1715			)
1716			assert_requested create_order
1717		end
1718		em :test_write_tn_fail
1719	end
1720
1721	class SnikketTest < Minitest::Test
1722		Command::COMMAND_MANAGER = Minitest::Mock.new
1723		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1724
1725		def setup
1726			@sgx = Minitest::Mock.new(mksgx)
1727			@snikket = Registration::FinishOnboarding::Snikket.new(
1728				customer(sgx: @sgx),
1729				"+15555550000",
1730				db: FakeDB.new
1731			)
1732		end
1733
1734		def test_write
1735			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1736
1737			subdomain_form = Blather::Stanza::Iq::Command.new
1738			subdomain_form.form.fields = [
1739				{ var: "subdomain", value: "test" }
1740			]
1741
1742			launched = Snikket::Launched.new
1743			launched << Niceogiri::XML::Node.new(
1744				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1745			).tap { |inner|
1746				inner << Niceogiri::XML::Node.new(
1747					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1748				).tap { |id|
1749					id.content = "si-1234"
1750				}
1751				inner << Niceogiri::XML::Node.new(
1752					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1753				).tap { |bootstrap|
1754					bootstrap << Niceogiri::XML::Node.new(
1755						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1756					).tap { |token|
1757						token.content = "TOKEN"
1758					}
1759				}
1760			}
1761
1762			blather = Minitest::Mock.new
1763			blather.expect(
1764				:<<,
1765				nil,
1766				[Matching.new do |reply|
1767					assert_equal :completed, reply.status
1768					assert_equal(
1769						xmpp_uri,
1770						OOB.find_or_create(reply.command).url
1771					)
1772				end]
1773			)
1774
1775			execute_command(blather: blather) do
1776				Command::COMMAND_MANAGER.expect(
1777					:write,
1778					EMPromise.resolve(subdomain_form),
1779					[Matching.new do |iq|
1780						assert_equal :form, iq.form.type
1781						assert iq.form.field("subdomain")
1782					end]
1783				)
1784
1785				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1786					:write,
1787					EMPromise.resolve(launched),
1788					[Matching.new do |iq|
1789						assert_equal :set, iq.type
1790						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1791						assert_equal(
1792							"test.snikket.chat",
1793							iq.xpath(
1794								"./ns:launch/ns:domain",
1795								ns: "xmpp:snikket.org/hosting/v1"
1796							).text
1797						)
1798					end]
1799				)
1800
1801				# Webmock doesn't support redirects properly, but they work live
1802				stub_request(
1803					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1804				).to_return(
1805					status: 200,
1806					headers: {
1807						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1808					}
1809				)
1810
1811				@snikket.write
1812			end
1813
1814			assert_mock Command::COMMAND_MANAGER
1815			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1816			assert_mock blather
1817		end
1818		em :test_write
1819
1820		def test_write_not_yet
1821			subdomain_form = Blather::Stanza::Iq::Command.new
1822			subdomain_form.form.fields = [
1823				{ var: "subdomain", value: "test" }
1824			]
1825
1826			launched = Snikket::Launched.new
1827			launched << Niceogiri::XML::Node.new(
1828				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1829			).tap { |inner|
1830				inner << Niceogiri::XML::Node.new(
1831					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1832				).tap { |id|
1833					id.content = "si-1234"
1834				}
1835				inner << Niceogiri::XML::Node.new(
1836					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1837				).tap { |bootstrap|
1838					bootstrap << Niceogiri::XML::Node.new(
1839						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1840					).tap { |token|
1841						token.content = "TOKEN"
1842					}
1843				}
1844			}
1845
1846			result = execute_command do
1847				Command::COMMAND_MANAGER.expect(
1848					:write,
1849					EMPromise.resolve(subdomain_form),
1850					[Matching.new do |iq|
1851						assert_equal :form, iq.form.type
1852						assert iq.form.field("subdomain")
1853					end]
1854				)
1855
1856				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1857					:write,
1858					EMPromise.resolve(launched),
1859					[Matching.new do |iq|
1860						assert_equal :set, iq.type
1861						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1862						assert_equal(
1863							"test.snikket.chat",
1864							iq.xpath(
1865								"./ns:launch/ns:domain",
1866								ns: "xmpp:snikket.org/hosting/v1"
1867							).text
1868						)
1869					end]
1870				)
1871
1872				stub_request(
1873					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1874				).to_timeout
1875
1876				Command::COMMAND_MANAGER.expect(
1877					:write,
1878					EMPromise.reject(:test_result),
1879					[Matching.new do |iq|
1880						assert_equal :result, iq.form.type
1881						assert iq.form.instructions =~ / test\.snikket\.chat /
1882						assert_equal "jid-single", iq.form.field("support").type
1883					end]
1884				)
1885
1886				@snikket.write.catch { |e| e }
1887			end
1888
1889			assert_equal :test_result, result
1890			assert_mock Command::COMMAND_MANAGER
1891			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1892		end
1893		em :test_write_not_yet
1894
1895		def test_write_already_taken
1896			subdomain_form = Blather::Stanza::Iq::Command.new
1897			subdomain_form.form.fields = [
1898				{ var: "subdomain", value: "test" }
1899			]
1900
1901			launched = Snikket::Launched.new.as_error(
1902				"internal-server-error",
1903				:wait,
1904				"This is an error"
1905			)
1906
1907			result = execute_command do
1908				Command::COMMAND_MANAGER.expect(
1909					:write,
1910					EMPromise.resolve(subdomain_form),
1911					[Matching.new do |iq|
1912						assert_equal :form, iq.form.type
1913						assert iq.form.field("subdomain")
1914					end]
1915				)
1916
1917				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1918					:write,
1919					EMPromise.reject(launched),
1920					[Matching.new do |iq|
1921						assert_equal :set, iq.type
1922						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1923						assert_equal(
1924							"test.snikket.chat",
1925							iq.xpath(
1926								"./ns:launch/ns:domain",
1927								ns: "xmpp:snikket.org/hosting/v1"
1928							).text
1929						)
1930					end]
1931				)
1932
1933				stub_request(
1934					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1935				).to_timeout
1936
1937				Command::COMMAND_MANAGER.expect(
1938					:write,
1939					EMPromise.reject(:test_result),
1940					[Matching.new do |iq|
1941						assert iq.executing?
1942						assert_equal(
1943							"This is an error",
1944							iq.form.field("subdomain").desc
1945						)
1946					end]
1947				)
1948
1949				@snikket.write.catch { |e| e }
1950			end
1951
1952			assert_equal :test_result, result
1953			assert_mock Command::COMMAND_MANAGER
1954			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1955		end
1956		em :test_write_already_taken
1957	end
1958
1959	class SnikketCustomDomainTest < Minitest::Test
1960		def setup
1961			@snikket = Registration::FinishOnboarding::CustomDomain.new(
1962				customer,
1963				"+15555550000",
1964				db: FakeDB.new
1965			)
1966		end
1967
1968		def test_write_needs_dns
1969			domain_form = Blather::Stanza::Iq::Command.new
1970			domain_form.form.fields = [
1971				{ var: "domain", value: "snikket.example.com" }
1972			]
1973
1974			launched = Snikket::Launched.new
1975			launched << Niceogiri::XML::Node.new(
1976				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1977			).tap { |inner|
1978				inner << Niceogiri::XML::Node.new(
1979					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1980				).tap { |id|
1981					id.content = "si-1234"
1982				}
1983				inner << Niceogiri::XML::Node.new(
1984					:status, launched.document, "xmpp:snikket.org/hosting/v1"
1985				).tap { |id|
1986					id.content = "needs_dns"
1987				}
1988				inner << Niceogiri::XML::Node.new(
1989					:records, launched.document, "xmpp:snikket.org/hosting/v1"
1990				).tap { |records|
1991					records << Niceogiri::XML::Node.new(
1992						:record, launched.document, "xmpp:snikket.org/hosting/v1"
1993					).tap { |record|
1994						record << Niceogiri::XML::Node.new(
1995							:name, launched.document, "xmpp:snikket.org/hosting/v1"
1996						).tap { |name| name.content = "snikket.example.com" }
1997						record << Niceogiri::XML::Node.new(
1998							:type, launched.document, "xmpp:snikket.org/hosting/v1"
1999						).tap { |type| type.content = "AAAA" }
2000						record << Niceogiri::XML::Node.new(
2001							:status, launched.document, "xmpp:snikket.org/hosting/v1"
2002						).tap { |type| type.content = "incorrect" }
2003						record << Niceogiri::XML::Node.new(
2004							:expected, launched.document, "xmpp:snikket.org/hosting/v1"
2005						).tap { |expected|
2006							expected << Niceogiri::XML::Node.new(
2007								:value, launched.document, "xmpp:snikket.org/hosting/v1"
2008							).tap { |value| value.content = "1::2" }
2009						}
2010						record << Niceogiri::XML::Node.new(
2011							:found, launched.document, "xmpp:snikket.org/hosting/v1"
2012						).tap { |found|
2013							found << Niceogiri::XML::Node.new(
2014								:value, launched.document, "xmpp:snikket.org/hosting/v1"
2015							).tap { |value| value.content = "0::0" }
2016						}
2017					}
2018				}
2019			}
2020
2021			result = execute_command do
2022				Command::COMMAND_MANAGER.expect(
2023					:write,
2024					EMPromise.resolve(domain_form),
2025					[Matching.new do |iq|
2026						assert_equal :form, iq.form.type
2027						assert iq.form.field("domain")
2028					end]
2029				)
2030
2031				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
2032					:write,
2033					EMPromise.resolve(launched),
2034					[Matching.new do |iq|
2035						assert_equal :set, iq.type
2036						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
2037						assert_equal(
2038							"snikket.example.com",
2039							iq.xpath(
2040								"./ns:launch/ns:domain",
2041								ns: "xmpp:snikket.org/hosting/v1"
2042							).text
2043						)
2044					end]
2045				)
2046
2047				Command::COMMAND_MANAGER.expect(
2048					:write,
2049					EMPromise.reject(:test_result),
2050					[Matching.new do |iq|
2051						assert_equal :form, iq.form.type
2052						assert_equal(
2053							["snikket.example.com"],
2054							iq.form.xpath(
2055								"./ns:item/ns:field[@var='name']/ns:value",
2056								ns: "jabber:x:data"
2057							).map(&:content)
2058						)
2059						assert_equal(
2060							["1::2"],
2061							iq.form.xpath(
2062								"./ns:item/ns:field[@var='expected']/ns:value",
2063								ns: "jabber:x:data"
2064							).map(&:content)
2065						)
2066					end]
2067				)
2068
2069				@snikket.write.catch { |e| e }
2070			end
2071
2072			assert_equal :test_result, result
2073			assert_mock Command::COMMAND_MANAGER
2074			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
2075		end
2076		em :test_write_needs_dns
2077	end
2078end