test_registration.rb

   1# frozen_string_literal: true
   2
   3require "test_helper"
   4require "customer"
   5require "registration"
   6require "bwmsgsv2_repo"
   7require "transaction"
   8require "sim_order"
   9
  10BandwidthTnReservationRepo::REDIS = FakeRedis.new
  11
  12class RegistrationTest < Minitest::Test
  13	def test_for_registered
  14		sgx = OpenStruct.new(
  15			registered?: OpenStruct.new(phone: "+15555550000")
  16		)
  17		iq = Blather::Stanza::Iq::Command.new
  18		iq.from = "test@example.com"
  19		result = execute_command(iq) do
  20			Registration.for(
  21				customer(sgx: sgx),
  22				nil,
  23				Minitest::Mock.new
  24			)
  25		end
  26		assert_kind_of Registration::Registered, result
  27	end
  28	em :test_for_registered
  29
  30	def test_for_activated
  31		reservation_req = stub_request(
  32			:post,
  33			"https://dashboard.bandwidth.com/v1.0/accounts//tnreservation"
  34		).to_return(
  35			status: 201,
  36			headers: {
  37				location: "https://dashboard.bandwidth.com/api/accounts//TnReservation/8da0f39c-043c-4806-9f0f-497b2d197bc5"
  38			}
  39		)
  40		stub_request(
  41			:get, "https://dashboard.bandwidth.com/v1.0/accounts//tnreservation/8da0f39c-043c-4806-9f0f-497b2d197bc5"
  42		).to_return(status: 200, body: <<~RESPONSE)
  43			<ReservationResponse>
  44				<Reservation>
  45					<ReservationId>f342904f-b03a-4499-bac0-e8f43a2664a1</ReservationId>
  46					<AccountId>12346099</AccountId>
  47					<ReservationExpires>1492</ReservationExpires>
  48					<ReservedTn>4354776010</ReservedTn>
  49				</Reservation>
  50			</ReservationResponse>
  51		RESPONSE
  52		web_manager = TelSelections.new(
  53			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  54		)
  55		web_manager.set(
  56			"test@example.net",
  57			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
  58		)
  59		result = execute_command do
  60			sgx = OpenStruct.new(registered?: false)
  61			Registration.for(
  62				customer(
  63					plan_name: "test_usd",
  64					expires_at: Time.now + 999,
  65					sgx: sgx
  66				),
  67				nil,
  68				web_manager
  69			)
  70		end
  71		assert_kind_of Registration::Finish, result
  72		assert_requested reservation_req
  73	end
  74	em :test_for_activated
  75
  76	def test_for_not_activated_approved
  77		sgx = OpenStruct.new(registered?: false)
  78		web_manager = TelSelections.new(
  79			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  80		)
  81		web_manager.set(
  82			"test\\40approved.example.com@component",
  83			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
  84		)
  85		iq = Blather::Stanza::Iq::Command.new
  86		iq.from = "test@approved.example.com"
  87		result = execute_command(iq) do
  88			Registration::Activation.for(
  89				customer(
  90					sgx: sgx,
  91					jid: Blather::JID.new("test\\40approved.example.com@component")
  92				),
  93				nil,
  94				web_manager
  95			)
  96		end
  97		assert_kind_of Registration::Activation::Allow, result
  98	end
  99	em :test_for_not_activated_approved
 100
 101	def test_for_not_activated_googleplay
 102		skip
 103		sgx = OpenStruct.new(registered?: false)
 104		web_manager = TelSelections.new(
 105			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
 106		)
 107		web_manager.set(
 108			"test@example.net",
 109			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 110		)
 111		iq = Blather::Stanza::Iq::Command.new
 112		iq.from = "test@approved.example.com"
 113		result = execute_command(iq) do
 114			Registration::Activation.for(
 115				customer(sgx: sgx),
 116				"GARBLEDYGOOK==",
 117				web_manager
 118			)
 119		end
 120		assert_kind_of Registration::Activation::GooglePlay, result
 121	end
 122	em :test_for_not_activated_googleplay
 123
 124	def test_for_not_activated_with_customer_id
 125		sgx = OpenStruct.new(registered?: false)
 126		web_manager = TelSelections.new(
 127			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
 128		)
 129		web_manager.set(
 130			"test@example.net",
 131			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 132		)
 133		iq = Blather::Stanza::Iq::Command.new
 134		iq.from = "test@example.com"
 135		result = execute_command(iq) do
 136			Registration::Activation.for(
 137				customer(sgx: sgx),
 138				nil,
 139				web_manager
 140			)
 141		end
 142		assert_kind_of Registration::Activation, result
 143	end
 144	em :test_for_not_activated_with_customer_id
 145
 146	class ActivationTest < Minitest::Test
 147		Registration::Activation::DB = Minitest::Mock.new
 148		Registration::Activation::REDIS = FakeRedis.new(
 149			"jmp_parent_codes" => {
 150				"PARENT_CODE" => "1",
 151				"PARENT_TOMB" => "2",
 152				"PARENT_MANY_SUBACCOUNTS" => "many_subaccounts"
 153			},
 154			"jmp_customer_trust_level-2" => "Tomb"
 155		)
 156		Registration::Activation::Payment = Minitest::Mock.new
 157		Registration::Activation::Finish = Minitest::Mock.new
 158		Command::COMMAND_MANAGER = Minitest::Mock.new
 159
 160		def setup
 161			@customer = Minitest::Mock.new(customer)
 162			@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 163			@activation = Registration::Activation.new(@customer, @tel)
 164		end
 165
 166		def test_write
 167			Command::COMMAND_MANAGER.expect(
 168				:write,
 169				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 170					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 171				}),
 172				[Matching.new do |iq|
 173					assert_equal :form, iq.form.type
 174					assert_equal(
 175						"You've selected (555) 555-0000 as your JMP number.",
 176						iq.form.instructions.lines.first.chomp
 177					)
 178				end]
 179			)
 180			@customer.expect(:with_plan, @customer) do |*args, **|
 181				assert_equal ["test_usd"], args
 182			end
 183			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 184			Registration::Activation::Payment.expect(
 185				:for,
 186				EMPromise.reject(:test_result),
 187				[Blather::Stanza::Iq, @customer, @tel]
 188			)
 189			assert_equal(
 190				:test_result,
 191				execute_command { @activation.write.catch { |e| e } }
 192			)
 193			assert_mock Command::COMMAND_MANAGER
 194			assert_mock @customer
 195			assert_mock Registration::Activation::Payment
 196		end
 197		em :test_write
 198
 199		def test_write_with_onboarding_jid
 200			Command::COMMAND_MANAGER.expect(
 201				:write,
 202				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 203					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 204				}),
 205				[Matching.new do |iq|
 206					assert_equal :form, iq.form.type
 207					assert_equal(
 208						"You've selected (555) 555-0000 as your JMP number.",
 209						iq.form.instructions.lines.first.chomp
 210					)
 211				end]
 212			)
 213			@customer.expect(
 214				:jid,
 215				Blather::JID.new("test\\40onboarding.example.com@proxy")
 216			)
 217			@customer.expect(:with_plan, @customer) do |*args, **|
 218				assert_equal ["test_usd"], args
 219			end
 220			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 221			Registration::Activation::Payment.expect(
 222				:for,
 223				EMPromise.reject(:test_result),
 224				[Blather::Stanza::Iq, @customer, @tel]
 225			)
 226			assert_equal(
 227				:test_result,
 228				execute_command { @activation.write.catch { |e| e } }
 229			)
 230			assert_mock Command::COMMAND_MANAGER
 231			assert_mock @customer
 232			assert_mock Registration::Activation::Payment
 233		end
 234		em :test_write_with_onboarding_jid
 235
 236		def test_write_bad_plan
 237			Command::COMMAND_MANAGER.expect(
 238				:write,
 239				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 240					iq.form.fields = [{ var: "plan_name", value: "test_usd_no_register" }]
 241				}),
 242				[Matching.new do |iq|
 243					assert_equal :form, iq.form.type
 244					assert_equal(
 245						"You've selected (555) 555-0000 as your JMP number.",
 246						iq.form.instructions.lines.first.chomp
 247					)
 248				end]
 249			)
 250			assert_equal(
 251				"No registration plan by that name",
 252				execute_command { @activation.write.catch { |e| e } }.message
 253			)
 254			assert_mock Command::COMMAND_MANAGER
 255			assert_mock @customer
 256		end
 257		em :test_write_bad_plan
 258
 259		def test_write_with_code
 260			Command::COMMAND_MANAGER.expect(
 261				:write,
 262				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 263					iq.form.fields = [
 264						{ var: "plan_name", value: "test_usd" },
 265						{ var: "code", value: "123" }
 266					]
 267				}),
 268				[Matching.new do |iq|
 269					assert_equal :form, iq.form.type
 270					assert_equal(
 271						"You've selected (555) 555-0000 as your JMP number.",
 272						iq.form.instructions.lines.first.chomp
 273					)
 274				end]
 275			)
 276			@customer.expect(:with_plan, @customer) do |*args, **|
 277				assert_equal ["test_usd"], args
 278			end
 279			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 280			@customer.expect(:activate_plan_starting_now, EMPromise.resolve(nil), [])
 281			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 282			Registration::Activation::DB.expect(
 283				:exec,
 284				OpenStruct.new(cmd_tuples: 1),
 285				[String, ["test", "123"]]
 286			)
 287			Registration::Activation::Finish.expect(
 288				:new,
 289				OpenStruct.new(write: EMPromise.reject(:test_result)),
 290				[@customer, @tel]
 291			)
 292			assert_equal(
 293				:test_result,
 294				execute_command { @activation.write.catch { |e| e } }
 295			)
 296			assert_mock Command::COMMAND_MANAGER
 297			assert_mock @customer
 298			assert_mock Registration::Activation::Payment
 299			assert_mock Registration::Activation::DB
 300		end
 301		em :test_write_with_code
 302
 303		def test_write_with_group_code
 304			Command::COMMAND_MANAGER.expect(
 305				:write,
 306				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 307					iq.form.fields = [
 308						{ var: "plan_name", value: "test_usd" },
 309						{ var: "code", value: "123" }
 310					]
 311				}),
 312				[Matching.new do |iq|
 313					assert_equal :form, iq.form.type
 314					assert_equal(
 315						"You've selected (555) 555-0000 as your JMP number.",
 316						iq.form.instructions.lines.first.chomp
 317					)
 318				end]
 319			)
 320			@customer.expect(:with_plan, @customer) do |*args, **|
 321				assert_equal ["test_usd"], args
 322			end
 323			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 324			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 325			Registration::Activation::DB.expect(
 326				:exec,
 327				OpenStruct.new(cmd_tuples: 0),
 328				[String, ["test", "123"]]
 329			)
 330			Registration::Activation::Payment.expect(
 331				:for,
 332				EMPromise.reject(:test_result),
 333				[Blather::Stanza::Iq, @customer, @tel]
 334			)
 335			assert_equal(
 336				:test_result,
 337				execute_command { @activation.write.catch { |e| e } }
 338			)
 339			assert_equal(
 340				"123",
 341				Registration::Activation::REDIS.get(
 342					"jmp_customer_pending_invite-test"
 343				).sync
 344			)
 345			assert_mock Command::COMMAND_MANAGER
 346			assert_mock @customer
 347			assert_mock Registration::Activation::Payment
 348			assert_mock Registration::Activation::DB
 349		end
 350		em :test_write_with_group_code
 351
 352		def test_write_with_parent_code
 353			execute_command do
 354				Command::COMMAND_MANAGER.expect(
 355					:write,
 356					EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 357						iq.form.fields = [
 358							{ var: "plan_name", value: "test_usd" },
 359							{ var: "code", value: "PARENT_CODE" }
 360						]
 361					}),
 362					[Matching.new do |iq|
 363						assert_equal :form, iq.form.type
 364						assert_equal(
 365							"You've selected (555) 555-0000 as your JMP number.",
 366							iq.form.instructions.lines.first.chomp
 367						)
 368					end]
 369				)
 370				Registration::Activation::DB.expect(
 371					:query_one, {}, [String, "1"], default: {}
 372				)
 373				Registration::Activation::DB.expect(
 374					:query_one, { c: 0 }, [String, "1"], default: { c: 0 }
 375				)
 376				@customer.expect(:with_plan, @customer) do |*args, **|
 377					assert_equal ["test_usd"], args
 378				end
 379				@customer.expect(:with_plan, @customer) do |*, **kwargs|
 380					assert_equal({ parent_customer_id: "1" }, kwargs)
 381				end
 382				@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 383				@customer.expect(:balance, 100, [])
 384				Command.execution.customer_repo.expect(
 385					:find,
 386					EMPromise.resolve(@customer), ["test"]
 387				)
 388				Registration::Payment::MaybeBill::BillPlan.expect(
 389					:new,
 390					EMPromise.reject(:test_result)
 391				) do |*args, **|
 392					assert_equal @tel, args[1]
 393				end
 394				assert_equal(
 395					:test_result,
 396					@activation.write.catch { |e| e }.sync
 397				)
 398			end
 399			assert_mock Command::COMMAND_MANAGER
 400			assert_mock @customer
 401			assert_mock Registration::Activation::Payment
 402			assert_mock Registration::Activation::DB
 403			assert_mock Registration::Payment::MaybeBill::BillPlan
 404		end
 405		em :test_write_with_parent_code
 406
 407		def test_write_with_parent_code_onboarding_jid
 408			Command::COMMAND_MANAGER.expect(
 409				:write,
 410				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 411					iq.form.fields = [
 412						{ var: "plan_name", value: "test_usd" },
 413						{ var: "code", value: "PARENT_CODE" }
 414					]
 415				}),
 416				[Matching.new do |iq|
 417					assert_equal :form, iq.form.type
 418					assert_equal(
 419						"You've selected (555) 555-0000 as your JMP number.",
 420						iq.form.instructions.lines.first.chomp
 421					)
 422				end]
 423			)
 424			Registration::Activation::DB.expect(
 425				:query_one, {}, [String, "1"], default: {}
 426			)
 427			Registration::Activation::DB.expect(
 428				:query_one, { c: 0 }, [String, "1"], default: { c: 0 }
 429			)
 430			@customer.expect(:with_plan, @customer, ["test_usd"])
 431			@customer.expect(
 432				:jid,
 433				Blather::JID.new("test\\40onboarding.example.com@proxy")
 434			)
 435			iq = Blather::Stanza::Iq::Command.new
 436			iq.from = "test\\40onboarding.example.com@proxied"
 437			assert_equal(
 438				"Please create a new Jabber ID before creating a subaccount.",
 439				execute_command(iq) { @activation.write.catch(&:to_s) }
 440			)
 441			assert_mock Command::COMMAND_MANAGER
 442			assert_mock @customer
 443			assert_mock Registration::Activation::Payment
 444			assert_mock Registration::Activation::DB
 445		end
 446		em :test_write_with_parent_code_onboarding_jid
 447
 448		def test_write_with_parent_code_tombed_parent
 449			Command::COMMAND_MANAGER.expect(
 450				:write,
 451				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 452					iq.form.fields = [
 453						{ var: "plan_name", value: "test_usd" },
 454						{ var: "code", value: "PARENT_TOMB" }
 455					]
 456				}),
 457				[Matching.new do |iq|
 458					assert_equal :form, iq.form.type
 459					assert_equal(
 460						"You've selected (555) 555-0000 as your JMP number.",
 461						iq.form.instructions.lines.first.chomp
 462					)
 463				end]
 464			)
 465			Registration::Activation::DB.expect(
 466				:query_one, {}, [String, "2"], default: {}
 467			)
 468			Registration::Activation::DB.expect(
 469				:query_one, { c: 0 }, [String, "2"], default: { c: 0 }
 470			)
 471			assert_equal(
 472				"Please contact support to create a subaccount",
 473				execute_command { @activation.write.catch(&:to_s) }
 474			)
 475			assert_mock Command::COMMAND_MANAGER
 476			assert_mock @customer
 477			assert_mock Registration::Activation::Payment
 478			assert_mock Registration::Activation::DB
 479		end
 480		em :test_write_with_parent_code_tombed_parent
 481
 482		def test_write_with_parent_code_too_many
 483			Command::COMMAND_MANAGER.expect(
 484				:write,
 485				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 486					iq.form.fields = [
 487						{ var: "plan_name", value: "test_usd" },
 488						{ var: "code", value: "PARENT_MANY_SUBACCOUNTS" }
 489					]
 490				}),
 491				[Matching.new do |iq|
 492					assert_equal :form, iq.form.type
 493					assert_equal(
 494						"You've selected (555) 555-0000 as your JMP number.",
 495						iq.form.instructions.lines.first.chomp
 496					)
 497				end]
 498			)
 499			Registration::Activation::DB.expect(
 500				:query_one, {}, [String, "many_subaccounts"], default: {}
 501			)
 502			Registration::Activation::DB.expect(
 503				:query_one, { c: 2 }, [String, "many_subaccounts"], default: { c: 0 }
 504			)
 505			assert_equal(
 506				"Please contact support to create a subaccount",
 507				execute_command { @activation.write.catch(&:to_s) }
 508			)
 509			assert_mock Command::COMMAND_MANAGER
 510			assert_mock @customer
 511			assert_mock Registration::Activation::Payment
 512			assert_mock Registration::Activation::DB
 513		end
 514		em :test_write_with_parent_code_too_many
 515	end
 516
 517	class AllowTest < Minitest::Test
 518		Command::COMMAND_MANAGER = Minitest::Mock.new
 519		Registration::Activation::Allow::DB = Minitest::Mock.new
 520
 521		def test_write_credit_to_nil
 522			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 523			cust = Minitest::Mock.new(customer("test"))
 524			allow = Registration::Activation::Allow.new(cust, tel, nil)
 525
 526			Command::COMMAND_MANAGER.expect(
 527				:write,
 528				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 529					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 530				}),
 531				[Matching.new do |iq|
 532					assert_equal :form, iq.form.type
 533					assert_equal(
 534						"You've selected (555) 555-0000 as your JMP number.",
 535						iq.form.instructions.lines.first.chomp
 536					)
 537					assert_equal 1, iq.form.fields.length
 538				end]
 539			)
 540			Registration::Activation::Allow::DB.expect(
 541				:transaction,
 542				EMPromise.reject(:test_result)
 543			) do |&blk|
 544				blk.call
 545				true
 546			end
 547			cust.expect(:with_plan, cust, ["test_usd"])
 548			cust.expect(:activate_plan_starting_now, nil)
 549			assert_equal(
 550				:test_result,
 551				execute_command { allow.write.catch { |e| e } }
 552			)
 553			assert_mock Command::COMMAND_MANAGER
 554		end
 555		em :test_write_credit_to_nil
 556
 557		def test_write_credit_to_refercust
 558			cust = Minitest::Mock.new(customer("test"))
 559			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 560			allow = Registration::Activation::Allow.new(
 561				cust, tel, "refercust"
 562			)
 563
 564			Command::COMMAND_MANAGER.expect(
 565				:write,
 566				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 567					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 568				}),
 569				[Matching.new do |iq|
 570					assert_equal :form, iq.form.type
 571					assert_equal(
 572						"You've selected (555) 555-0000 as your JMP number.",
 573						iq.form.instructions.lines.first.chomp
 574					)
 575					assert_equal 1, iq.form.fields.length
 576				end]
 577			)
 578			Registration::Activation::Allow::DB.expect(
 579				:transaction,
 580				EMPromise.reject(:test_result)
 581			) do |&blk|
 582				blk.call
 583				true
 584			end
 585			Registration::Activation::Allow::DB.expect(
 586				:exec,
 587				nil,
 588				[String, ["refercust", "test"]]
 589			)
 590			cust.expect(:with_plan, cust, ["test_usd"])
 591			cust.expect(:activate_plan_starting_now, nil)
 592			assert_equal(
 593				:test_result,
 594				execute_command { allow.write.catch { |e| e } }
 595			)
 596			assert_mock Command::COMMAND_MANAGER
 597		end
 598		em :test_write_credit_to_refercust
 599	end
 600
 601	class GooglePlayTest < Minitest::Test
 602		CustomerPlan::DB = Minitest::Mock.new
 603		Registration::Activation::GooglePlay::Finish = Minitest::Mock.new
 604
 605		def setup
 606			@customer = customer
 607			@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 608			@google_play = Registration::Activation::GooglePlay.new(
 609				@customer,
 610				"abcd",
 611				@tel
 612			)
 613		end
 614
 615		def test_write
 616			Command::COMMAND_MANAGER.expect(
 617				:write,
 618				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 619					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 620				}),
 621				[Matching.new do |iq|
 622					assert_equal :form, iq.form.type
 623					assert_equal(
 624						"You've selected (555) 555-0000 as your JMP number.",
 625						iq.form.instructions.lines.first.chomp
 626					)
 627				end]
 628			)
 629			CustomerPlan::DB.expect(
 630				:exec,
 631				OpenStruct.new(cmd_tuples: 1),
 632				[String, ["test", "test_usd", nil]]
 633			)
 634			CustomerPlan::DB.expect(
 635				:exec,
 636				OpenStruct.new(cmd_tuples: 0),
 637				[String, ["test"]]
 638			)
 639			Transaction::DB.expect(:transaction, true, [])
 640			Registration::Activation::GooglePlay::Finish.expect(
 641				:new,
 642				OpenStruct.new(write: EMPromise.reject(:test_result)),
 643				[Customer, @tel]
 644			)
 645			result = execute_command { @google_play.write.catch { |e| e } }
 646			assert_equal :test_result, result
 647			assert_mock Command::COMMAND_MANAGER
 648			assert_mock CustomerPlan::DB
 649			assert_mock Transaction::DB
 650			assert_mock Registration::Activation::GooglePlay::Finish
 651		end
 652		em :test_write
 653	end
 654
 655	class PaymentTest < Minitest::Test
 656		CustomerFinancials::BRAINTREE = Minitest::Mock.new
 657
 658		def test_for_bitcoin
 659			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 660			iq = Blather::Stanza::Iq::Command.new
 661			iq.form.fields = [
 662				{ var: "activation_method", value: "bitcoin" },
 663				{ var: "plan_name", value: "test_usd" }
 664			]
 665			result = Registration::Payment.for(iq, customer, tel)
 666			assert_kind_of Registration::Payment::Bitcoin, result
 667		end
 668
 669		def test_for_bch
 670			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 671			iq = Blather::Stanza::Iq::Command.new
 672			iq.form.fields = [
 673				{ var: "activation_method", value: "bch" },
 674				{ var: "plan_name", value: "test_usd" }
 675			]
 676			result = Registration::Payment.for(iq, customer, tel)
 677			assert_kind_of Registration::Payment::BCH, result
 678		end
 679
 680		def test_for_credit_card
 681			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 682			iq = Blather::Stanza::Iq::Command.new
 683			iq.from = "test@example.com"
 684			iq.form.fields = [
 685				{ var: "activation_method", value: "credit_card" },
 686				{ var: "plan_name", value: "test_usd" }
 687			]
 688			cust = customer
 689			result = execute_command do
 690				Command.execution.customer_repo.expect(:find, cust, ["test"])
 691				Registration::Payment.for(
 692					iq,
 693					cust,
 694					tel
 695				)
 696			end
 697			assert_kind_of Registration::Payment::CreditCard, result
 698		end
 699		em :test_for_credit_card
 700
 701		def test_for_code
 702			iq = Blather::Stanza::Iq::Command.new
 703			iq.form.fields = [
 704				{ var: "activation_method", value: "code" },
 705				{ var: "plan_name", value: "test_usd" }
 706			]
 707			cust = customer
 708			result = execute_command do
 709				Command.execution.customer_repo.expect(:find, cust, ["test"])
 710				Registration::Payment.for(
 711					iq,
 712					cust,
 713					TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 714				)
 715			end
 716			assert_kind_of Registration::Payment::InviteCode, result
 717		end
 718		em :test_for_code
 719
 720		class BitcoinTest < Minitest::Test
 721			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
 722			CustomerFinancials::REDIS = Minitest::Mock.new
 723
 724			def setup
 725				@customer = Minitest::Mock.new(
 726					customer(plan_name: "test_usd")
 727				)
 728				@customer.expect(
 729					:add_btc_address,
 730					EMPromise.resolve("testaddr")
 731				)
 732				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 733				@bitcoin = Registration::Payment::Bitcoin.new(
 734					@customer,
 735					@tel
 736				)
 737			end
 738
 739			def test_write
 740				CustomerFinancials::REDIS.expect(
 741					:smembers,
 742					EMPromise.resolve([]),
 743					["jmp_customer_btc_addresses-test"]
 744				)
 745				blather = Minitest::Mock.new
 746				Command::COMMAND_MANAGER.expect(
 747					:write,
 748					EMPromise.reject(SessionManager::Timeout.new),
 749					[Matching.new do |reply|
 750						assert_equal :canceled, reply.status
 751						assert_equal "1.000000", reply.form.field("amount").value
 752						assert_equal "testaddr", reply.form.field("btc_addresses").value
 753						true
 754					end]
 755				)
 756				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
 757					:usd,
 758					EMPromise.resolve(BigDecimal(1))
 759				)
 760				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
 761					execute_command(blather: blather) do
 762						@bitcoin.write
 763					end
 764				end
 765				assert_mock blather
 766			end
 767			em :test_write
 768		end
 769
 770		class BCHTest < Minitest::Test
 771			Registration::Payment::BCH::BCH_SELL_PRICES = Minitest::Mock.new
 772			CustomerFinancials::REDIS = Minitest::Mock.new
 773
 774			def setup
 775				@customer = Minitest::Mock.new(
 776					customer(plan_name: "test_usd")
 777				)
 778				@customer.expect(
 779					:add_bch_address,
 780					EMPromise.resolve("testaddr")
 781				)
 782				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 783				@bch = Registration::Payment::BCH.new(
 784					@customer,
 785					@tel
 786				)
 787			end
 788
 789			def test_write
 790				CustomerFinancials::REDIS.expect(
 791					:smembers,
 792					EMPromise.resolve([]),
 793					["jmp_customer_bch_addresses-test"]
 794				)
 795				blather = Minitest::Mock.new
 796				Command::COMMAND_MANAGER.expect(
 797					:write,
 798					EMPromise.reject(SessionManager::Timeout.new),
 799					[Matching.new do |reply|
 800						assert_equal :canceled, reply.status
 801						assert_equal "1.000000", reply.form.field("amount").value
 802						assert_equal "testaddr", reply.form.field("bch_addresses").value
 803						true
 804					end]
 805				)
 806				Registration::Payment::BCH::BCH_SELL_PRICES.expect(
 807					:usd,
 808					EMPromise.resolve(BigDecimal(1))
 809				)
 810				@bch.stub(:save, EMPromise.resolve(nil)) do
 811					execute_command(blather: blather) do
 812						@bch.write
 813					end
 814				end
 815				assert_mock blather
 816			end
 817			em :test_write
 818		end
 819
 820		class CreditCardTest < Minitest::Test
 821			def setup
 822				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 823				@credit_card = Registration::Payment::CreditCard.new(
 824					customer,
 825					@tel
 826				)
 827			end
 828
 829			def test_new
 830				tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 831				cust = Minitest::Mock.new(customer)
 832				cust.expect(
 833					:payment_methods,
 834					EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
 835				)
 836				execute_command do
 837					Command.execution.customer_repo.expect(:find, cust, ["test"])
 838					assert_kind_of(
 839						Registration::Payment::CreditCard,
 840						Registration::Payment::CreditCard.new(cust, tel)
 841					)
 842				end
 843			end
 844			em :test_new
 845
 846			def test_write
 847				result = execute_command do
 848					Command::COMMAND_MANAGER.expect(
 849						:write,
 850						EMPromise.reject(:test_result),
 851						[Matching.new do |reply|
 852							assert_equal [:execute, :next, :prev], reply.allowed_actions
 853							assert_equal(
 854								"Pay by credit card, save, then next here to continue: " \
 855								"http://creditcard.example.com?&amount=1",
 856								reply.note.content
 857							)
 858						end]
 859					)
 860
 861					@credit_card.write.catch { |e| e }
 862				end
 863
 864				assert_equal :test_result, result
 865			end
 866			em :test_write
 867		end
 868
 869		class MailTest < Minitest::Test
 870			def setup
 871				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 872				@mail = Registration::Payment::Mail.new(
 873					customer(plan_name: "test_cad"),
 874					@tel
 875				)
 876			end
 877
 878			def test_write
 879				result = execute_command do
 880					Command::COMMAND_MANAGER.expect(
 881						:write,
 882						EMPromise.reject(:test_result),
 883						[Matching.new do |reply|
 884							assert_equal [:execute, :prev], reply.allowed_actions
 885							refute reply.form.instructions.empty?
 886							assert_equal(
 887								"A Mailing Address",
 888								reply.form.field("adr").value
 889							)
 890							assert_equal(
 891								"interac@example.com",
 892								reply.form.field("interac_email").value
 893							)
 894						end]
 895					)
 896
 897					@mail.write.catch { |e| e }
 898				end
 899
 900				assert_equal :test_result, result
 901			end
 902			em :test_write
 903		end
 904
 905		class InviteCodeTest < Minitest::Test
 906			Registration::Payment::InviteCode::DB =
 907				Minitest::Mock.new
 908			Registration::Payment::InviteCode::REDIS =
 909				Minitest::Mock.new
 910			Command::COMMAND_MANAGER = Minitest::Mock.new
 911			Registration::Payment::InviteCode::Finish =
 912				Minitest::Mock.new
 913			Registration::Payment::MaybeBill::BillPlan =
 914				Minitest::Mock.new
 915
 916			def setup
 917				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 918			end
 919
 920			def test_write
 921				customer = customer(plan_name: "test_usd")
 922				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 923				Registration::Payment::InviteCode::Finish.expect(
 924					:new,
 925					OpenStruct.new(write: nil),
 926					[
 927						customer,
 928						@tel
 929					]
 930				)
 931				execute_command do
 932					Registration::Payment::InviteCode::REDIS.expect(
 933						:get,
 934						EMPromise.resolve(nil),
 935						["jmp_invite_tries-test"]
 936					)
 937					Registration::Payment::InviteCode::REDIS.expect(
 938						:hget,
 939						EMPromise.resolve(nil),
 940						["jmp_parent_codes", "abc"]
 941					)
 942					Command::COMMAND_MANAGER.expect(
 943						:write,
 944						EMPromise.resolve(
 945							Blather::Stanza::Iq::Command.new.tap { |iq|
 946								iq.form.fields = [{ var: "code", value: "abc" }]
 947							}
 948						),
 949						[Matching.new do |reply|
 950							assert_equal :form, reply.form.type
 951							assert_nil reply.form.instructions
 952						end]
 953					)
 954
 955					Registration::Payment::InviteCode.new(
 956						customer,
 957						@tel
 958					).write
 959				end
 960				assert_mock Command::COMMAND_MANAGER
 961				assert_mock Registration::Payment::InviteCode::DB
 962				assert_mock Registration::Payment::InviteCode::REDIS
 963				assert_mock Registration::Payment::InviteCode::Finish
 964			end
 965			em :test_write
 966
 967			def test_write_parent_code
 968				customer = customer(plan_name: "test_usd")
 969				Registration::Payment::MaybeBill::BillPlan.expect(
 970					:new,
 971					OpenStruct.new(write: nil)
 972				) { |*| true }
 973				Registration::Payment::InviteCode::DB.expect(
 974					:query_one, {}, [String, "parent_customer"], default: {}
 975				)
 976				Registration::Payment::InviteCode::DB.expect(
 977					:query_one, { c: 0 }, [String, "parent_customer"], default: { c: 0 }
 978				)
 979				execute_command do
 980					Registration::Payment::InviteCode::REDIS.expect(
 981						:hget,
 982						EMPromise.resolve("parent_customer"),
 983						["jmp_parent_codes", "pabc"]
 984					)
 985					Registration::Payment::InviteCode::REDIS.expect(
 986						:get,
 987						EMPromise.resolve(nil),
 988						["jmp_customer_trust_level-parent_customer"]
 989					)
 990					CustomerPlan::DB.expect(
 991						:query,
 992						[{ "plan_name" => "test_usd" }],
 993						[String, ["parent_customer"]]
 994					)
 995					CustomerPlan::DB.expect(
 996						:exec_defer,
 997						EMPromise.resolve(nil),
 998						[String, ["test", "test_usd", "parent_customer"]]
 999					)
