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