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(mksgx)
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				:get,
1238				EMPromise.resolve(nil),
1239				["jmp_customer_backend_sgx-test"]
1240			)
1241			Bwmsgsv2Repo::REDIS.expect(
1242				:set,
1243				nil,
1244				[
1245					"catapult_fwd-+15555550000",
1246					"xmpp:test@example.net"
1247				]
1248			)
1249			Bwmsgsv2Repo::REDIS.expect(
1250				:set,
1251				nil,
1252				["catapult_fwd_timeout-customer_test@component", 25]
1253			)
1254			Customer::BLATHER.expect(
1255				:<<,
1256				nil,
1257				[Matching.new do |m|
1258					assert_equal :chat, m.type
1259					assert m.body =~ /^Welcome to JMP/
1260				end]
1261			)
1262			blather = Minitest::Mock.new
1263			blather.expect(
1264				:<<,
1265				nil,
1266				[Matching.new do |reply|
1267					assert_equal :completed, reply.status
1268					assert_equal :info, reply.note_type
1269					assert_equal(
1270						"Your JMP account has been activated as (555) 555-0000",
1271						reply.note.content
1272					)
1273				end]
1274			)
1275			execute_command(blather: blather) do
1276				@sgx.expect(
1277					:register!,
1278					EMPromise.resolve(@sgx.with(
1279						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1280							ibr.phone = "+15555550000"
1281						end
1282					)),
1283					["+15555550000"]
1284				)
1285
1286				@finish.write
1287			end
1288			assert_requested create_order
1289			assert_mock @sgx
1290			assert_mock Registration::Finish::REDIS
1291			assert_mock Bwmsgsv2Repo::REDIS
1292			assert_mock Customer::BLATHER
1293			assert_mock blather
1294		end
1295		em :test_write
1296
1297		def test_write_with_pending_code
1298			create_order = stub_request(
1299				:post,
1300				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1301			).to_return(status: 201, body: <<~RESPONSE)
1302				<OrderResponse>
1303					<Order>
1304						<id>test_order</id>
1305					</Order>
1306				</OrderResponse>
1307			RESPONSE
1308			stub_request(
1309				:get,
1310				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1311			).to_return(status: 201, body: <<~RESPONSE)
1312				<OrderResponse>
1313					<OrderStatus>COMPLETE</OrderStatus>
1314					<CompletedNumbers>
1315						<TelephoneNumber>
1316							<FullNumber>5555550000</FullNumber>
1317						</TelephoneNumber>
1318					</CompletedNumbers>
1319				</OrderResponse>
1320			RESPONSE
1321			stub_request(
1322				:post,
1323				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1324			)
1325			Registration::Finish::REDIS.expect(
1326				:get,
1327				EMPromise.resolve("123"),
1328				["jmp_customer_pending_invite-test"]
1329			)
1330			Registration::Finish::REDIS.expect(
1331				:del,
1332				nil,
1333				["jmp_customer_pending_invite-test"]
1334			)
1335			Registration::Finish::REDIS.expect(
1336				:hget,
1337				EMPromise.resolve("test-inviter"),
1338				["jmp_group_codes", "123"]
1339			)
1340			Registration::Finish::DB.expect(
1341				:exec,
1342				EMPromise.resolve(nil),
1343				[String, ["test-inviter", "test"]]
1344			)
1345			Transaction::DB.expect(:transaction, nil) do |&blk|
1346				blk.call
1347				true
1348			end
1349			Transaction::DB.expect(
1350				:exec,
1351				nil,
1352				[String, Matching.new { |params|
1353					assert_equal "test", params[0]
1354					assert params[1].start_with?("referral_")
1355					assert_equal 1, params[4]
1356					assert_equal "Referral Bonus", params[5]
1357				}]
1358			)
1359			Bwmsgsv2Repo::REDIS.expect(
1360				:get,
1361				EMPromise.resolve(nil),
1362				["jmp_customer_backend_sgx-test"]
1363			)
1364			Bwmsgsv2Repo::REDIS.expect(
1365				:set,
1366				nil,
1367				[
1368					"catapult_fwd-+15555550000",
1369					"xmpp:test@example.net"
1370				]
1371			)
1372			Bwmsgsv2Repo::REDIS.expect(
1373				:set,
1374				nil,
1375				["catapult_fwd_timeout-customer_test@component", 25]
1376			)
1377			Customer::BLATHER.expect(
1378				:<<,
1379				nil,
1380				[Matching.new do |m|
1381					assert_equal :chat, m.type
1382					assert m.body =~ /^Welcome to JMP/
1383				end]
1384			)
1385			blather = Minitest::Mock.new
1386			blather.expect(
1387				:<<,
1388				nil,
1389				[Matching.new do |reply|
1390					assert_equal :completed, reply.status
1391					assert_equal :info, reply.note_type
1392					assert_equal(
1393						"Your JMP account has been activated as (555) 555-0000",
1394						reply.note.content
1395					)
1396				end]
1397			)
1398			execute_command(blather: blather) do
1399				@sgx.expect(
1400					:register!,
1401					EMPromise.resolve(@sgx.with(
1402						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1403							ibr.phone = "+15555550000"
1404						end
1405					)),
1406					["+15555550000"]
1407				)
1408
1409				@finish.write
1410			end
1411			assert_requested create_order
1412			assert_mock @sgx
1413			assert_mock Registration::Finish::REDIS
1414			assert_mock Bwmsgsv2Repo::REDIS
1415			assert_mock Customer::BLATHER
1416			assert_mock blather
1417			assert_mock Transaction::DB
1418		end
1419		em :test_write_with_pending_code
1420
1421		def test_write_onboarding
1422			create_order = stub_request(
1423				:post,
1424				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1425			).to_return(status: 201, body: <<~RESPONSE)
1426				<OrderResponse>
1427					<Order>
1428						<id>test_order</id>
1429					</Order>
1430				</OrderResponse>
1431			RESPONSE
1432			stub_request(
1433				:get,
1434				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1435			).to_return(status: 201, body: <<~RESPONSE)
1436				<OrderResponse>
1437					<OrderStatus>COMPLETE</OrderStatus>
1438					<CompletedNumbers>
1439						<TelephoneNumber>
1440							<FullNumber>5555550000</FullNumber>
1441						</TelephoneNumber>
1442					</CompletedNumbers>
1443				</OrderResponse>
1444			RESPONSE
1445			stub_request(
1446				:post,
1447				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1448			)
1449			Registration::Finish::REDIS.expect(
1450				:get,
1451				nil,
1452				["jmp_customer_pending_invite-test"]
1453			)
1454			Registration::Finish::REDIS.expect(
1455				:del,
1456				nil,
1457				["jmp_customer_pending_invite-test"]
1458			)
1459			Registration::Finish::REDIS.expect(
1460				:hget,
1461				nil,
1462				["jmp_group_codes", nil]
1463			)
1464			Bwmsgsv2Repo::REDIS.expect(
1465				:get,
1466				EMPromise.resolve(nil),
1467				["jmp_customer_backend_sgx-test"]
1468			)
1469			Bwmsgsv2Repo::REDIS.expect(
1470				:set,
1471				nil,
1472				[
1473					"catapult_fwd-+15555550000",
1474					"xmpp:test\\40onboarding.example.com@proxy"
1475				]
1476			)
1477			Bwmsgsv2Repo::REDIS.expect(
1478				:set,
1479				nil,
1480				["catapult_fwd_timeout-customer_test@component", 25]
1481			)
1482			result = execute_command do
1483				@sgx.expect(
1484					:register!,
1485					EMPromise.resolve(@sgx.with(
1486						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1487							ibr.phone = "+15555550000"
1488						end
1489					)),
1490					["+15555550000"]
1491				)
1492
1493				Command::COMMAND_MANAGER.expect(
1494					:write,
1495					EMPromise.reject(:test_result),
1496					[Matching.new do |iq|
1497						assert_equal :form, iq.form.type
1498						assert iq.form.field("subdomain")
1499					end]
1500				)
1501
1502				Registration::Finish.new(
1503					customer(
1504						sgx: @sgx,
1505						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1506					),
1507					TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1508				).write.catch { |e| e }
1509			end
1510			assert_equal :test_result, result
1511			assert_requested create_order
1512			assert_mock @sgx
1513			assert_mock Registration::Finish::REDIS
1514			assert_mock Bwmsgsv2Repo::REDIS
1515			assert_mock Command::COMMAND_MANAGER
1516		end
1517		em :test_write_onboarding
1518
1519		def test_write_local_inventory
1520			stub_request(
1521				:post,
1522				"https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
1523			).with(
1524				body: {
1525					CustomerOrderId: "test",
1526					SourceAccountId: "bandwidth_account_id",
1527					SiteId: "test_site",
1528					SipPeerId: "test_peer",
1529					TelephoneNumbers: { TelephoneNumber: "5555550000" }
1530				}.to_xml(indent: 0, root: "MoveTnsOrder")
1531			).to_return(status: 200, body: "", headers: {})
1532
1533			Registration::Finish::REDIS.expect(
1534				:get,
1535				nil,
1536				["jmp_customer_pending_invite-test"]
1537			)
1538			Registration::Finish::REDIS.expect(
1539				:del,
1540				nil,
1541				["jmp_customer_pending_invite-test"]
1542			)
1543			Registration::Finish::REDIS.expect(
1544				:hget,
1545				nil,
1546				["jmp_group_codes", nil]
1547			)
1548			Registration::Finish::DB.expect(
1549				:exec_defer,
1550				EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
1551				[String, ["+15555550000"]]
1552			)
1553			Bwmsgsv2Repo::REDIS.expect(
1554				:get,
1555				EMPromise.resolve(nil),
1556				["jmp_customer_backend_sgx-test"]
1557			)
1558			Bwmsgsv2Repo::REDIS.expect(
1559				:set,
1560				nil,
1561				[
1562					"catapult_fwd-+15555550000",
1563					"xmpp:test\\40onboarding.example.com@proxy"
1564				]
1565			)
1566			Bwmsgsv2Repo::REDIS.expect(
1567				:set,
1568				nil,
1569				["catapult_fwd_timeout-customer_test@component", 25]
1570			)
1571			result = execute_command do
1572				@sgx.expect(
1573					:register!,
1574					EMPromise.resolve(@sgx.with(
1575						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1576							ibr.phone = "+15555550000"
1577						end
1578					)),
1579					["+15555550000"]
1580				)
1581
1582				Command::COMMAND_MANAGER.expect(
1583					:write,
1584					EMPromise.reject(:test_result),
1585					[Matching.new do |iq|
1586						assert_equal :form, iq.form.type
1587						assert iq.form.field("subdomain")
1588					end]
1589				)
1590
1591				Registration::Finish.new(
1592					customer(
1593						sgx: @sgx,
1594						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1595					),
1596					TelSelections::ChooseTel::Tn::LocalInventory.new(
1597						TelSelections::ChooseTel::Tn.new("+15555550000"),
1598						"bandwidth_account_id"
1599					)
1600				).write.catch { |e| e }
1601			end
1602			assert_equal :test_result, result
1603			assert_mock @sgx
1604			assert_mock Registration::Finish::REDIS
1605			assert_mock Bwmsgsv2Repo::REDIS
1606			assert_mock Command::COMMAND_MANAGER
1607		end
1608		em :test_write_local_inventory
1609
1610		def test_write_tn_fail
1611			create_order = stub_request(
1612				:post,
1613				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1614			).to_return(status: 201, body: <<~RESPONSE)
1615				<OrderResponse>
1616					<Order>
1617						<id>test_order</id>
1618					</Order>
1619				</OrderResponse>
1620			RESPONSE
1621			stub_request(
1622				:get,
1623				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1624			).to_return(status: 201, body: <<~RESPONSE)
1625				<OrderResponse>
1626					<OrderStatus>FAILED</OrderStatus>
1627				</OrderResponse>
1628			RESPONSE
1629
1630			result = execute_command do
1631				Command::COMMAND_MANAGER.expect(
1632					:write,
1633					EMPromise.reject(:test_result),
1634					[Matching.new do |iq|
1635						assert_equal :form, iq.form.type
1636						assert_equal(
1637							"The JMP number (555) 555-0000 is no longer available.",
1638							iq.form.instructions
1639						)
1640					end]
1641				)
1642
1643				@finish.write.catch { |e| e }
1644			end
1645
1646			assert_equal :test_result, result
1647			assert_mock Command::COMMAND_MANAGER
1648			assert_instance_of(
1649				TelSelections::ChooseTel,
1650				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1651			)
1652			assert_requested create_order
1653		end
1654		em :test_write_tn_fail
1655	end
1656
1657	class SnikketTest < Minitest::Test
1658		Command::COMMAND_MANAGER = Minitest::Mock.new
1659		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1660
1661		def setup
1662			@sgx = Minitest::Mock.new(mksgx)
1663			@snikket = Registration::FinishOnboarding::Snikket.new(
1664				customer(sgx: @sgx),
1665				"+15555550000",
1666				db: FakeDB.new
1667			)
1668		end
1669
1670		def test_write
1671			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1672
1673			subdomain_form = Blather::Stanza::Iq::Command.new
1674			subdomain_form.form.fields = [
1675				{ var: "subdomain", value: "test" }
1676			]
1677
1678			launched = Snikket::Launched.new
1679			launched << Niceogiri::XML::Node.new(
1680				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1681			).tap { |inner|
1682				inner << Niceogiri::XML::Node.new(
1683					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1684				).tap { |id|
1685					id.content = "si-1234"
1686				}
1687				inner << Niceogiri::XML::Node.new(
1688					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1689				).tap { |bootstrap|
1690					bootstrap << Niceogiri::XML::Node.new(
1691						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1692					).tap { |token|
1693						token.content = "TOKEN"
1694					}
1695				}
1696			}
1697
1698			blather = Minitest::Mock.new
1699			blather.expect(
1700				:<<,
1701				nil,
1702				[Matching.new do |reply|
1703					assert_equal :completed, reply.status
1704					assert_equal(
1705						xmpp_uri,
1706						OOB.find_or_create(reply.command).url
1707					)
1708				end]
1709			)
1710
1711			execute_command(blather: blather) do
1712				Command::COMMAND_MANAGER.expect(
1713					:write,
1714					EMPromise.resolve(subdomain_form),
1715					[Matching.new do |iq|
1716						assert_equal :form, iq.form.type
1717						assert iq.form.field("subdomain")
1718					end]
1719				)
1720
1721				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1722					:write,
1723					EMPromise.resolve(launched),
1724					[Matching.new do |iq|
1725						assert_equal :set, iq.type
1726						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1727						assert_equal(
1728							"test.snikket.chat",
1729							iq.xpath(
1730								"./ns:launch/ns:domain",
1731								ns: "xmpp:snikket.org/hosting/v1"
1732							).text
1733						)
1734					end]
1735				)
1736
1737				# Webmock doesn't support redirects properly, but they work live
1738				stub_request(
1739					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1740				).to_return(
1741					status: 200,
1742					headers: {
1743						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1744					}
1745				)
1746
1747				@snikket.write
1748			end
1749
1750			assert_mock Command::COMMAND_MANAGER
1751			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1752			assert_mock blather
1753		end
1754		em :test_write
1755
1756		def test_write_not_yet
1757			subdomain_form = Blather::Stanza::Iq::Command.new
1758			subdomain_form.form.fields = [
1759				{ var: "subdomain", value: "test" }
1760			]
1761
1762			launched = Snikket::Launched.new
1763			launched << Niceogiri::XML::Node.new(
1764				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1765			).tap { |inner|
1766				inner << Niceogiri::XML::Node.new(
1767					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1768				).tap { |id|
1769					id.content = "si-1234"
1770				}
1771				inner << Niceogiri::XML::Node.new(
1772					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1773				).tap { |bootstrap|
1774					bootstrap << Niceogiri::XML::Node.new(
1775						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1776					).tap { |token|
1777						token.content = "TOKEN"
1778					}
1779				}
1780			}
1781
1782			result = execute_command do
1783				Command::COMMAND_MANAGER.expect(
1784					:write,
1785					EMPromise.resolve(subdomain_form),
1786					[Matching.new do |iq|
1787						assert_equal :form, iq.form.type
1788						assert iq.form.field("subdomain")
1789					end]
1790				)
1791
1792				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1793					:write,
1794					EMPromise.resolve(launched),
1795					[Matching.new do |iq|
1796						assert_equal :set, iq.type
1797						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1798						assert_equal(
1799							"test.snikket.chat",
1800							iq.xpath(
1801								"./ns:launch/ns:domain",
1802								ns: "xmpp:snikket.org/hosting/v1"
1803							).text
1804						)
1805					end]
1806				)
1807
1808				stub_request(
1809					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1810				).to_timeout
1811
1812				Command::COMMAND_MANAGER.expect(
1813					:write,
1814					EMPromise.reject(:test_result),
1815					[Matching.new do |iq|
1816						assert_equal :result, iq.form.type
1817						assert iq.form.instructions =~ / test\.snikket\.chat /
1818						assert_equal "jid-single", iq.form.field("support").type
1819					end]
1820				)
1821
1822				@snikket.write.catch { |e| e }
1823			end
1824
1825			assert_equal :test_result, result
1826			assert_mock Command::COMMAND_MANAGER
1827			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1828		end
1829		em :test_write_not_yet
1830
1831		def test_write_already_taken
1832			subdomain_form = Blather::Stanza::Iq::Command.new
1833			subdomain_form.form.fields = [
1834				{ var: "subdomain", value: "test" }
1835			]
1836
1837			launched = Snikket::Launched.new.as_error(
1838				"internal-server-error",
1839				:wait,
1840				"This is an error"
1841			)
1842
1843			result = execute_command do
1844				Command::COMMAND_MANAGER.expect(
1845					:write,
1846					EMPromise.resolve(subdomain_form),
1847					[Matching.new do |iq|
1848						assert_equal :form, iq.form.type
1849						assert iq.form.field("subdomain")
1850					end]
1851				)
1852
1853				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1854					:write,
1855					EMPromise.reject(launched),
1856					[Matching.new do |iq|
1857						assert_equal :set, iq.type
1858						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1859						assert_equal(
1860							"test.snikket.chat",
1861							iq.xpath(
1862								"./ns:launch/ns:domain",
1863								ns: "xmpp:snikket.org/hosting/v1"
1864							).text
1865						)
1866					end]
1867				)
1868
1869				stub_request(
1870					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1871				).to_timeout
1872
1873				Command::COMMAND_MANAGER.expect(
1874					:write,
1875					EMPromise.reject(:test_result),
1876					[Matching.new do |iq|
1877						assert iq.executing?
1878						assert_equal(
1879							"This is an error",
1880							iq.form.field("subdomain").desc
1881						)
1882					end]
1883				)
1884
1885				@snikket.write.catch { |e| e }
1886			end
1887
1888			assert_equal :test_result, result
1889			assert_mock Command::COMMAND_MANAGER
1890			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1891		end
1892		em :test_write_already_taken
1893	end
1894
1895	class SnikketCustomDomainTest < Minitest::Test
1896		def setup
1897			@snikket = Registration::FinishOnboarding::CustomDomain.new(
1898				customer,
1899				"+15555550000",
1900				db: FakeDB.new
1901			)
1902		end
1903
1904		def test_write_needs_dns
1905			domain_form = Blather::Stanza::Iq::Command.new
1906			domain_form.form.fields = [
1907				{ var: "domain", value: "snikket.example.com" }
1908			]
1909
1910			launched = Snikket::Launched.new
1911			launched << Niceogiri::XML::Node.new(
1912				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1913			).tap { |inner|
1914				inner << Niceogiri::XML::Node.new(
1915					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1916				).tap { |id|
1917					id.content = "si-1234"
1918				}
1919				inner << Niceogiri::XML::Node.new(
1920					:status, launched.document, "xmpp:snikket.org/hosting/v1"
1921				).tap { |id|
1922					id.content = "needs_dns"
1923				}
1924				inner << Niceogiri::XML::Node.new(
1925					:records, launched.document, "xmpp:snikket.org/hosting/v1"
1926				).tap { |records|
1927					records << Niceogiri::XML::Node.new(
1928						:record, launched.document, "xmpp:snikket.org/hosting/v1"
1929					).tap { |record|
1930						record << Niceogiri::XML::Node.new(
1931							:name, launched.document, "xmpp:snikket.org/hosting/v1"
1932						).tap { |name| name.content = "snikket.example.com" }
1933						record << Niceogiri::XML::Node.new(
1934							:type, launched.document, "xmpp:snikket.org/hosting/v1"
1935						).tap { |type| type.content = "AAAA" }
1936						record << Niceogiri::XML::Node.new(
1937							:status, launched.document, "xmpp:snikket.org/hosting/v1"
1938						).tap { |type| type.content = "incorrect" }
1939						record << Niceogiri::XML::Node.new(
1940							:expected, launched.document, "xmpp:snikket.org/hosting/v1"
1941						).tap { |expected|
1942							expected << Niceogiri::XML::Node.new(
1943								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1944							).tap { |value| value.content = "1::2" }
1945						}
1946						record << Niceogiri::XML::Node.new(
1947							:found, launched.document, "xmpp:snikket.org/hosting/v1"
1948						).tap { |found|
1949							found << Niceogiri::XML::Node.new(
1950								:value, launched.document, "xmpp:snikket.org/hosting/v1"
1951							).tap { |value| value.content = "0::0" }
1952						}
1953					}
1954				}
1955			}
1956
1957			result = execute_command do
1958				Command::COMMAND_MANAGER.expect(
1959					:write,
1960					EMPromise.resolve(domain_form),
1961					[Matching.new do |iq|
1962						assert_equal :form, iq.form.type
1963						assert iq.form.field("domain")
1964					end]
1965				)
1966
1967				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1968					:write,
1969					EMPromise.resolve(launched),
1970					[Matching.new do |iq|
1971						assert_equal :set, iq.type
1972						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1973						assert_equal(
1974							"snikket.example.com",
1975							iq.xpath(
1976								"./ns:launch/ns:domain",
1977								ns: "xmpp:snikket.org/hosting/v1"
1978							).text
1979						)
1980					end]
1981				)
1982
1983				Command::COMMAND_MANAGER.expect(
1984					:write,
1985					EMPromise.reject(:test_result),
1986					[Matching.new do |iq|
1987						assert_equal :form, iq.form.type
1988						assert_equal(
1989							["snikket.example.com"],
1990							iq.form.xpath(
1991								"./ns:item/ns:field[@var='name']/ns:value",
1992								ns: "jabber:x:data"
1993							).map(&:content)
1994						)
1995						assert_equal(
1996							["1::2"],
1997							iq.form.xpath(
1998								"./ns:item/ns:field[@var='expected']/ns:value",
1999								ns: "jabber:x:data"
2000							).map(&:content)
2001						)
2002					end]
2003				)
2004
2005				@snikket.write.catch { |e| e }
2006			end
2007
2008			assert_equal :test_result, result
2009			assert_mock Command::COMMAND_MANAGER
2010			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
2011		end
2012		em :test_write_needs_dns
2013	end
2014end