1000					Command.execution.customer_repo.expect(
1001						:find,
1002						customer.with_balance(10000),
1003						["test"]
1004					)
1005					Command::COMMAND_MANAGER.expect(
1006						:write,
1007						EMPromise.resolve(
1008							Blather::Stanza::Iq::Command.new.tap { |iq|
1009								iq.form.fields = [{ var: "code", value: "pabc" }]
1010							}
1011						),
1012						[Matching.new do |reply|
1013							assert_equal :form, reply.form.type
1014							assert_nil reply.form.instructions
1015						end]
1016					)
1017
1018					Registration::Payment::InviteCode.new(
1019						customer,
1020						@tel
1021					).write
1022				end
1023				assert_mock Command::COMMAND_MANAGER
1024				assert_mock Registration::Payment::InviteCode::DB
1025				assert_mock Registration::Payment::InviteCode::REDIS
1026				assert_mock Registration::Payment::MaybeBill::BillPlan
1027			end
1028			em :test_write_parent_code
1029
1030			def test_write_bad_code
1031				result = execute_command do
1032					customer = customer(plan_name: "test_usd")
1033					Registration::Payment::InviteCode::REDIS.expect(
1034						:set,
1035						EMPromise.resolve(nil),
1036						["jmp_customer_pending_invite-test", "abc"]
1037					)
1038					Registration::Payment::InviteCode::REDIS.expect(
1039						:get,
1040						EMPromise.resolve(0),
1041						["jmp_invite_tries-test"]
1042					)
1043					Registration::Payment::InviteCode::REDIS.expect(
1044						:hget,
1045						EMPromise.resolve(nil),
1046						["jmp_parent_codes", "abc"]
1047					)
1048					Registration::Payment::InviteCode::DB.expect(
1049						:transaction,
1050						[]
1051					) { |&blk| blk.call }
1052					Registration::Payment::InviteCode::DB.expect(
1053						:exec,
1054						OpenStruct.new(cmd_tuples: 0),
1055						[String, ["test", "abc"]]
1056					)
1057					Registration::Payment::InviteCode::REDIS.expect(
1058						:incr,
1059						EMPromise.resolve(nil),
1060						["jmp_invite_tries-test"]
1061					)
1062					Registration::Payment::InviteCode::REDIS.expect(
1063						:expire,
1064						EMPromise.resolve(nil),
1065						["jmp_invite_tries-test", 60 * 60]
1066					)
1067					Registration::Payment::InviteCode::REDIS.expect(
1068						:hexists,
1069						EMPromise.resolve(0),
1070						["jmp_group_codes", "abc"]
1071					)
1072					Command::COMMAND_MANAGER.expect(
1073						:write,
1074						EMPromise.resolve(
1075							Blather::Stanza::Iq::Command.new.tap { |iq|
1076								iq.form.fields = [{ var: "code", value: "abc" }]
1077							}
1078						),
1079						[Matching.new do |reply|
1080							assert_equal :form, reply.form.type
1081							assert_nil reply.form.instructions
1082						end]
1083					)
1084					Command::COMMAND_MANAGER.expect(
1085						:write,
1086						EMPromise.reject(:test_result),
1087						[Matching.new do |reply|
1088							assert_equal :form, reply.form.type
1089							assert_equal(
1090								"Not a valid invite code: abc",
1091								reply.form.instructions
1092							)
1093						end]
1094					)
1095
1096					Registration::Payment::InviteCode.new(
1097						customer,
1098						@tel
1099					).write.catch { |e| e }
1100				end
1101				assert_equal :test_result, result
1102				assert_mock Command::COMMAND_MANAGER
1103				assert_mock Registration::Payment::InviteCode::DB
1104				assert_mock Registration::Payment::InviteCode::REDIS
1105			end
1106			em :test_write_bad_code
1107
1108			def test_write_group_code
1109				result = execute_command do
1110					customer = customer(plan_name: "test_usd")
1111					Registration::Payment::InviteCode::REDIS.expect(
1112						:set,
1113						EMPromise.resolve(nil),
1114						["jmp_customer_pending_invite-test", "abc"]
1115					)
1116					Registration::Payment::InviteCode::REDIS.expect(
1117						:get,
1118						EMPromise.resolve(0),
1119						["jmp_invite_tries-test"]
1120					)
1121					Registration::Payment::InviteCode::REDIS.expect(
1122						:hget,
1123						EMPromise.resolve(nil),
1124						["jmp_parent_codes", "abc"]
1125					)
1126					Registration::Payment::InviteCode::DB.expect(
1127						:transaction,
1128						[]
1129					) { |&blk| blk.call }
1130					Registration::Payment::InviteCode::DB.expect(
1131						:exec,
1132						OpenStruct.new(cmd_tuples: 0),
1133						[String, ["test", "abc"]]
1134					)
1135					Registration::Payment::InviteCode::REDIS.expect(
1136						:incr,
1137						EMPromise.resolve(nil),
1138						["jmp_invite_tries-test"]
1139					)
1140					Registration::Payment::InviteCode::REDIS.expect(
1141						:expire,
1142						EMPromise.resolve(nil),
1143						["jmp_invite_tries-test", 60 * 60]
1144					)
1145					Registration::Payment::InviteCode::REDIS.expect(
1146						:hexists,
1147						EMPromise.resolve(1),
1148						["jmp_group_codes", "abc"]
1149					)
1150					Command::COMMAND_MANAGER.expect(
1151						:write,
1152						EMPromise.resolve(
1153							Blather::Stanza::Iq::Command.new.tap { |iq|
1154								iq.form.fields = [{ var: "code", value: "abc" }]
1155							}
1156						),
1157						[Matching.new do |reply|
1158							assert_equal :form, reply.form.type
1159							assert_nil reply.form.instructions
1160						end]
1161					)
1162					Command::COMMAND_MANAGER.expect(
1163						:write,
1164						EMPromise.reject(:test_result),
1165						[Matching.new do |reply|
1166							assert_equal :form, reply.form.type
1167							assert_equal(
1168								"abc is a post-payment referral",
1169								reply.form.instructions
1170							)
1171						end]
1172					)
1173
1174					Registration::Payment::InviteCode.new(
1175						customer,
1176						@tel
1177					).write.catch { |e| e }
1178				end
1179				assert_equal :test_result, result
1180				assert_mock Command::COMMAND_MANAGER
1181				assert_mock Registration::Payment::InviteCode::DB
1182				assert_mock Registration::Payment::InviteCode::REDIS
1183			end
1184			em :test_write_group_code
1185
1186			def test_write_bad_code_over_limit
1187				result = execute_command do
1188					customer = customer(plan_name: "test_usd")
1189					Registration::Payment::InviteCode::REDIS.expect(
1190						:get,
1191						EMPromise.resolve(11),
1192						["jmp_invite_tries-test"]
1193					)
1194					Registration::Payment::InviteCode::REDIS.expect(
1195						:hget,
1196						EMPromise.resolve(nil),
1197						["jmp_parent_codes", "abc"]
1198					)
1199					Command::COMMAND_MANAGER.expect(
1200						:write,
1201						EMPromise.resolve(
1202							Blather::Stanza::Iq::Command.new.tap { |iq|
1203								iq.form.fields = [{ var: "code", value: "abc" }]
1204							}
1205						),
1206						[Matching.new do |reply|
1207							assert_equal :form, reply.form.type
1208							assert_nil reply.form.instructions
1209						end]
1210					)
1211					Command::COMMAND_MANAGER.expect(
1212						:write,
1213						EMPromise.reject(:test_result),
1214						[Matching.new do |reply|
1215							assert_equal :form, reply.form.type
1216							assert_equal "Too many wrong attempts", reply.form.instructions
1217						end]
1218					)
1219					Registration::Payment::InviteCode.new(
1220						customer,
1221						@tel
1222					).write.catch { |e| e }
1223				end
1224				assert_equal :test_result, result
1225				assert_mock Command::COMMAND_MANAGER
1226				assert_mock Registration::Payment::InviteCode::REDIS
1227			end
1228			em :test_write_bad_code_over_limit
1229		end
1230	end
1231
1232	class FinishTest < Minitest::Test
1233		Customer::BLATHER = Minitest::Mock.new
1234		Command::COMMAND_MANAGER = Minitest::Mock.new
1235		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
1236		Registration::Finish::REDIS = Minitest::Mock.new
1237		Registration::Finish::DB = Minitest::Mock.new
1238		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
1239		Registration::FinishOnboarding::DB = FakeDB.new
1240		Transaction::DB = Minitest::Mock.new
1241
1242		def setup
1243			@sgx = Minitest::Mock.new(mksgx)
1244			iq = Blather::Stanza::Iq::Command.new
1245			iq.from = "test\\40example.com@cheogram.com"
1246			@finish = Registration::Finish.new(
1247				customer(sgx: @sgx, plan_name: "test_usd"),
1248				TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1249			)
1250		end
1251
1252		def test_write
1253			create_order = stub_request(
1254				:post,
1255				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1256			).to_return(status: 201, body: <<~RESPONSE)
1257				<OrderResponse>
1258					<Order>
1259						<id>test_order</id>
1260					</Order>
1261				</OrderResponse>
1262			RESPONSE
1263			stub_request(
1264				:get,
1265				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1266			).to_return(status: 201, body: <<~RESPONSE)
1267				<OrderResponse>
1268					<OrderStatus>COMPLETE</OrderStatus>
1269					<CompletedNumbers>
1270						<TelephoneNumber>
1271							<FullNumber>5555550000</FullNumber>
1272						</TelephoneNumber>
1273					</CompletedNumbers>
1274				</OrderResponse>
1275			RESPONSE
1276			stub_request(
1277				:post,
1278				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1279			)
1280			Registration::Finish::REDIS.expect(
1281				:get,
1282				nil,
1283				["jmp_customer_pending_invite-test"]
1284			)
1285			Registration::Finish::REDIS.expect(
1286				:del,
1287				nil,
1288				["jmp_customer_pending_invite-test"]
1289			)
1290			Registration::Finish::REDIS.expect(
1291				:hget,
1292				nil,
1293				["jmp_group_codes", nil]
1294			)
1295			Bwmsgsv2Repo::REDIS.expect(
1296				:get,
1297				EMPromise.resolve(nil),
1298				["jmp_customer_backend_sgx-test"]
1299			)
1300			Bwmsgsv2Repo::REDIS.expect(
1301				:set,
1302				nil,
1303				[
1304					"catapult_fwd-+15555550000",
1305					"xmpp:test@example.net"
1306				]
1307			)
1308			Bwmsgsv2Repo::REDIS.expect(
1309				:set,
1310				nil,
1311				["catapult_fwd_timeout-customer_test@component", 25]
1312			)
1313			Customer::BLATHER.expect(
1314				:<<,
1315				nil,
1316				[Matching.new do |m|
1317					assert_equal :chat, m.type
1318					assert m.body =~ /^Welcome to JMP/
1319				end]
1320			)
1321			blather = Minitest::Mock.new
1322			blather.expect(
1323				:<<,
1324				nil,
1325				[Matching.new do |reply|
1326					assert_equal :completed, reply.status
1327					assert_equal :info, reply.note_type
1328					assert_equal(
1329						"Your JMP account has been activated as (555) 555-0000",
1330						reply.note.content
1331					)
1332				end]
1333			)
1334			execute_command(blather: blather) do
1335				@sgx.expect(
1336					:register!,
1337					EMPromise.resolve(@sgx.with(
1338						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1339							ibr.phone = "+15555550000"
1340						end
1341					)),
1342					["+15555550000"]
1343				)
1344
1345				@finish.write
1346			end
1347			assert_requested create_order
1348			assert_mock @sgx
1349			assert_mock Registration::Finish::REDIS
1350			assert_mock Bwmsgsv2Repo::REDIS
1351			assert_mock Customer::BLATHER
1352			assert_mock blather
1353		end
1354		em :test_write
1355
1356		def test_write_with_pending_code
1357			create_order = stub_request(
1358				:post,
1359				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1360			).to_return(status: 201, body: <<~RESPONSE)
1361				<OrderResponse>
1362					<Order>
1363						<id>test_order</id>
1364					</Order>
1365				</OrderResponse>
1366			RESPONSE
1367			stub_request(
1368				:get,
1369				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1370			).to_return(status: 201, body: <<~RESPONSE)
1371				<OrderResponse>
1372					<OrderStatus>COMPLETE</OrderStatus>
1373					<CompletedNumbers>
1374						<TelephoneNumber>
1375							<FullNumber>5555550000</FullNumber>
1376						</TelephoneNumber>
1377					</CompletedNumbers>
1378				</OrderResponse>
1379			RESPONSE
1380			stub_request(
1381				:post,
1382				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1383			)
1384			Registration::Finish::REDIS.expect(
1385				:get,
1386				EMPromise.resolve("123"),
1387				["jmp_customer_pending_invite-test"]
1388			)
1389			Registration::Finish::REDIS.expect(
1390				:del,
1391				nil,
1392				["jmp_customer_pending_invite-test"]
1393			)
1394			Registration::Finish::REDIS.expect(
1395				:hget,
1396				EMPromise.resolve("test-inviter"),
1397				["jmp_group_codes", "123"]
1398			)
1399			Registration::Finish::DB.expect(
1400				:exec,
1401				EMPromise.resolve(nil),
1402				[String, ["test-inviter", "test"]]
1403			)
1404			Transaction::DB.expect(:transaction, nil) do |&blk|
1405				blk.call
1406				true
1407			end
1408			Transaction::DB.expect(
1409				:exec,
1410				nil,
1411				[String, Matching.new { |params|
1412					assert_equal "test", params[0]
1413					assert params[1].start_with?("referral_")
1414					assert_equal 1, params[4]
1415					assert_equal "Referral Bonus", params[5]
1416				}]
1417			)
1418			Bwmsgsv2Repo::REDIS.expect(
1419				:get,
1420				EMPromise.resolve(nil),
1421				["jmp_customer_backend_sgx-test"]
1422			)
1423			Bwmsgsv2Repo::REDIS.expect(
1424				:set,
1425				nil,
1426				[
1427					"catapult_fwd-+15555550000",
1428					"xmpp:test@example.net"
1429				]
1430			)
1431			Bwmsgsv2Repo::REDIS.expect(
1432				:set,
1433				nil,
1434				["catapult_fwd_timeout-customer_test@component", 25]
1435			)
1436			Customer::BLATHER.expect(
1437				:<<,
1438				nil,
1439				[Matching.new do |m|
1440					assert_equal :chat, m.type
1441					assert m.body =~ /^Welcome to JMP/
1442				end]
1443			)
1444			blather = Minitest::Mock.new
1445			blather.expect(
1446				:<<,
1447				nil,
1448				[Matching.new do |reply|
1449					assert_equal :completed, reply.status
1450					assert_equal :info, reply.note_type
1451					assert_equal(
1452						"Your JMP account has been activated as (555) 555-0000",
1453						reply.note.content
1454					)
1455				end]
1456			)
1457			execute_command(blather: blather) do
1458				@sgx.expect(
1459					:register!,
1460					EMPromise.resolve(@sgx.with(
1461						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1462							ibr.phone = "+15555550000"
1463						end
1464					)),
1465					["+15555550000"]
1466				)
1467
1468				@finish.write
1469			end
1470			assert_requested create_order
1471			assert_mock @sgx
1472			assert_mock Registration::Finish::REDIS
1473			assert_mock Bwmsgsv2Repo::REDIS
1474			assert_mock Customer::BLATHER
1475			assert_mock blather
1476			assert_mock Transaction::DB
1477		end
1478		em :test_write_with_pending_code
1479
1480		def test_write_onboarding
1481			create_order = stub_request(
1482				:post,
1483				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1484			).to_return(status: 201, body: <<~RESPONSE)
1485				<OrderResponse>
1486					<Order>
1487						<id>test_order</id>
1488					</Order>
1489				</OrderResponse>
1490			RESPONSE
1491			stub_request(
1492				:get,
1493				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1494			).to_return(status: 201, body: <<~RESPONSE)
1495				<OrderResponse>
1496					<OrderStatus>COMPLETE</OrderStatus>
1497					<CompletedNumbers>
1498						<TelephoneNumber>
1499							<FullNumber>5555550000</FullNumber>
1500						</TelephoneNumber>
1501					</CompletedNumbers>
1502				</OrderResponse>
1503			RESPONSE
1504			stub_request(
1505				:post,
1506				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1507			)
1508			Registration::Finish::REDIS.expect(
1509				:get,
1510				nil,
1511				["jmp_customer_pending_invite-test"]
1512			)
1513			Registration::Finish::REDIS.expect(
1514				:del,
1515				nil,
1516				["jmp_customer_pending_invite-test"]
1517			)
1518			Registration::Finish::REDIS.expect(
1519				:hget,
1520				nil,
1521				["jmp_group_codes", nil]
1522			)
1523			Bwmsgsv2Repo::REDIS.expect(
1524				:get,
1525				EMPromise.resolve(nil),
1526				["jmp_customer_backend_sgx-test"]
1527			)
1528			Bwmsgsv2Repo::REDIS.expect(
1529				:set,
1530				nil,
1531				[
1532					"catapult_fwd-+15555550000",
1533					"xmpp:test\\40onboarding.example.com@proxy"
1534				]
1535			)
1536			Bwmsgsv2Repo::REDIS.expect(
1537				:set,
1538				nil,
1539				["catapult_fwd_timeout-customer_test@component", 25]
1540			)
1541			result = execute_command do
1542				@sgx.expect(
1543					:register!,
1544					EMPromise.resolve(@sgx.with(
1545						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1546							ibr.phone = "+15555550000"
1547						end
1548					)),
1549					["+15555550000"]
1550				)
1551
1552				Command::COMMAND_MANAGER.expect(
1553					:write,
1554					EMPromise.reject(:test_result),
1555					[Matching.new do |iq|
1556						assert_equal :form, iq.form.type
1557						assert iq.form.field("subdomain")
1558					end]
1559				)
1560
1561				Registration::Finish.new(
1562					customer(
1563						sgx: @sgx,
1564						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1565					),
1566					TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1567				).write.catch { |e| e }
1568			end
1569			assert_equal :test_result, result
1570			assert_requested create_order
1571			assert_mock @sgx
1572			assert_mock Registration::Finish::REDIS
1573			assert_mock Bwmsgsv2Repo::REDIS
1574			assert_mock Command::COMMAND_MANAGER
1575		end
1576		em :test_write_onboarding
1577
1578		def test_write_local_inventory
1579			stub_request(
1580				:post,
1581				"https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
1582			).with(
1583				body: {
1584					CustomerOrderId: "test",
1585					SourceAccountId: "bandwidth_account_id",
1586					SiteId: "test_site",
1587					SipPeerId: "test_peer",
1588					TelephoneNumbers: { TelephoneNumber: "5555550000" }
1589				}.to_xml(indent: 0, root: "MoveTnsOrder")
1590			).to_return(status: 200, body: "", headers: {})
1591
1592			Registration::Finish::REDIS.expect(
1593				:get,
1594				nil,
1595				["jmp_customer_pending_invite-test"]
1596			)
1597			Registration::Finish::REDIS.expect(
1598				:del,
1599				nil,
1600				["jmp_customer_pending_invite-test"]
1601			)
1602			Registration::Finish::REDIS.expect(
1603				:hget,
1604				nil,
1605				["jmp_group_codes", nil]
1606			)
1607			Registration::Finish::DB.expect(
1608				:exec_defer,
1609				EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
1610				[String, ["+15555550000"]]
1611			)
1612			Bwmsgsv2Repo::REDIS.expect(
1613				:get,
1614				EMPromise.resolve(nil),
1615				["jmp_customer_backend_sgx-test"]
1616			)
1617			Bwmsgsv2Repo::REDIS.expect(
1618				:set,
1619				nil,
1620				[
1621					"catapult_fwd-+15555550000",
1622					"xmpp:test\\40onboarding.example.com@proxy"
1623				]
1624			)
1625			Bwmsgsv2Repo::REDIS.expect(
1626				:set,
1627				nil,
1628				["catapult_fwd_timeout-customer_test@component", 25]
1629			)
1630			result = execute_command do
1631				@sgx.expect(
1632					:register!,
1633					EMPromise.resolve(@sgx.with(
1634						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1635							ibr.phone = "+15555550000"
1636						end
1637					)),
1638					["+15555550000"]
1639				)
1640
1641				Command::COMMAND_MANAGER.expect(
1642					:write,
1643					EMPromise.reject(:test_result),
1644					[Matching.new do |iq|
1645						assert_equal :form, iq.form.type
1646						assert iq.form.field("subdomain")
1647					end]
1648				)
1649
1650				Registration::Finish.new(
1651					customer(
1652						sgx: @sgx,
1653						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1654					),
1655					TelSelections::ChooseTel::Tn::LocalInventory.new(
1656						TelSelections::ChooseTel::Tn.new("+15555550000"),
1657						"bandwidth_account_id"
1658					)
1659				).write.catch { |e| e }
1660			end
1661			assert_equal :test_result, result
1662			assert_mock @sgx
1663			assert_mock Registration::Finish::REDIS
1664			assert_mock Bwmsgsv2Repo::REDIS
1665			assert_mock Command::COMMAND_MANAGER
1666		end
1667		em :test_write_local_inventory
1668
1669		def test_write_local_inventory_must_pay
1670			low_cust = customer(
1671				sgx: @sgx,
1672				jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1673			).with_balance(5.0)
1674			high_cust = customer(
1675				sgx: @sgx,
1676				jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1677			).with_balance(100.0)
1678
1679			stub_request(
1680				:post,
1681				"https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
1682			).with(
1683				body: {
1684					CustomerOrderId: "test",
1685					SourceAccountId: "bandwidth_account_id",
1686					SiteId: "test_site",
1687					SipPeerId: "test_peer",
1688					TelephoneNumbers: { TelephoneNumber: "5555550000" }
1689				}.to_xml(indent: 0, root: "MoveTnsOrder")
1690			).to_return(status: 200, body: "", headers: {})
1691
1692			Registration::Finish::REDIS.expect(
1693				:get,
1694				nil,
1695				["jmp_customer_pending_invite-test"]
1696			)
1697			Registration::Finish::REDIS.expect(
1698				:del,
1699				nil,
1700				["jmp_customer_pending_invite-test"]
1701			)
1702			Registration::Finish::REDIS.expect(
1703				:hget,
1704				nil,
1705				["jmp_group_codes", nil]
1706			)
1707			Registration::Finish::DB.expect(
1708				:exec_defer,
1709				EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
1710				[String, ["+15555550000"]]
1711			)
1712			Bwmsgsv2Repo::REDIS.expect(
1713				:get,
1714				EMPromise.resolve(nil),
1715				["jmp_customer_backend_sgx-test"]
1716			)
1717			Bwmsgsv2Repo::REDIS.expect(
1718				:set,
1719				nil,
1720				[
1721					"catapult_fwd-+15555550000",
1722					"xmpp:test\\40onboarding.example.com@proxy"
1723				]
1724			)
1725			Bwmsgsv2Repo::REDIS.expect(
1726				:set,
1727				nil,
1728				["catapult_fwd_timeout-customer_test@component", 25]
1729			)
1730
1731			local_tel = Minitest::Mock.new(
1732				TelSelections::ChooseTel::Tn::LocalInventory.new(
1733					TelSelections::ChooseTel::Tn.new("+15555550000"),
1734					"bandwidth_account_id",
1735					price: 10.0
1736				)
1737			)
1738
1739			result = execute_command do
1740				local_tel.expect(:charge, EMPromise.reject(:test_result), [Customer])
1741				@sgx.expect(
1742					:register!,
1743					EMPromise.resolve(@sgx.with(
1744						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1745							ibr.phone = "+15555550000"
1746						end
1747					)),
1748					["+15555550000"]
1749				)
1750
1751				Command::COMMAND_MANAGER.expect(
1752					:write,
1753					EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
1754						iq.from = "customer@example.org"
1755						iq.form.fields = [
1756							{ var: "activation_method", value: "credit_card" }
1757						]
1758					}),
1759					[Matching.new do |iq|
1760						assert_equal :form, iq.form.type
1761						assert_equal "Purchase Number", iq.form.title
1762					end]
1763				)
1764
1765				Command.execution.customer_repo.expect(
1766					:find,
1767					EMPromise.resolve(high_cust),
1768					["test"]
1769				)
1770
1771				Command::COMMAND_MANAGER.expect(
1772					:write,
1773					EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
1774						iq.from = "customer@example.org"
1775					}),
1776					[Matching.new do |iq|
1777						assert_equal(
1778							"Pay by credit card, save, then next here to continue: " \
1779							"http://creditcard.example.com?&amount=10",
1780							iq.note.text
1781						)
1782					end]
1783				)
1784
1785				Registration::Finish.new(
1786					low_cust,
1787					local_tel
1788				).write.catch { |e| e }
1789			end
1790
1791			assert_equal :test_result, result
1792			assert_mock @sgx
1793			assert_mock Registration::Finish::REDIS
1794			assert_mock Bwmsgsv2Repo::REDIS
1795			assert_mock Command::COMMAND_MANAGER
1796		end
1797		em :test_write_local_inventory_must_pay
1798
1799		def test_write_tn_fail
1800			create_order = stub_request(
1801				:post,
1802				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1803			).to_return(status: 201, body: <<~RESPONSE)
1804				<OrderResponse>
1805					<Order>
1806						<id>test_order</id>
1807					</Order>
1808				</OrderResponse>
1809			RESPONSE
1810			stub_request(
1811				:get,
1812				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1813			).to_return(status: 201, body: <<~RESPONSE)
1814				<OrderResponse>
1815					<OrderStatus>FAILED</OrderStatus>
1816				</OrderResponse>
1817			RESPONSE
1818
1819			result = execute_command do
1820				Command::COMMAND_MANAGER.expect(
1821					:write,
1822					EMPromise.reject(:test_result),
1823					[Matching.new do |iq|
1824						assert_equal :form, iq.form.type
1825						assert_equal(
1826							"The JMP number (555) 555-0000 is no longer available.",
1827							iq.form.instructions
1828						)
1829					end]
1830				)
1831
1832				@finish.write.catch { |e| e }
1833			end
1834
1835			assert_equal :test_result, result
1836			assert_mock Command::COMMAND_MANAGER
1837			assert_instance_of(
1838				TelSelections::ChooseTel,
1839				Registration::Finish::TEL_SELECTIONS["test@example.com"]
1840			)
1841			assert_requested create_order
1842		end
1843		em :test_write_tn_fail
1844
1845		def test_write_tn_fail_no_data_only_option
1846			create_order = stub_request(
1847				:post,
1848				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1849			).to_return(status: 201, body: <<~RESPONSE)
1850				<OrderResponse>
1851					<Order>
1852						<id>test_order</id>
1853					</Order>
1854				</OrderResponse>
1855			RESPONSE
1856			stub_request(
1857				:get,
1858				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1859			).to_return(status: 201, body: <<~RESPONSE)
1860				<OrderResponse>
1861					<OrderStatus>FAILED</OrderStatus>
1862				</OrderResponse>
1863			RESPONSE
1864
1865			result = execute_command do
1866				Command::COMMAND_MANAGER.expect(
1867					:write,
1868					EMPromise.reject(:test_result),
1869					[Matching.new do |iq|
1870						assert_equal :form, iq.form.type
1871						assert_equal(
1872							"The JMP number (555) 555-0000 is no longer available.",
1873							iq.form.instructions
1874						)
1875						action_field = iq.form.field(
1876							"http://jabber.org/protocol/commands#actions"
1877						)
1878						refute(
1879							action_field.options.any? { |o| o.value == "data_only" },
1880							"data_only option should not be present"
1881						)
1882					end]
1883				)
1884
1885				@finish.write.catch { |e| e }
1886			end
1887
1888			assert_equal :test_result, result
1889			assert_mock Command::COMMAND_MANAGER
1890			assert_requested create_order
1891		end
1892		em :test_write_tn_fail_no_data_only_option
1893	end
1894
1895	class SnikketTest < Minitest::Test
1896		Command::COMMAND_MANAGER = Minitest::Mock.new
1897		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
1898
1899		def setup
1900			@sgx = Minitest::Mock.new(mksgx)
1901			@snikket = Registration::FinishOnboarding::Snikket.new(
1902				customer(sgx: @sgx),
1903				"+15555550000",
1904				db: FakeDB.new
1905			)
1906		end
1907
1908		def test_write
1909			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
1910
1911			subdomain_form = Blather::Stanza::Iq::Command.new
1912			subdomain_form.form.fields = [
1913				{ var: "subdomain", value: "test" }
1914			]
1915
1916			launched = Snikket::Launched.new
1917			launched << Niceogiri::XML::Node.new(
1918				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1919			).tap { |inner|
1920				inner << Niceogiri::XML::Node.new(
1921					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1922				).tap { |id|
1923					id.content = "si-1234"
1924				}
1925				inner << Niceogiri::XML::Node.new(
1926					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1927				).tap { |bootstrap|
1928					bootstrap << Niceogiri::XML::Node.new(
1929						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1930					).tap { |token|
1931						token.content = "TOKEN"
1932					}
1933				}
1934			}
1935
1936			blather = Minitest::Mock.new
1937			blather.expect(
1938				:<<,
1939				nil,
1940				[Matching.new do |reply|
1941					assert_equal :completed, reply.status
1942					assert_equal(
1943						xmpp_uri,
1944						OOB.find_or_create(reply.command).url
1945					)
1946				end]
1947			)
1948
1949			execute_command(blather: blather) do
1950				Command::COMMAND_MANAGER.expect(
1951					:write,
1952					EMPromise.resolve(subdomain_form),
1953					[Matching.new do |iq|
1954						assert_equal :form, iq.form.type
1955						assert iq.form.field("subdomain")
1956					end]
1957				)
1958
1959				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1960					:write,
1961					EMPromise.resolve(launched),
1962					[Matching.new do |iq|
1963						assert_equal :set, iq.type
1964						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1965						assert_equal(
1966							"test.snikket.chat",
1967							iq.xpath(
1968								"./ns:launch/ns:domain",
1969								ns: "xmpp:snikket.org/hosting/v1"
1970							).text
1971						)
1972					end]
1973				)
1974
1975				# Webmock doesn't support redirects properly, but they work live
1976				stub_request(
1977					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1978				).to_return(
1979					status: 200,
1980					headers: {
1981						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1982					}
1983				)
1984
1985				@snikket.write
1986			end
1987
1988			assert_mock Command::COMMAND_MANAGER
1989			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1990			assert_mock blather
1991		end
1992		em :test_write
1993
1994		def test_write_not_yet
1995			subdomain_form = Blather::Stanza::Iq::Command.new
1996			subdomain_form.form.fields = [
1997				{ var: "subdomain", value: "test" }
1998			]
1999
2000			launched = Snikket::Launched.new
2001			launched << Niceogiri::XML::Node.new(
2002				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
2003			).tap { |inner|
2004				inner << Niceogiri::XML::Node.new(
2005					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
2006				).tap { |id|
2007					id.content = "si-1234"
2008				}
2009				inner << Niceogiri::XML::Node.new(
2010					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
2011				).tap { |bootstrap|
2012					bootstrap << Niceogiri::XML::Node.new(
2013						:token, launched.document, "xmpp:snikket.org/hosting/v1"
2014					).tap { |token|
2015						token.content = "TOKEN"
2016					}
2017				}
2018			}
2019
2020			result = execute_command do
2021				Command::COMMAND_MANAGER.expect(
2022					:write,
2023					EMPromise.resolve(subdomain_form),
2024					[Matching.new do |iq|
2025						assert_equal :form, iq.form.type
2026						assert iq.form.field("subdomain")
2027					end]
2028				)
2029
2030				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
2031					:write,
2032					EMPromise.resolve(launched),
2033					[Matching.new do |iq|
2034						assert_equal :set, iq.type
2035						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
2036						assert_equal(
2037							"test.snikket.chat",
2038							iq.xpath(
2039								"./ns:launch/ns:domain",
2040								ns: "xmpp:snikket.org/hosting/v1"
2041							).text
2042						)
2043					end]
2044				)
2045
2046				stub_request(
2047					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
2048				).to_timeout
2049
2050				Command::COMMAND_MANAGER.expect(
2051					:write,
2052					EMPromise.reject(:test_result),
2053					[Matching.new do |iq|
2054						assert_equal :result, iq.form.type
2055						assert iq.form.instructions =~ / test\.snikket\.chat /
2056						assert_equal "jid-single", iq.form.field("support").type
2057					end]
2058				)
2059
2060				@snikket.write.catch { |e| e }
2061			end
2062
2063			assert_equal :test_result, result
2064			assert_mock Command::COMMAND_MANAGER
2065			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
2066		end
2067		em :test_write_not_yet
2068
2069		def test_write_already_taken
2070			subdomain_form = Blather::Stanza::Iq::Command.new
2071			subdomain_form.form.fields = [
2072				{ var: "subdomain", value: "test" }
2073			]
2074
2075			launched = Snikket::Launched.new.as_error(
2076				"internal-server-error",
2077				:wait,
2078				"This is an error"
2079			)
2080
2081			result = execute_command do
2082				Command::COMMAND_MANAGER.expect(
2083					:write,
2084					EMPromise.resolve(subdomain_form),
2085					[Matching.new do |iq|
2086						assert_equal :form, iq.form.type
2087						assert iq.form.field("subdomain")
2088					end]
2089				)
2090
2091				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
2092					:write,
2093					EMPromise.reject(launched),
2094					[Matching.new do |iq|
2095						assert_equal :set, iq.type
2096						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
2097						assert_equal(
2098							"test.snikket.chat",
2099							iq.xpath(
2100								"./ns:launch/ns:domain",
2101								ns: "xmpp:snikket.org/hosting/v1"
2102							).text
2103						)
2104					end]
2105				)
2106
2107				stub_request(
2108					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
2109				).to_timeout
2110
2111				Command::COMMAND_MANAGER.expect(
2112					:write,
2113					EMPromise.reject(:test_result),
2114					[Matching.new do |iq|
2115						assert iq.executing?
2116						assert_equal(
2117							"This is an error",
2118							iq.form.field("subdomain").desc
2119						)
2120					end]
2121				)
2122
2123				@snikket.write.catch { |e| e }
2124			end
2125
2126			assert_equal :test_result, result
2127			assert_mock Command::COMMAND_MANAGER
2128			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
2129		end
2130		em :test_write_already_taken
2131	end
2132
2133	class SnikketCustomDomainTest < Minitest::Test
2134		def setup
2135			@snikket = Registration::FinishOnboarding::CustomDomain.new(
2136				customer,
2137				"+15555550000",
2138				db: FakeDB.new
2139			)
2140		end
2141
2142		def test_write_needs_dns
2143			domain_form = Blather::Stanza::Iq::Command.new
2144			domain_form.form.fields = [
2145				{ var: "domain", value: "snikket.example.com" }
2146			]
2147
2148			launched = Snikket::Launched.new
2149			launched << Niceogiri::XML::Node.new(
2150				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
2151			).tap { |inner|
2152				inner << Niceogiri::XML::Node.new(
2153					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
2154				).tap { |id|
2155					id.content = "si-1234"
2156				}
2157				inner << Niceogiri::XML::Node.new(
2158					:status, launched.document, "xmpp:snikket.org/hosting/v1"
2159				).tap { |id|
2160					id.content = "needs_dns"
2161				}
2162				inner << Niceogiri::XML::Node.new(
2163					:records, launched.document, "xmpp:snikket.org/hosting/v1"
2164				).tap { |records|
2165					records << Niceogiri::XML::Node.new(
2166						:record, launched.document, "xmpp:snikket.org/hosting/v1"
2167					).tap { |record|
2168						record << Niceogiri::XML::Node.new(
2169							:name, launched.document, "xmpp:snikket.org/hosting/v1"
2170						).tap { |name| name.content = "snikket.example.com" }
2171						record << Niceogiri::XML::Node.new(
2172							:type, launched.document, "xmpp:snikket.org/hosting/v1"
2173						).tap { |type| type.content = "AAAA" }
2174						record << Niceogiri::XML::Node.new(
2175							:status, launched.document, "xmpp:snikket.org/hosting/v1"
2176						).tap { |type| type.content = "incorrect" }
2177						record << Niceogiri::XML::Node.new(
2178							:expected, launched.document, "xmpp:snikket.org/hosting/v1"
2179						).tap { |expected|
2180							expected << Niceogiri::XML::Node.new(
2181								:value, launched.document, "xmpp:snikket.org/hosting/v1"
2182							).tap { |value| value.content = "1::2" }
2183						}
2184						record << Niceogiri::XML::Node.new(
2185							:found, launched.document, "xmpp:snikket.org/hosting/v1"
2186						).tap { |found|
2187							found << Niceogiri::XML::Node.new(
2188								:value, launched.document, "xmpp:snikket.org/hosting/v1"
2189							).tap { |value| value.content = "0::0" }
2190						}
2191					}
2192				}
2193			}
2194
2195			result = execute_command do
2196				Command::COMMAND_MANAGER.expect(
2197					:write,
2198					EMPromise.resolve(domain_form),
2199					[Matching.new do |iq|
2200						assert_equal :form, iq.form.type
2201						assert iq.form.field("domain")
2202					end]
2203				)
2204
2205				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
2206					:write,
2207					EMPromise.resolve(launched),
2208					[Matching.new do |iq|
2209						assert_equal :set, iq.type
2210						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
2211						assert_equal(
2212							"snikket.example.com",
2213							iq.xpath(
2214								"./ns:launch/ns:domain",
2215								ns: "xmpp:snikket.org/hosting/v1"
2216							).text
2217						)
2218					end]
2219				)
2220
2221				Command::COMMAND_MANAGER.expect(
2222					:write,
2223					EMPromise.reject(:test_result),
2224					[Matching.new do |iq|
2225						assert_equal :form, iq.form.type
2226						assert_equal(
2227							["snikket.example.com"],
2228							iq.form.xpath(
2229								"./ns:item/ns:field[@var='name']/ns:value",
2230								ns: "jabber:x:data"
2231							).map(&:content)
2232						)
2233						assert_equal(
2234							["1::2"],
2235							iq.form.xpath(
2236								"./ns:item/ns:field[@var='expected']/ns:value",
2237								ns: "jabber:x:data"
2238							).map(&:content)
2239						)
2240					end]
2241				)
2242
2243				@snikket.write.catch { |e| e }
2244			end
2245
2246			assert_equal :test_result, result
2247			assert_mock Command::COMMAND_MANAGER
2248			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
2249		end
2250		em :test_write_needs_dns
2251	end
2252
2253	class RegistrationTypeTest < Minitest::Test
2254		def test_for_with_sim_kind
2255			cust = customer(plan_name: "test_usd").with_balance(1000)
2256			sim_kind = SIMKind.new("sim")
2257			result = Registration::RegistrationType.for(cust, nil, sim_kind)
2258			assert_kind_of Registration::DataOnly, result
2259		end
2260
2261		def test_for_with_esim_kind
2262			cust = customer(plan_name: "test_usd").with_balance(1000)
2263			sim_kind = SIMKind.new("esim")
2264			result = Registration::RegistrationType.for(cust, nil, sim_kind)
2265			assert_kind_of Registration::DataOnly, result
2266		end
2267
2268		def test_for_with_telephone_number
2269			cust = customer(plan_name: "test_usd", expires_at: Time.now + 999)
2270			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
2271			result = Registration::RegistrationType.for(cust, nil, tel)
2272			assert_kind_of Registration::Finish, result
2273		end
2274	end
2275
2276	class DataOnlyTest < Minitest::Test
2277		def setup
2278			@customer = customer(plan_name: "test_usd").with_balance(5)
2279			@sim_kind = SIMKind.new("sim")
2280		end
2281
2282		def test_for_returns_pay_for_sim_when_balance_insufficient
2283			low_balance_customer = @customer.with_balance(0.50)
2284			result = Registration::DataOnly.for(low_balance_customer, @sim_kind)
2285			assert_kind_of Registration::PayForSim, result
2286		end
2287
2288		def test_for_returns_pay_for_sim_when_config_missing
2289			no_currency_customer = customer(currency: nil)
2290			result = Registration::DataOnly.for(no_currency_customer, @sim_kind)
2291			assert_kind_of Registration::PayForSim, result
2292		end
2293
2294		def test_for_returns_data_only_when_balance_sufficient
2295			result =
2296				Registration::DataOnly.for(@customer, @sim_kind)
2297			assert_kind_of Registration::DataOnly, result
2298		end
2299
2300		def test_write_calls_sim_kind_for_and_process
2301			result = execute_command do
2302				Command::COMMAND_MANAGER.expect(
2303					:write,
2304					EMPromise.reject(:test_result),
2305					[Matching.new do |iq|
2306						assert_equal iq.form.title, "Order SIM"
2307						assert(
2308							iq.form.instructions.start_with?("Our SIMs provide a plan")
2309						)
2310					end]
2311				)
2312				Registration::DataOnly.new(
2313					@customer,
2314					@sim_kind
2315				).write.catch { |e| e }.sync
2316			end
2317			assert_equal result, :test_result
2318			assert_mock Command::COMMAND_MANAGER
2319		end
2320		em :test_write_calls_sim_kind_for_and_process
2321	end
2322
2323	class PayForSimTest < Minitest::Test
2324		Command::COMMAND_MANAGER = Minitest::Mock.new
2325		Registration::PayForSim::Payment = Minitest::Mock.new
2326
2327		def setup
2328			@customer = customer(plan_name: "test_usd")
2329			@sim_kind = SIMKind.new("sim")
2330			@pay_for_sim = Registration::PayForSim.new(@customer, @sim_kind)
2331		end
2332
2333		def test_write_displays_payment_form
2334			iq = Blather::Stanza::Iq::Command.new
2335			iq.form.fields = [
2336				{ var: "activation_method", value: "credit_card" }
2337			]
2338
2339			result = execute_command do
2340				Command::COMMAND_MANAGER.expect(
2341					:write,
2342					EMPromise.resolve(iq),
2343					[Matching.new do |reply|
2344						assert_equal :form, reply.form.type
2345						assert_equal "Pay for SIM", reply.form.title
2346					end]
2347				)
2348
2349				ejector_mock = Minitest::Mock.new
2350				ejector_mock.expect(
2351					:write,
2352					EMPromise.reject(:test_result),
2353					[]
2354				)
2355				Registration::PayForSim::Payment.expect(
2356					:for,
2357					ejector_mock
2358				) do |*, price:, maybe_bill:|
2359					assert_equal 500, price
2360					assert_equal(
2361						Registration::Payment::JustCharge,
2362						maybe_bill
2363					)
2364				end
2365				@pay_for_sim.write.catch { |e| e }
2366			end
2367
2368			assert_equal :test_result, result
2369			assert_mock Command::COMMAND_MANAGER
2370		end
2371		em :test_write_displays_payment_form
2372
2373		def test_write_with_no_currency_shows_plan_selection
2374			no_currency_customer = customer(currency: nil)
2375			pay_for_sim = Registration::PayForSim.new(no_currency_customer, @sim_kind)
2376
2377			iq = Blather::Stanza::Iq::Command.new
2378			iq.form.fields = [
2379				{ var: "plan_name", value: "test_usd" },
2380				{ var: "activation_method", value: "credit_card" }
2381			]
2382
2383			result = execute_command do
2384				Command::COMMAND_MANAGER.expect(
2385					:write,
2386					EMPromise.resolve(iq),
2387					[Matching.new do |reply|
2388						assert_equal :form, reply.form.type
2389						assert_equal "Pay for SIM", reply.form.title
2390					end]
2391				)
2392
2393				CustomerPlan::DB.expect(
2394					:exec_defer,
2395					EMPromise.resolve(nil),
2396					[String, ["test", "test_usd", nil]]
2397				)
2398				ejector_mock = Minitest::Mock.new
2399				ejector_mock.expect(
2400					:write,
2401					EMPromise.reject(:test_result),
2402					[]
2403				)
2404				Registration::PayForSim::Payment.expect(
2405					:for,
2406					ejector_mock
2407				) do |*, price:, maybe_bill:|
2408					assert_equal 500, price
2409					assert_equal(
2410						Registration::Payment::JustCharge,
2411						maybe_bill
2412					)
2413				end
2414				pay_for_sim.write.catch { |e| e }
2415			end
2416
2417			assert_equal :test_result, result
2418			assert_mock Command::COMMAND_MANAGER
2419			assert_mock CustomerPlan::DB
2420		end
2421		em :test_write_with_no_currency_shows_plan_selection
2422
2423		def test_process_payment_uses_just_charge_strategy
2424			iq = Blather::Stanza::Iq::Command.new
2425			iq.form.fields = [
2426				{ var: "activation_method", value: "credit_card" }
2427			]
2428
2429			reloaded_customer = @customer.with_balance(4).with_plan("test_usd")
2430
2431			result = execute_command do |exe|
2432				payment = Minitest::Mock.new
2433				payment.expect(
2434					:write,
2435					EMPromise.resolve(nil),
2436					[]
2437				)
2438				Registration::PayForSim::Payment.expect(
2439					:for,
2440					payment
2441				) do |_, customer, sim_kind, price:, maybe_bill:|
2442					assert_equal @customer, customer
2443					assert_equal @sim_kind, sim_kind
2444					assert_equal Registration::Payment::JustCharge, maybe_bill
2445					assert_equal 500, price
2446				end
2447				exe.customer_repo.expect(
2448					:find,
2449					EMPromise.resolve(reloaded_customer),
2450					[@customer.customer_id]
2451				)
2452
2453				result_ = @pay_for_sim.process_payment(iq).sync
2454				assert_mock payment
2455				assert_mock Command.execution.customer_repo
2456				assert_mock Registration::PayForSim::Payment
2457				result_
2458			end
2459			assert_kind_of Registration::PayForSim, result
2460		end
2461		em :test_process_payment_uses_just_charge_strategy
2462	end
2463end