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