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