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_tn_fail
1505			create_order = stub_request(
1506				:post,
1507				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1508			).to_return(status: 201, body: <<~RESPONSE)
1509				<OrderResponse>
1510					<Order>
1511						<id>test_order</id>
1512					</Order>
1513				</OrderResponse>
1514			RESPONSE
1515			stub_request(
1516				:get,
1517				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1518			).to_return(status: 201, body: <<~RESPONSE)
1519				<OrderResponse>
1520					<OrderStatus>FAILED</OrderStatus>
1521				</OrderResponse>
1522			RESPONSE
1523
1524			result = execute_command do
1525				Command::COMMAND_MANAGER.expect(
1526					:write,
1527					EMPromise.reject(:test_result),
1528					[Matching.new do |iq|
1529						assert_equal :form, iq.form.type
1530						assert_equal(
1531							"The JMP number (555) 555-0000 is no longer available.",
1532							iq.form.instructions
1533						)
1534					end]
1535				)
1536
1537				@finish.write.catch { |e| e }
1538			end
1539
1540			assert_equal :test_result, result
1541			assert_mock Command::COMMAND_MANAGER
1542			assert_instance_of(
1543				TelSelections::ChooseTel,
1544				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1545			)
1546			assert_requested create_order
1547		end
1548		em :test_write_tn_fail
1549	end
1550
1551	class SnikketTest < Minitest::Test
1552		Command::COMMAND_MANAGER = Minitest::Mock.new
1553		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1554
1555		def setup
1556			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
1557			@snikket = Registration::FinishOnboarding::Snikket.new(
1558				customer,
1559				"+15555550000",
1560				db: FakeDB.new
1561			)
1562		end
1563
1564		def test_write
1565			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1566
1567			subdomain_form = Blather::Stanza::Iq::Command.new
1568			subdomain_form.form.fields = [
1569				{ var: "subdomain", value: "test" }
1570			]
1571
1572			launched = Snikket::Launched.new
1573			launched << Niceogiri::XML::Node.new(
1574				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1575			).tap { |inner|
1576				inner << Niceogiri::XML::Node.new(
1577					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1578				).tap { |id|
1579					id.content = "si-1234"
1580				}
1581				inner << Niceogiri::XML::Node.new(
1582					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1583				).tap { |bootstrap|
1584					bootstrap << Niceogiri::XML::Node.new(
1585						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1586					).tap { |token|
1587						token.content = "TOKEN"
1588					}
1589				}
1590			}
1591
1592			blather = Minitest::Mock.new
1593			blather.expect(
1594				:<<,
1595				nil,
1596				[Matching.new do |reply|
1597					assert_equal :completed, reply.status
1598					assert_equal(
1599						xmpp_uri,
1600						OOB.find_or_create(reply.command).url
1601					)
1602				end]
1603			)
1604
1605			execute_command(blather: blather) do
1606				Command::COMMAND_MANAGER.expect(
1607					:write,
1608					EMPromise.resolve(subdomain_form),
1609					[Matching.new do |iq|
1610						assert_equal :form, iq.form.type
1611						assert iq.form.field("subdomain")
1612					end]
1613				)
1614
1615				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1616					:write,
1617					EMPromise.resolve(launched),
1618					[Matching.new do |iq|
1619						assert_equal :set, iq.type
1620						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1621						assert_equal(
1622							"test.snikket.chat",
1623							iq.xpath(
1624								"./ns:launch/ns:domain",
1625								ns: "xmpp:snikket.org/hosting/v1"
1626							).text
1627						)
1628					end]
1629				)
1630
1631				# Webmock doesn't support redirects properly, but they work live
1632				stub_request(
1633					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1634				).to_return(
1635					status: 200,
1636					headers: {
1637						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1638					}
1639				)
1640
1641				@snikket.write
1642			end
1643
1644			assert_mock Command::COMMAND_MANAGER
1645			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1646			assert_mock blather
1647		end
1648		em :test_write
1649
1650		def test_write_not_yet
1651			subdomain_form = Blather::Stanza::Iq::Command.new
1652			subdomain_form.form.fields = [
1653				{ var: "subdomain", value: "test" }
1654			]
1655
1656			launched = Snikket::Launched.new
1657			launched << Niceogiri::XML::Node.new(
1658				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1659			).tap { |inner|
1660				inner << Niceogiri::XML::Node.new(
1661					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1662				).tap { |id|
1663					id.content = "si-1234"
1664				}
1665				inner << Niceogiri::XML::Node.new(
1666					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1667				).tap { |bootstrap|
1668					bootstrap << Niceogiri::XML::Node.new(
1669						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1670					).tap { |token|
1671						token.content = "TOKEN"
1672					}
1673				}
1674			}
1675
1676			result = execute_command do
1677				Command::COMMAND_MANAGER.expect(
1678					:write,
1679					EMPromise.resolve(subdomain_form),
1680					[Matching.new do |iq|
1681						assert_equal :form, iq.form.type
1682						assert iq.form.field("subdomain")
1683					end]
1684				)
1685
1686				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1687					:write,
1688					EMPromise.resolve(launched),
1689					[Matching.new do |iq|
1690						assert_equal :set, iq.type
1691						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1692						assert_equal(
1693							"test.snikket.chat",
1694							iq.xpath(
1695								"./ns:launch/ns:domain",
1696								ns: "xmpp:snikket.org/hosting/v1"
1697							).text
1698						)
1699					end]
1700				)
1701
1702				stub_request(
1703					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1704				).to_timeout
1705
1706				Command::COMMAND_MANAGER.expect(
1707					:write,
1708					EMPromise.reject(:test_result),
1709					[Matching.new do |iq|
1710						assert_equal :result, iq.form.type
1711						assert iq.form.instructions =~ / test\.snikket\.chat /
1712						assert_equal "jid-single", iq.form.field("support").type
1713					end]
1714				)
1715
1716				@snikket.write.catch { |e| e }
1717			end
1718
1719			assert_equal :test_result, result
1720			assert_mock Command::COMMAND_MANAGER
1721			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1722		end
1723		em :test_write_not_yet
1724
1725		def test_write_already_taken
1726			subdomain_form = Blather::Stanza::Iq::Command.new
1727			subdomain_form.form.fields = [
1728				{ var: "subdomain", value: "test" }
1729			]
1730
1731			launched = Snikket::Launched.new.as_error(
1732				"internal-server-error",
1733				:wait,
1734				"This is an error"
1735			)
1736
1737			result = execute_command do
1738				Command::COMMAND_MANAGER.expect(
1739					:write,
1740					EMPromise.resolve(subdomain_form),
1741					[Matching.new do |iq|
1742						assert_equal :form, iq.form.type
1743						assert iq.form.field("subdomain")
1744					end]
1745				)
1746
1747				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1748					:write,
1749					EMPromise.reject(launched),
1750					[Matching.new do |iq|
1751						assert_equal :set, iq.type
1752						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1753						assert_equal(
1754							"test.snikket.chat",
1755							iq.xpath(
1756								"./ns:launch/ns:domain",
1757								ns: "xmpp:snikket.org/hosting/v1"
1758							).text
1759						)
1760					end]
1761				)
1762
1763				stub_request(
1764					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1765				).to_timeout
1766
1767				Command::COMMAND_MANAGER.expect(
1768					:write,
1769					EMPromise.reject(:test_result),
1770					[Matching.new do |iq|
1771						assert iq.executing?
1772						assert_equal(
1773							"This is an error",
1774							iq.form.field("subdomain").desc
1775						)
1776					end]
1777				)
1778
1779				@snikket.write.catch { |e| e }
1780			end
1781
1782			assert_equal :test_result, result
1783			assert_mock Command::COMMAND_MANAGER
1784			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1785		end
1786		em :test_write_already_taken
1787	end
1788
1789	class SnikketCustomDomainTest < Minitest::Test
1790		def setup
1791			@snikket = Registration::FinishOnboarding::CustomDomain.new(
1792				customer,
1793				"+15555550000",
1794				db: FakeDB.new
1795			)
1796		end
1797
1798		def test_write_needs_dns
1799			domain_form = Blather::Stanza::Iq::Command.new
1800			domain_form.form.fields = [
1801				{ var: "domain", value: "snikket.example.com" }
1802			]
1803
1804			launched = Snikket::Launched.new
1805			launched << Niceogiri::XML::Node.new(
1806				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1807			).tap { |inner|
1808				inner << Niceogiri::XML::Node.new(
1809					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1810				).tap { |id|
1811					id.content = "si-1234"
1812				}
1813				inner << Niceogiri::XML::Node.new(
1814					:status, launched.document, "xmpp:snikket.org/hosting/v1"
1815				).tap { |id|
1816					id.content = "needs_dns"
1817				}
1818				inner << Niceogiri::XML::Node.new(
1819					:records, launched.document, "xmpp:snikket.org/hosting/v1"
1820				).tap { |records|
1821					records << Niceogiri::XML::Node.new(
1822						:record, launched.document, "xmpp:snikket.org/hosting/v1"
1823					).tap { |record|
1824						record << Niceogiri::XML::Node.new(
1825							:name, launched.document, "xmpp:snikket.org/hosting/v1"
1826						).tap { |name| name.content = "snikket.example.com" }
1827						record << Niceogiri::XML::Node.new(
1828							:type, launched.document, "xmpp:snikket.org/hosting/v1"
1829						).tap { |type| type.content = "AAAA" }
1830						record << Niceogiri::XML::Node.new(
1831							:status, launched.document, "xmpp:snikket.org/hosting/v1"
1832						).tap { |type| type.content = "incorrect" }
1833						record << Niceogiri::XML::Node.new(
1834							:expected, launched.document, "xmpp:snikket.org/hosting/v1"
1835						).tap { |expected|
1836							expected << Niceogiri::XML::Node.new(
1837								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1838							).tap { |value| value.content = "1::2" }
1839						}
1840						record << Niceogiri::XML::Node.new(
1841							:found, launched.document, "xmpp:snikket.org/hosting/v1"
1842						).tap { |found|
1843							found << Niceogiri::XML::Node.new(
1844								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1845							).tap { |value| value.content = "0::0" }
1846						}
1847					}
1848				}
1849			}
1850
1851			result = execute_command do
1852				Command::COMMAND_MANAGER.expect(
1853					:write,
1854					EMPromise.resolve(domain_form),
1855					[Matching.new do |iq|
1856						assert_equal :form, iq.form.type
1857						assert iq.form.field("domain")
1858					end]
1859				)
1860
1861				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1862					:write,
1863					EMPromise.resolve(launched),
1864					[Matching.new do |iq|
1865						assert_equal :set, iq.type
1866						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1867						assert_equal(
1868							"snikket.example.com",
1869							iq.xpath(
1870								"./ns:launch/ns:domain",
1871								ns: "xmpp:snikket.org/hosting/v1"
1872							).text
1873						)
1874					end]
1875				)
1876
1877				Command::COMMAND_MANAGER.expect(
1878					:write,
1879					EMPromise.reject(:test_result),
1880					[Matching.new do |iq|
1881						assert_equal :form, iq.form.type
1882						assert_equal(
1883							["snikket.example.com"],
1884							iq.form.xpath(
1885								"./ns:item/ns:field[@var='name']/ns:value",
1886								ns: "jabber:x:data"
1887							).map(&:content)
1888						)
1889						assert_equal(
1890							["1::2"],
1891							iq.form.xpath(
1892								"./ns:item/ns:field[@var='expected']/ns:value",
1893								ns: "jabber:x:data"
1894							).map(&:content)
1895						)
1896					end]
1897				)
1898
1899				@snikket.write.catch { |e| e }
1900			end
1901
1902			assert_equal :test_result, result
1903			assert_mock Command::COMMAND_MANAGER
1904			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1905		end
1906		em :test_write_needs_dns
1907	end
1908end