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 |exe|
  60			sgx = OpenStruct.new(registered?: false)
  61			cust = customer(
  62				plan_name: "test_usd",
  63				expires_at: Time.now + 999,
  64				sgx: sgx
  65			)
  66			exe.customer_repo.expect(:find, cust, [cust.customer_id])
  67			Registration.for(cust, nil, web_manager)
  68		end
  69		assert_kind_of Registration::Finish, result
  70		assert_requested reservation_req
  71	end
  72	em :test_for_activated
  73
  74	def test_for_not_activated_approved
  75		sgx = OpenStruct.new(registered?: false)
  76		web_manager = TelSelections.new(
  77			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
  78		)
  79		web_manager.set(
  80			"test\\40approved.example.com@component",
  81			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
  82		)
  83		iq = Blather::Stanza::Iq::Command.new
  84		iq.from = "test@approved.example.com"
  85		result = execute_command(iq) do
  86			Registration::Activation.for(
  87				customer(
  88					sgx: sgx,
  89					jid: Blather::JID.new("test\\40approved.example.com@component")
  90				),
  91				nil,
  92				web_manager
  93			)
  94		end
  95		assert_kind_of Registration::Activation::Allow, result
  96	end
  97	em :test_for_not_activated_approved
  98
  99	def test_for_not_activated_googleplay
 100		skip
 101		sgx = OpenStruct.new(registered?: false)
 102		web_manager = TelSelections.new(
 103			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
 104		)
 105		web_manager.set(
 106			"test@example.net",
 107			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 108		)
 109		iq = Blather::Stanza::Iq::Command.new
 110		iq.from = "test@approved.example.com"
 111		result = execute_command(iq) do
 112			Registration::Activation.for(
 113				customer(sgx: sgx),
 114				"GARBLEDYGOOK==",
 115				web_manager
 116			)
 117		end
 118		assert_kind_of Registration::Activation::GooglePlay, result
 119	end
 120	em :test_for_not_activated_googleplay
 121
 122	def test_for_not_activated_with_customer_id
 123		sgx = OpenStruct.new(registered?: false)
 124		web_manager = TelSelections.new(
 125			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
 126		)
 127		web_manager.set(
 128			"test@example.net",
 129			TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 130		)
 131		iq = Blather::Stanza::Iq::Command.new
 132		iq.from = "test@example.com"
 133		result = execute_command(iq) do
 134			Registration::Activation.for(
 135				customer(sgx: sgx),
 136				nil,
 137				web_manager
 138			)
 139		end
 140		assert_kind_of Registration::Activation, result
 141	end
 142	em :test_for_not_activated_with_customer_id
 143
 144	class ActivationTest < Minitest::Test
 145		Registration::Activation::DB = Minitest::Mock.new
 146		Registration::Activation::REDIS = FakeRedis.new(
 147			"jmp_parent_codes" => {
 148				"PARENT_CODE" => "1",
 149				"PARENT_TOMB" => "2",
 150				"PARENT_MANY_SUBACCOUNTS" => "many_subaccounts"
 151			},
 152			"jmp_customer_trust_level-2" => "Tomb"
 153		)
 154		Registration::Activation::Payment = Minitest::Mock.new
 155		Registration::Activation::Finish = Minitest::Mock.new
 156		Command::COMMAND_MANAGER = Minitest::Mock.new
 157
 158		def setup
 159			@customer = Minitest::Mock.new(customer)
 160			@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 161			@activation = Registration::Activation.new(@customer, @tel)
 162		end
 163
 164		def test_write
 165			Command::COMMAND_MANAGER.expect(
 166				:write,
 167				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 168					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 169				}),
 170				[Matching.new do |iq|
 171					assert_equal :form, iq.form.type
 172					assert_equal(
 173						"You've selected (555) 555-0000 as your JMP number.",
 174						iq.form.instructions.lines.first.chomp
 175					)
 176				end]
 177			)
 178			@customer.expect(:with_plan, @customer) do |*args, **|
 179				assert_equal ["test_usd"], args
 180			end
 181			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 182			Registration::Activation::Payment.expect(
 183				:for,
 184				EMPromise.reject(:test_result),
 185				[Blather::Stanza::Iq, @customer, @tel]
 186			)
 187			assert_equal(
 188				:test_result,
 189				execute_command { @activation.write.catch { |e| e } }
 190			)
 191			assert_mock Command::COMMAND_MANAGER
 192			assert_mock @customer
 193			assert_mock Registration::Activation::Payment
 194		end
 195		em :test_write
 196
 197		def test_write_with_onboarding_jid
 198			Command::COMMAND_MANAGER.expect(
 199				:write,
 200				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 201					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 202				}),
 203				[Matching.new do |iq|
 204					assert_equal :form, iq.form.type
 205					assert_equal(
 206						"You've selected (555) 555-0000 as your JMP number.",
 207						iq.form.instructions.lines.first.chomp
 208					)
 209				end]
 210			)
 211			@customer.expect(
 212				:jid,
 213				Blather::JID.new("test\\40onboarding.example.com@proxy")
 214			)
 215			@customer.expect(:with_plan, @customer) do |*args, **|
 216				assert_equal ["test_usd"], args
 217			end
 218			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 219			Registration::Activation::Payment.expect(
 220				:for,
 221				EMPromise.reject(:test_result),
 222				[Blather::Stanza::Iq, @customer, @tel]
 223			)
 224			assert_equal(
 225				:test_result,
 226				execute_command { @activation.write.catch { |e| e } }
 227			)
 228			assert_mock Command::COMMAND_MANAGER
 229			assert_mock @customer
 230			assert_mock Registration::Activation::Payment
 231		end
 232		em :test_write_with_onboarding_jid
 233
 234		def test_write_bad_plan
 235			Command::COMMAND_MANAGER.expect(
 236				:write,
 237				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 238					iq.form.fields = [{ var: "plan_name", value: "test_usd_no_register" }]
 239				}),
 240				[Matching.new do |iq|
 241					assert_equal :form, iq.form.type
 242					assert_equal(
 243						"You've selected (555) 555-0000 as your JMP number.",
 244						iq.form.instructions.lines.first.chomp
 245					)
 246				end]
 247			)
 248			assert_equal(
 249				"No registration plan by that name",
 250				execute_command { @activation.write.catch { |e| e } }.message
 251			)
 252			assert_mock Command::COMMAND_MANAGER
 253			assert_mock @customer
 254		end
 255		em :test_write_bad_plan
 256
 257		def test_write_with_code
 258			Command::COMMAND_MANAGER.expect(
 259				:write,
 260				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 261					iq.form.fields = [
 262						{ var: "plan_name", value: "test_usd" },
 263						{ var: "code", value: "123" }
 264					]
 265				}),
 266				[Matching.new do |iq|
 267					assert_equal :form, iq.form.type
 268					assert_equal(
 269						"You've selected (555) 555-0000 as your JMP number.",
 270						iq.form.instructions.lines.first.chomp
 271					)
 272				end]
 273			)
 274			@customer.expect(:with_plan, @customer) do |*args, **|
 275				assert_equal ["test_usd"], args
 276			end
 277			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 278			@customer.expect(:activate_plan_starting_now, EMPromise.resolve(nil), [])
 279			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 280			Registration::Activation::DB.expect(
 281				:exec,
 282				[{ creator_id: "creator" }],
 283				[String, ["test", "123"]]
 284			)
 285			Registration::Activation::Finish.expect(
 286				:new,
 287				OpenStruct.new(write: EMPromise.reject(:test_result)),
 288				[@customer, @tel]
 289			)
 290			assert_equal(
 291				:test_result,
 292				execute_command { @activation.write.catch { |e| e } }
 293			)
 294			assert_mock Command::COMMAND_MANAGER
 295			assert_mock @customer
 296			assert_mock Registration::Activation::Payment
 297			assert_mock Registration::Activation::DB
 298		end
 299		em :test_write_with_code
 300
 301		def test_write_with_group_code
 302			Command::COMMAND_MANAGER.expect(
 303				:write,
 304				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 305					iq.form.fields = [
 306						{ var: "plan_name", value: "test_usd" },
 307						{ var: "code", value: "123" }
 308					]
 309				}),
 310				[Matching.new do |iq|
 311					assert_equal :form, iq.form.type
 312					assert_equal(
 313						"You've selected (555) 555-0000 as your JMP number.",
 314						iq.form.instructions.lines.first.chomp
 315					)
 316				end]
 317			)
 318			@customer.expect(:with_plan, @customer) do |*args, **|
 319				assert_equal ["test_usd"], args
 320			end
 321			@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 322			Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
 323			Registration::Activation::DB.expect(
 324				:exec,
 325				OpenStruct.new(cmd_tuples: 0),
 326				[String, ["test", "123"]]
 327			)
 328			Registration::Activation::Payment.expect(
 329				:for,
 330				EMPromise.reject(:test_result),
 331				[Blather::Stanza::Iq, @customer, @tel]
 332			)
 333			assert_equal(
 334				:test_result,
 335				execute_command { @activation.write.catch { |e| e } }
 336			)
 337			assert_equal(
 338				"123",
 339				Registration::Activation::REDIS.get(
 340					"jmp_customer_pending_invite-test"
 341				).sync
 342			)
 343			assert_mock Command::COMMAND_MANAGER
 344			assert_mock @customer
 345			assert_mock Registration::Activation::Payment
 346			assert_mock Registration::Activation::DB
 347		end
 348		em :test_write_with_group_code
 349
 350		def test_write_with_parent_code
 351			execute_command do
 352				Command::COMMAND_MANAGER.expect(
 353					:write,
 354					EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 355						iq.form.fields = [
 356							{ var: "plan_name", value: "test_usd" },
 357							{ var: "code", value: "PARENT_CODE" }
 358						]
 359					}),
 360					[Matching.new do |iq|
 361						assert_equal :form, iq.form.type
 362						assert_equal(
 363							"You've selected (555) 555-0000 as your JMP number.",
 364							iq.form.instructions.lines.first.chomp
 365						)
 366					end]
 367				)
 368				Registration::Activation::DB.expect(
 369					:query_one, {}, [String, "1"], default: {}
 370				)
 371				Registration::Activation::DB.expect(
 372					:query_one, { c: 0 }, [String, "1"], default: { c: 0 }
 373				)
 374				@customer.expect(:with_plan, @customer) do |*args, **|
 375					assert_equal ["test_usd"], args
 376				end
 377				@customer.expect(:with_plan, @customer) do |*, **kwargs|
 378					assert_equal({ parent_customer_id: "1" }, kwargs)
 379				end
 380				@customer.expect(:save_plan!, EMPromise.resolve(nil), [])
 381				@customer.expect(:balance, 100, [])
 382				Command.execution.customer_repo.expect(
 383					:find,
 384					EMPromise.resolve(@customer), ["test"]
 385				)
 386				Registration::Payment::MaybeBill::BillPlan.expect(
 387					:new,
 388					EMPromise.reject(:test_result)
 389				) do |*args, **|
 390					assert_equal @tel, args[1]
 391				end
 392				assert_equal(
 393					:test_result,
 394					@activation.write.catch { |e| e }.sync
 395				)
 396			end
 397			assert_mock Command::COMMAND_MANAGER
 398			assert_mock @customer
 399			assert_mock Registration::Activation::Payment
 400			assert_mock Registration::Activation::DB
 401			assert_mock Registration::Payment::MaybeBill::BillPlan
 402		end
 403		em :test_write_with_parent_code
 404
 405		def test_write_with_parent_code_onboarding_jid
 406			Command::COMMAND_MANAGER.expect(
 407				:write,
 408				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 409					iq.form.fields = [
 410						{ var: "plan_name", value: "test_usd" },
 411						{ var: "code", value: "PARENT_CODE" }
 412					]
 413				}),
 414				[Matching.new do |iq|
 415					assert_equal :form, iq.form.type
 416					assert_equal(
 417						"You've selected (555) 555-0000 as your JMP number.",
 418						iq.form.instructions.lines.first.chomp
 419					)
 420				end]
 421			)
 422			Registration::Activation::DB.expect(
 423				:query_one, {}, [String, "1"], default: {}
 424			)
 425			Registration::Activation::DB.expect(
 426				:query_one, { c: 0 }, [String, "1"], default: { c: 0 }
 427			)
 428			@customer.expect(:with_plan, @customer, ["test_usd"])
 429			@customer.expect(
 430				:jid,
 431				Blather::JID.new("test\\40onboarding.example.com@proxy")
 432			)
 433			iq = Blather::Stanza::Iq::Command.new
 434			iq.from = "test\\40onboarding.example.com@proxied"
 435			assert_equal(
 436				"Please create a new Jabber ID before creating a subaccount.",
 437				execute_command(iq) { @activation.write.catch(&:to_s) }
 438			)
 439			assert_mock Command::COMMAND_MANAGER
 440			assert_mock @customer
 441			assert_mock Registration::Activation::Payment
 442			assert_mock Registration::Activation::DB
 443		end
 444		em :test_write_with_parent_code_onboarding_jid
 445
 446		def test_write_with_parent_code_tombed_parent
 447			Command::COMMAND_MANAGER.expect(
 448				:write,
 449				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 450					iq.form.fields = [
 451						{ var: "plan_name", value: "test_usd" },
 452						{ var: "code", value: "PARENT_TOMB" }
 453					]
 454				}),
 455				[Matching.new do |iq|
 456					assert_equal :form, iq.form.type
 457					assert_equal(
 458						"You've selected (555) 555-0000 as your JMP number.",
 459						iq.form.instructions.lines.first.chomp
 460					)
 461				end]
 462			)
 463			Registration::Activation::DB.expect(
 464				:query_one, {}, [String, "2"], default: {}
 465			)
 466			Registration::Activation::DB.expect(
 467				:query_one, { c: 0 }, [String, "2"], default: { c: 0 }
 468			)
 469			assert_equal(
 470				"Please contact support to create a subaccount",
 471				execute_command { @activation.write.catch(&:to_s) }
 472			)
 473			assert_mock Command::COMMAND_MANAGER
 474			assert_mock @customer
 475			assert_mock Registration::Activation::Payment
 476			assert_mock Registration::Activation::DB
 477		end
 478		em :test_write_with_parent_code_tombed_parent
 479
 480		def test_write_with_parent_code_too_many
 481			Command::COMMAND_MANAGER.expect(
 482				:write,
 483				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 484					iq.form.fields = [
 485						{ var: "plan_name", value: "test_usd" },
 486						{ var: "code", value: "PARENT_MANY_SUBACCOUNTS" }
 487					]
 488				}),
 489				[Matching.new do |iq|
 490					assert_equal :form, iq.form.type
 491					assert_equal(
 492						"You've selected (555) 555-0000 as your JMP number.",
 493						iq.form.instructions.lines.first.chomp
 494					)
 495				end]
 496			)
 497			Registration::Activation::DB.expect(
 498				:query_one, {}, [String, "many_subaccounts"], default: {}
 499			)
 500			Registration::Activation::DB.expect(
 501				:query_one, { c: 2 }, [String, "many_subaccounts"], default: { c: 0 }
 502			)
 503			assert_equal(
 504				"Please contact support to create a subaccount",
 505				execute_command { @activation.write.catch(&:to_s) }
 506			)
 507			assert_mock Command::COMMAND_MANAGER
 508			assert_mock @customer
 509			assert_mock Registration::Activation::Payment
 510			assert_mock Registration::Activation::DB
 511		end
 512		em :test_write_with_parent_code_too_many
 513	end
 514
 515	class AllowTest < Minitest::Test
 516		Command::COMMAND_MANAGER = Minitest::Mock.new
 517		Registration::Activation::Allow::DB = Minitest::Mock.new
 518
 519		def test_write_credit_to_nil
 520			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 521			cust = Minitest::Mock.new(customer("test"))
 522			allow = Registration::Activation::Allow.new(cust, tel, nil)
 523
 524			Command::COMMAND_MANAGER.expect(
 525				:write,
 526				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 527					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 528				}),
 529				[Matching.new do |iq|
 530					assert_equal :form, iq.form.type
 531					assert_equal(
 532						"You've selected (555) 555-0000 as your JMP number.",
 533						iq.form.instructions.lines.first.chomp
 534					)
 535					assert_equal 1, iq.form.fields.length
 536				end]
 537			)
 538			Registration::Activation::Allow::DB.expect(
 539				:transaction,
 540				EMPromise.reject(:test_result)
 541			) do |&blk|
 542				blk.call
 543				true
 544			end
 545			cust.expect(:with_plan, cust, ["test_usd"])
 546			cust.expect(:activate_plan_starting_now, nil)
 547			assert_equal(
 548				:test_result,
 549				execute_command { allow.write.catch { |e| e } }
 550			)
 551			assert_mock Command::COMMAND_MANAGER
 552		end
 553		em :test_write_credit_to_nil
 554
 555		def test_write_credit_to_refercust
 556			cust = Minitest::Mock.new(customer("test"))
 557			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 558			allow = Registration::Activation::Allow.new(
 559				cust, tel, "refercust"
 560			)
 561
 562			Command::COMMAND_MANAGER.expect(
 563				:write,
 564				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 565					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 566				}),
 567				[Matching.new do |iq|
 568					assert_equal :form, iq.form.type
 569					assert_equal(
 570						"You've selected (555) 555-0000 as your JMP number.",
 571						iq.form.instructions.lines.first.chomp
 572					)
 573					assert_equal 1, iq.form.fields.length
 574				end]
 575			)
 576			Registration::Activation::Allow::DB.expect(
 577				:transaction,
 578				EMPromise.reject(:test_result)
 579			) do |&blk|
 580				blk.call
 581				true
 582			end
 583			Registration::Activation::Allow::DB.expect(
 584				:exec,
 585				nil,
 586				[String, ["refercust", "test"]]
 587			)
 588			cust.expect(:with_plan, cust, ["test_usd"])
 589			cust.expect(:activate_plan_starting_now, nil)
 590			assert_equal(
 591				:test_result,
 592				execute_command { allow.write.catch { |e| e } }
 593			)
 594			assert_mock Command::COMMAND_MANAGER
 595		end
 596		em :test_write_credit_to_refercust
 597	end
 598
 599	class GooglePlayTest < Minitest::Test
 600		CustomerPlan::DB = Minitest::Mock.new
 601		Registration::Activation::GooglePlay::Finish = Minitest::Mock.new
 602
 603		def setup
 604			@customer = customer
 605			@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 606			@google_play = Registration::Activation::GooglePlay.new(
 607				@customer,
 608				"abcd",
 609				@tel
 610			)
 611		end
 612
 613		def test_write
 614			Command::COMMAND_MANAGER.expect(
 615				:write,
 616				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 617					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 618				}),
 619				[Matching.new do |iq|
 620					assert_equal :form, iq.form.type
 621					assert_equal(
 622						"You've selected (555) 555-0000 as your JMP number.",
 623						iq.form.instructions.lines.first.chomp
 624					)
 625				end]
 626			)
 627			CustomerPlan::DB.expect(
 628				:exec,
 629				OpenStruct.new(cmd_tuples: 1),
 630				[String, ["test", "test_usd", nil]]
 631			)
 632			CustomerPlan::DB.expect(
 633				:exec,
 634				OpenStruct.new(cmd_tuples: 0),
 635				[String, ["test"]]
 636			)
 637			Transaction::DB.expect(:transaction, true, [])
 638			Registration::Activation::GooglePlay::Finish.expect(
 639				:new,
 640				OpenStruct.new(write: EMPromise.reject(:test_result)),
 641				[Customer, @tel]
 642			)
 643			result = execute_command { @google_play.write.catch { |e| e } }
 644			assert_equal :test_result, result
 645			assert_mock Command::COMMAND_MANAGER
 646			assert_mock CustomerPlan::DB
 647			assert_mock Transaction::DB
 648			assert_mock Registration::Activation::GooglePlay::Finish
 649		end
 650		em :test_write
 651	end
 652
 653	class PaymentTest < Minitest::Test
 654		CustomerFinancials::BRAINTREE = Minitest::Mock.new
 655
 656		def test_for_bitcoin
 657			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 658			iq = Blather::Stanza::Iq::Command.new
 659			iq.form.fields = [
 660				{ var: "activation_method", value: "bitcoin" },
 661				{ var: "plan_name", value: "test_usd" }
 662			]
 663			result = Registration::Payment.for(iq, customer, tel)
 664			assert_kind_of Registration::Payment::Bitcoin, result
 665		end
 666
 667		def test_for_bch
 668			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 669			iq = Blather::Stanza::Iq::Command.new
 670			iq.form.fields = [
 671				{ var: "activation_method", value: "bch" },
 672				{ var: "plan_name", value: "test_usd" }
 673			]
 674			result = Registration::Payment.for(iq, customer, tel)
 675			assert_kind_of Registration::Payment::BCH, result
 676		end
 677
 678		def test_for_credit_card
 679			tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 680			iq = Blather::Stanza::Iq::Command.new
 681			iq.from = "test@example.com"
 682			iq.form.fields = [
 683				{ var: "activation_method", value: "credit_card" },
 684				{ var: "plan_name", value: "test_usd" }
 685			]
 686			cust = customer
 687			result = execute_command do
 688				Command.execution.customer_repo.expect(:find, cust, ["test"])
 689				Registration::Payment.for(
 690					iq,
 691					cust,
 692					tel
 693				)
 694			end
 695			assert_kind_of Registration::Payment::CreditCard, result
 696		end
 697		em :test_for_credit_card
 698
 699		def test_for_code
 700			iq = Blather::Stanza::Iq::Command.new
 701			iq.form.fields = [
 702				{ var: "activation_method", value: "code" },
 703				{ var: "plan_name", value: "test_usd" }
 704			]
 705			cust = customer
 706			result = execute_command do
 707				Command.execution.customer_repo.expect(:find, cust, ["test"])
 708				Registration::Payment.for(
 709					iq,
 710					cust,
 711					TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 712				)
 713			end
 714			assert_kind_of Registration::Payment::InviteCode, result
 715		end
 716		em :test_for_code
 717
 718		class BitcoinTest < Minitest::Test
 719			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
 720			CustomerFinancials::REDIS = Minitest::Mock.new
 721
 722			def setup
 723				@customer = Minitest::Mock.new(
 724					customer(plan_name: "test_usd")
 725				)
 726				@customer.expect(
 727					:add_btc_address,
 728					EMPromise.resolve("testaddr")
 729				)
 730				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 731				@bitcoin = Registration::Payment::Bitcoin.new(
 732					@customer,
 733					@tel
 734				)
 735			end
 736
 737			def test_write
 738				CustomerFinancials::REDIS.expect(
 739					:smembers,
 740					EMPromise.resolve([]),
 741					["jmp_customer_btc_addresses-test"]
 742				)
 743				blather = Minitest::Mock.new
 744				Command::COMMAND_MANAGER.expect(
 745					:write,
 746					EMPromise.reject(SessionManager::Timeout.new),
 747					[Matching.new do |reply|
 748						assert_equal :canceled, reply.status
 749						assert_equal "1.000000", reply.form.field("amount").value
 750						assert_equal "testaddr", reply.form.field("btc_addresses").value
 751						true
 752					end]
 753				)
 754				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
 755					:usd,
 756					EMPromise.resolve(BigDecimal(1))
 757				)
 758				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
 759					execute_command(blather: blather) do
 760						@bitcoin.write
 761					end
 762				end
 763				assert_mock blather
 764			end
 765			em :test_write
 766		end
 767
 768		class BCHTest < Minitest::Test
 769			Registration::Payment::BCH::BCH_SELL_PRICES = Minitest::Mock.new
 770			CustomerFinancials::REDIS = Minitest::Mock.new
 771
 772			def setup
 773				@customer = Minitest::Mock.new(
 774					customer(plan_name: "test_usd")
 775				)
 776				@customer.expect(
 777					:add_bch_address,
 778					EMPromise.resolve("testaddr")
 779				)
 780				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 781				@bch = Registration::Payment::BCH.new(
 782					@customer,
 783					@tel
 784				)
 785			end
 786
 787			def test_write
 788				CustomerFinancials::REDIS.expect(
 789					:smembers,
 790					EMPromise.resolve([]),
 791					["jmp_customer_bch_addresses-test"]
 792				)
 793				blather = Minitest::Mock.new
 794				Command::COMMAND_MANAGER.expect(
 795					:write,
 796					EMPromise.reject(SessionManager::Timeout.new),
 797					[Matching.new do |reply|
 798						assert_equal :canceled, reply.status
 799						assert_equal "1.000000", reply.form.field("amount").value
 800						assert_equal "testaddr", reply.form.field("bch_addresses").value
 801						true
 802					end]
 803				)
 804				Registration::Payment::BCH::BCH_SELL_PRICES.expect(
 805					:usd,
 806					EMPromise.resolve(BigDecimal(1))
 807				)
 808				@bch.stub(:save, EMPromise.resolve(nil)) do
 809					execute_command(blather: blather) do
 810						@bch.write
 811					end
 812				end
 813				assert_mock blather
 814			end
 815			em :test_write
 816		end
 817
 818		class CreditCardTest < Minitest::Test
 819			def setup
 820				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 821				@credit_card = Registration::Payment::CreditCard.new(
 822					customer,
 823					@tel
 824				)
 825			end
 826
 827			def test_new
 828				tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 829				cust = Minitest::Mock.new(customer)
 830				cust.expect(
 831					:payment_methods,
 832					EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
 833				)
 834				execute_command do
 835					Command.execution.customer_repo.expect(:find, cust, ["test"])
 836					assert_kind_of(
 837						Registration::Payment::CreditCard,
 838						Registration::Payment::CreditCard.new(cust, tel)
 839					)
 840				end
 841			end
 842			em :test_new
 843
 844			def test_write
 845				result = execute_command do
 846					Command::COMMAND_MANAGER.expect(
 847						:write,
 848						EMPromise.reject(:test_result),
 849						[Matching.new do |reply|
 850							assert_equal [:execute, :next, :prev], reply.allowed_actions
 851							assert_equal(
 852								"Pay by credit card, save, then next here to continue: " \
 853								"http://creditcard.example.com?&amount=1",
 854								reply.note.content
 855							)
 856						end]
 857					)
 858
 859					@credit_card.write.catch { |e| e }
 860				end
 861
 862				assert_equal :test_result, result
 863			end
 864			em :test_write
 865		end
 866
 867		class MailTest < Minitest::Test
 868			def setup
 869				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 870				@mail = Registration::Payment::Mail.new(
 871					customer(plan_name: "test_cad"),
 872					@tel
 873				)
 874			end
 875
 876			def test_write
 877				result = execute_command do
 878					Command::COMMAND_MANAGER.expect(
 879						:write,
 880						EMPromise.reject(:test_result),
 881						[Matching.new do |reply|
 882							assert_equal [:execute, :prev], reply.allowed_actions
 883							refute reply.form.instructions.empty?
 884							assert_equal(
 885								"A Mailing Address",
 886								reply.form.field("adr").value
 887							)
 888							assert_equal(
 889								"interac@example.com",
 890								reply.form.field("interac_email").value
 891							)
 892						end]
 893					)
 894
 895					@mail.write.catch { |e| e }
 896				end
 897
 898				assert_equal :test_result, result
 899			end
 900			em :test_write
 901		end
 902
 903		class InviteCodeTest < Minitest::Test
 904			Registration::Payment::InviteCode::DB =
 905				Minitest::Mock.new
 906			Registration::Payment::InviteCode::REDIS =
 907				Minitest::Mock.new
 908			Command::COMMAND_MANAGER = Minitest::Mock.new
 909			Registration::Payment::InviteCode::Finish =
 910				Minitest::Mock.new
 911			Registration::Payment::MaybeBill::BillPlan =
 912				Minitest::Mock.new
 913
 914			def setup
 915				@tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
 916			end
 917
 918			def test_write
 919				customer = customer(plan_name: "test_usd")
 920				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 921				Registration::Payment::InviteCode::Finish.expect(
 922					:new,
 923					OpenStruct.new(write: nil),
 924					[
 925						customer,
 926						@tel
 927					]
 928				)
 929				execute_command do
 930					Registration::Payment::InviteCode::REDIS.expect(
 931						:get,
 932						EMPromise.resolve(nil),
 933						["jmp_invite_tries-test"]
 934					)
 935					Registration::Payment::InviteCode::REDIS.expect(
 936						:hget,
 937						EMPromise.resolve(nil),
 938						["jmp_parent_codes", "abc"]
 939					)
 940					Command::COMMAND_MANAGER.expect(
 941						:write,
 942						EMPromise.resolve(
 943							Blather::Stanza::Iq::Command.new.tap { |iq|
 944								iq.form.fields = [{ var: "code", value: "abc" }]
 945							}
 946						),
 947						[Matching.new do |reply|
 948							assert_equal :form, reply.form.type
 949							assert_nil reply.form.instructions
 950						end]
 951					)
 952
 953					Registration::Payment::InviteCode.new(
 954						customer,
 955						@tel
 956					).write
 957				end
 958				assert_mock Command::COMMAND_MANAGER
 959				assert_mock Registration::Payment::InviteCode::DB
 960				assert_mock Registration::Payment::InviteCode::REDIS
 961				assert_mock Registration::Payment::InviteCode::Finish
 962			end
 963			em :test_write
 964
 965			def test_write_parent_code
 966				customer = customer(plan_name: "test_usd")
 967				Registration::Payment::MaybeBill::BillPlan.expect(
 968					:new,
 969					OpenStruct.new(write: nil)
 970				) { |*| true }
 971				Registration::Payment::InviteCode::DB.expect(
 972					:query_one, {}, [String, "parent_customer"], default: {}
 973				)
 974				Registration::Payment::InviteCode::DB.expect(
 975					:query_one, { c: 0 }, [String, "parent_customer"], default: { c: 0 }
 976				)
 977				execute_command do
 978					Registration::Payment::InviteCode::REDIS.expect(
 979						:hget,
 980						EMPromise.resolve("parent_customer"),
 981						["jmp_parent_codes", "pabc"]
 982					)
 983					Registration::Payment::InviteCode::REDIS.expect(
 984						:get,
 985						EMPromise.resolve(nil),
 986						["jmp_customer_trust_level-parent_customer"]
 987					)
 988					CustomerPlan::DB.expect(
 989						:query,
 990						[{ "plan_name" => "test_usd" }],
 991						[String, ["parent_customer"]]
 992					)
 993					CustomerPlan::DB.expect(
 994						:exec_defer,
 995						EMPromise.resolve(nil),
 996						[String, ["test", "test_usd", "parent_customer"]]
 997					)
 998					Command.execution.customer_repo.expect(
 999						:find,
1000						customer.with_balance(10000),
1001						["test"]
1002					)
1003					Command::COMMAND_MANAGER.expect(
1004						:write,
1005						EMPromise.resolve(
1006							Blather::Stanza::Iq::Command.new.tap { |iq|
1007								iq.form.fields = [{ var: "code", value: "pabc" }]
1008							}
1009						),
1010						[Matching.new do |reply|
1011							assert_equal :form, reply.form.type
1012							assert_nil reply.form.instructions
1013						end]
1014					)
1015
1016					Registration::Payment::InviteCode.new(
1017						customer,
1018						@tel
1019					).write
1020				end
1021				assert_mock Command::COMMAND_MANAGER
1022				assert_mock Registration::Payment::InviteCode::DB
1023				assert_mock Registration::Payment::InviteCode::REDIS
1024				assert_mock Registration::Payment::MaybeBill::BillPlan
1025			end
1026			em :test_write_parent_code
1027
1028			def test_write_bad_code
1029				result = execute_command do
1030					customer = customer(plan_name: "test_usd")
1031					Registration::Payment::InviteCode::REDIS.expect(
1032						:set,
1033						EMPromise.resolve(nil),
1034						["jmp_customer_pending_invite-test", "abc"]
1035					)
1036					Registration::Payment::InviteCode::REDIS.expect(
1037						:get,
1038						EMPromise.resolve(0),
1039						["jmp_invite_tries-test"]
1040					)
1041					Registration::Payment::InviteCode::REDIS.expect(
1042						:hget,
1043						EMPromise.resolve(nil),
1044						["jmp_parent_codes", "abc"]
1045					)
1046					Registration::Payment::InviteCode::DB.expect(
1047						:transaction,
1048						[]
1049					) { |&blk| blk.call }
1050					Registration::Payment::InviteCode::DB.expect(
1051						:exec,
1052						OpenStruct.new(cmd_tuples: 0),
1053						[String, ["test", "abc"]]
1054					)
1055					Registration::Payment::InviteCode::REDIS.expect(
1056						:incr,
1057						EMPromise.resolve(nil),
1058						["jmp_invite_tries-test"]
1059					)
1060					Registration::Payment::InviteCode::REDIS.expect(
1061						:expire,
1062						EMPromise.resolve(nil),
1063						["jmp_invite_tries-test", 60 * 60]
1064					)
1065					Registration::Payment::InviteCode::REDIS.expect(
1066						:hexists,
1067						EMPromise.resolve(0),
1068						["jmp_group_codes", "abc"]
1069					)
1070					Command::COMMAND_MANAGER.expect(
1071						:write,
1072						EMPromise.resolve(
1073							Blather::Stanza::Iq::Command.new.tap { |iq|
1074								iq.form.fields = [{ var: "code", value: "abc" }]
1075							}
1076						),
1077						[Matching.new do |reply|
1078							assert_equal :form, reply.form.type
1079							assert_nil reply.form.instructions
1080						end]
1081					)
1082					Command::COMMAND_MANAGER.expect(
1083						:write,
1084						EMPromise.reject(:test_result),
1085						[Matching.new do |reply|
1086							assert_equal :form, reply.form.type
1087							assert_equal(
1088								"Not a valid invite code: abc",
1089								reply.form.instructions
1090							)
1091						end]
1092					)
1093
1094					Registration::Payment::InviteCode.new(
1095						customer,
1096						@tel
1097					).write.catch { |e| e }
1098				end
1099				assert_equal :test_result, result
1100				assert_mock Command::COMMAND_MANAGER
1101				assert_mock Registration::Payment::InviteCode::DB
1102				assert_mock Registration::Payment::InviteCode::REDIS
1103			end
1104			em :test_write_bad_code
1105
1106			def test_write_group_code
1107				result = execute_command do
1108					customer = customer(plan_name: "test_usd")
1109					Registration::Payment::InviteCode::REDIS.expect(
1110						:set,
1111						EMPromise.resolve(nil),
1112						["jmp_customer_pending_invite-test", "abc"]
1113					)
1114					Registration::Payment::InviteCode::REDIS.expect(
1115						:get,
1116						EMPromise.resolve(0),
1117						["jmp_invite_tries-test"]
1118					)
1119					Registration::Payment::InviteCode::REDIS.expect(
1120						:hget,
1121						EMPromise.resolve(nil),
1122						["jmp_parent_codes", "abc"]
1123					)
1124					Registration::Payment::InviteCode::DB.expect(
1125						:transaction,
1126						[]
1127					) { |&blk| blk.call }
1128					Registration::Payment::InviteCode::DB.expect(
1129						:exec,
1130						OpenStruct.new(cmd_tuples: 0),
1131						[String, ["test", "abc"]]
1132					)
1133					Registration::Payment::InviteCode::REDIS.expect(
1134						:incr,
1135						EMPromise.resolve(nil),
1136						["jmp_invite_tries-test"]
1137					)
1138					Registration::Payment::InviteCode::REDIS.expect(
1139						:expire,
1140						EMPromise.resolve(nil),
1141						["jmp_invite_tries-test", 60 * 60]
1142					)
1143					Registration::Payment::InviteCode::REDIS.expect(
1144						:hexists,
1145						EMPromise.resolve(1),
1146						["jmp_group_codes", "abc"]
1147					)
1148					Command::COMMAND_MANAGER.expect(
1149						:write,
1150						EMPromise.resolve(
1151							Blather::Stanza::Iq::Command.new.tap { |iq|
1152								iq.form.fields = [{ var: "code", value: "abc" }]
1153							}
1154						),
1155						[Matching.new do |reply|
1156							assert_equal :form, reply.form.type
1157							assert_nil reply.form.instructions
1158						end]
1159					)
1160					Command::COMMAND_MANAGER.expect(
1161						:write,
1162						EMPromise.reject(:test_result),
1163						[Matching.new do |reply|
1164							assert_equal :form, reply.form.type
1165							assert_equal(
1166								"abc is a post-payment referral",
1167								reply.form.instructions
1168							)
1169						end]
1170					)
1171
1172					Registration::Payment::InviteCode.new(
1173						customer,
1174						@tel
1175					).write.catch { |e| e }
1176				end
1177				assert_equal :test_result, result
1178				assert_mock Command::COMMAND_MANAGER
1179				assert_mock Registration::Payment::InviteCode::DB
1180				assert_mock Registration::Payment::InviteCode::REDIS
1181			end
1182			em :test_write_group_code
1183
1184			def test_write_bad_code_over_limit
1185				result = execute_command do
1186					customer = customer(plan_name: "test_usd")
1187					Registration::Payment::InviteCode::REDIS.expect(
1188						:get,
1189						EMPromise.resolve(11),
1190						["jmp_invite_tries-test"]
1191					)
1192					Registration::Payment::InviteCode::REDIS.expect(
1193						:hget,
1194						EMPromise.resolve(nil),
1195						["jmp_parent_codes", "abc"]
1196					)
1197					Command::COMMAND_MANAGER.expect(
1198						:write,
1199						EMPromise.resolve(
1200							Blather::Stanza::Iq::Command.new.tap { |iq|
1201								iq.form.fields = [{ var: "code", value: "abc" }]
1202							}
1203						),
1204						[Matching.new do |reply|
1205							assert_equal :form, reply.form.type
1206							assert_nil reply.form.instructions
1207						end]
1208					)
1209					Command::COMMAND_MANAGER.expect(
1210						:write,
1211						EMPromise.reject(:test_result),
1212						[Matching.new do |reply|
1213							assert_equal :form, reply.form.type
1214							assert_equal "Too many wrong attempts", reply.form.instructions
1215						end]
1216					)
1217					Registration::Payment::InviteCode.new(
1218						customer,
1219						@tel
1220					).write.catch { |e| e }
1221				end
1222				assert_equal :test_result, result
1223				assert_mock Command::COMMAND_MANAGER
1224				assert_mock Registration::Payment::InviteCode::REDIS
1225			end
1226			em :test_write_bad_code_over_limit
1227		end
1228	end
1229
1230	class FinishTest < Minitest::Test
1231		Customer::BLATHER = Minitest::Mock.new
1232		Command::COMMAND_MANAGER = Minitest::Mock.new
1233		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
1234		Registration::Finish::REDIS = Minitest::Mock.new
1235		Registration::Finish::DB = Minitest::Mock.new
1236		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
1237		Registration::FinishOnboarding::DB = FakeDB.new
1238		Transaction::DB = Minitest::Mock.new
1239
1240		def setup
1241			@sgx = Minitest::Mock.new(mksgx)
1242			iq = Blather::Stanza::Iq::Command.new
1243			iq.from = "test\\40example.com@cheogram.com"
1244			@finish = Registration::Finish.new(
1245				customer(sgx: @sgx, plan_name: "test_usd"),
1246				TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1247			)
1248		end
1249
1250		def test_write
1251			create_order = stub_request(
1252				:post,
1253				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1254			).to_return(status: 201, body: <<~RESPONSE)
1255				<OrderResponse>
1256					<Order>
1257						<id>test_order</id>
1258					</Order>
1259				</OrderResponse>
1260			RESPONSE
1261			stub_request(
1262				:get,
1263				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1264			).to_return(status: 201, body: <<~RESPONSE)
1265				<OrderResponse>
1266					<OrderStatus>COMPLETE</OrderStatus>
1267					<CompletedNumbers>
1268						<TelephoneNumber>
1269							<FullNumber>5555550000</FullNumber>
1270						</TelephoneNumber>
1271					</CompletedNumbers>
1272				</OrderResponse>
1273			RESPONSE
1274			stub_request(
1275				:post,
1276				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1277			)
1278			Registration::Finish::REDIS.expect(
1279				:get,
1280				nil,
1281				["jmp_customer_pending_invite-test"]
1282			)
1283			Registration::Finish::REDIS.expect(
1284				:del,
1285				nil,
1286				["jmp_customer_pending_invite-test"]
1287			)
1288			Registration::Finish::REDIS.expect(
1289				:hget,
1290				nil,
1291				["jmp_group_codes", nil]
1292			)
1293			Bwmsgsv2Repo::REDIS.expect(
1294				:get,
1295				EMPromise.resolve(nil),
1296				["jmp_customer_backend_sgx-test"]
1297			)
1298			Bwmsgsv2Repo::REDIS.expect(
1299				:set,
1300				nil,
1301				[
1302					"catapult_fwd-+15555550000",
1303					"xmpp:test@example.net"
1304				]
1305			)
1306			Bwmsgsv2Repo::REDIS.expect(
1307				:set,
1308				nil,
1309				["catapult_fwd_timeout-customer_test@component", 25]
1310			)
1311			Customer::BLATHER.expect(
1312				:<<,
1313				nil,
1314				[Matching.new do |m|
1315					assert_equal :chat, m.type
1316					assert m.body =~ /^Welcome to JMP/
1317				end]
1318			)
1319			blather = Minitest::Mock.new
1320			blather.expect(
1321				:<<,
1322				nil,
1323				[Matching.new do |reply|
1324					assert_equal :completed, reply.status
1325					assert_equal :info, reply.note_type
1326					assert_equal(
1327						"Your JMP account has been activated as (555) 555-0000",
1328						reply.note.content
1329					)
1330				end]
1331			)
1332			execute_command(blather: blather) do
1333				@sgx.expect(
1334					:register!,
1335					EMPromise.resolve(@sgx.with(
1336						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1337							ibr.phone = "+15555550000"
1338						end
1339					)),
1340					["+15555550000"]
1341				)
1342
1343				@finish.write
1344			end
1345			assert_requested create_order
1346			assert_mock @sgx
1347			assert_mock Registration::Finish::REDIS
1348			assert_mock Bwmsgsv2Repo::REDIS
1349			assert_mock Customer::BLATHER
1350			assert_mock blather
1351		end
1352		em :test_write
1353
1354		def test_write_with_pending_code
1355			create_order = stub_request(
1356				:post,
1357				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1358			).to_return(status: 201, body: <<~RESPONSE)
1359				<OrderResponse>
1360					<Order>
1361						<id>test_order</id>
1362					</Order>
1363				</OrderResponse>
1364			RESPONSE
1365			stub_request(
1366				:get,
1367				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1368			).to_return(status: 201, body: <<~RESPONSE)
1369				<OrderResponse>
1370					<OrderStatus>COMPLETE</OrderStatus>
1371					<CompletedNumbers>
1372						<TelephoneNumber>
1373							<FullNumber>5555550000</FullNumber>
1374						</TelephoneNumber>
1375					</CompletedNumbers>
1376				</OrderResponse>
1377			RESPONSE
1378			stub_request(
1379				:post,
1380				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1381			)
1382			Registration::Finish::REDIS.expect(
1383				:get,
1384				EMPromise.resolve("123"),
1385				["jmp_customer_pending_invite-test"]
1386			)
1387			Registration::Finish::REDIS.expect(
1388				:del,
1389				nil,
1390				["jmp_customer_pending_invite-test"]
1391			)
1392			Registration::Finish::REDIS.expect(
1393				:hget,
1394				EMPromise.resolve("test-inviter"),
1395				["jmp_group_codes", "123"]
1396			)
1397			Registration::Finish::DB.expect(
1398				:exec,
1399				EMPromise.resolve(nil),
1400				[String, ["test-inviter", "test"]]
1401			)
1402			Transaction::DB.expect(:transaction, nil) do |&blk|
1403				blk.call
1404				true
1405			end
1406			Transaction::DB.expect(
1407				:exec,
1408				nil,
1409				[String, Matching.new { |params|
1410					assert_equal "test", params[0]
1411					assert params[1].start_with?("referral_")
1412					assert_equal 1, params[4]
1413					assert_equal "Referral Bonus", params[5]
1414				}]
1415			)
1416			Bwmsgsv2Repo::REDIS.expect(
1417				:get,
1418				EMPromise.resolve(nil),
1419				["jmp_customer_backend_sgx-test"]
1420			)
1421			Bwmsgsv2Repo::REDIS.expect(
1422				:set,
1423				nil,
1424				[
1425					"catapult_fwd-+15555550000",
1426					"xmpp:test@example.net"
1427				]
1428			)
1429			Bwmsgsv2Repo::REDIS.expect(
1430				:set,
1431				nil,
1432				["catapult_fwd_timeout-customer_test@component", 25]
1433			)
1434			Customer::BLATHER.expect(
1435				:<<,
1436				nil,
1437				[Matching.new do |m|
1438					assert_equal :chat, m.type
1439					assert m.body =~ /^Welcome to JMP/
1440				end]
1441			)
1442			blather = Minitest::Mock.new
1443			blather.expect(
1444				:<<,
1445				nil,
1446				[Matching.new do |reply|
1447					assert_equal :completed, reply.status
1448					assert_equal :info, reply.note_type
1449					assert_equal(
1450						"Your JMP account has been activated as (555) 555-0000",
1451						reply.note.content
1452					)
1453				end]
1454			)
1455			execute_command(blather: blather) do
1456				@sgx.expect(
1457					:register!,
1458					EMPromise.resolve(@sgx.with(
1459						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1460							ibr.phone = "+15555550000"
1461						end
1462					)),
1463					["+15555550000"]
1464				)
1465
1466				@finish.write
1467			end
1468			assert_requested create_order
1469			assert_mock @sgx
1470			assert_mock Registration::Finish::REDIS
1471			assert_mock Bwmsgsv2Repo::REDIS
1472			assert_mock Customer::BLATHER
1473			assert_mock blather
1474			assert_mock Transaction::DB
1475		end
1476		em :test_write_with_pending_code
1477
1478		def test_write_onboarding
1479			create_order = stub_request(
1480				:post,
1481				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1482			).to_return(status: 201, body: <<~RESPONSE)
1483				<OrderResponse>
1484					<Order>
1485						<id>test_order</id>
1486					</Order>
1487				</OrderResponse>
1488			RESPONSE
1489			stub_request(
1490				:get,
1491				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1492			).to_return(status: 201, body: <<~RESPONSE)
1493				<OrderResponse>
1494					<OrderStatus>COMPLETE</OrderStatus>
1495					<CompletedNumbers>
1496						<TelephoneNumber>
1497							<FullNumber>5555550000</FullNumber>
1498						</TelephoneNumber>
1499					</CompletedNumbers>
1500				</OrderResponse>
1501			RESPONSE
1502			stub_request(
1503				:post,
1504				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
1505			)
1506			Registration::Finish::REDIS.expect(
1507				:get,
1508				nil,
1509				["jmp_customer_pending_invite-test"]
1510			)
1511			Registration::Finish::REDIS.expect(
1512				:del,
1513				nil,
1514				["jmp_customer_pending_invite-test"]
1515			)
1516			Registration::Finish::REDIS.expect(
1517				:hget,
1518				nil,
1519				["jmp_group_codes", nil]
1520			)
1521			Bwmsgsv2Repo::REDIS.expect(
1522				:get,
1523				EMPromise.resolve(nil),
1524				["jmp_customer_backend_sgx-test"]
1525			)
1526			Bwmsgsv2Repo::REDIS.expect(
1527				:set,
1528				nil,
1529				[
1530					"catapult_fwd-+15555550000",
1531					"xmpp:test\\40onboarding.example.com@proxy"
1532				]
1533			)
1534			Bwmsgsv2Repo::REDIS.expect(
1535				:set,
1536				nil,
1537				["catapult_fwd_timeout-customer_test@component", 25]
1538			)
1539			result = execute_command do
1540				@sgx.expect(
1541					:register!,
1542					EMPromise.resolve(@sgx.with(
1543						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1544							ibr.phone = "+15555550000"
1545						end
1546					)),
1547					["+15555550000"]
1548				)
1549
1550				Command::COMMAND_MANAGER.expect(
1551					:write,
1552					EMPromise.reject(:test_result),
1553					[Matching.new do |iq|
1554						assert_equal :form, iq.form.type
1555						assert iq.form.field("subdomain")
1556					end]
1557				)
1558
1559				Registration::Finish.new(
1560					customer(
1561						sgx: @sgx,
1562						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1563					),
1564					TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
1565				).write.catch { |e| e }
1566			end
1567			assert_equal :test_result, result
1568			assert_requested create_order
1569			assert_mock @sgx
1570			assert_mock Registration::Finish::REDIS
1571			assert_mock Bwmsgsv2Repo::REDIS
1572			assert_mock Command::COMMAND_MANAGER
1573		end
1574		em :test_write_onboarding
1575
1576		def test_write_local_inventory
1577			stub_request(
1578				:post,
1579				"https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
1580			).with(
1581				body: {
1582					CustomerOrderId: "test",
1583					SourceAccountId: "bandwidth_account_id",
1584					SiteId: "test_site",
1585					SipPeerId: "test_peer",
1586					TelephoneNumbers: { TelephoneNumber: "5555550000" }
1587				}.to_xml(indent: 0, root: "MoveTnsOrder")
1588			).to_return(status: 200, body: "", headers: {})
1589
1590			Registration::Finish::REDIS.expect(
1591				:get,
1592				nil,
1593				["jmp_customer_pending_invite-test"]
1594			)
1595			Registration::Finish::REDIS.expect(
1596				:del,
1597				nil,
1598				["jmp_customer_pending_invite-test"]
1599			)
1600			Registration::Finish::REDIS.expect(
1601				:hget,
1602				nil,
1603				["jmp_group_codes", nil]
1604			)
1605			Registration::Finish::DB.expect(
1606				:exec_defer,
1607				EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
1608				[String, ["+15555550000"]]
1609			)
1610			Bwmsgsv2Repo::REDIS.expect(
1611				:get,
1612				EMPromise.resolve(nil),
1613				["jmp_customer_backend_sgx-test"]
1614			)
1615			Bwmsgsv2Repo::REDIS.expect(
1616				:set,
1617				nil,
1618				[
1619					"catapult_fwd-+15555550000",
1620					"xmpp:test\\40onboarding.example.com@proxy"
1621				]
1622			)
1623			Bwmsgsv2Repo::REDIS.expect(
1624				:set,
1625				nil,
1626				["catapult_fwd_timeout-customer_test@component", 25]
1627			)
1628			result = execute_command do
1629				@sgx.expect(
1630					:register!,
1631					EMPromise.resolve(@sgx.with(
1632						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1633							ibr.phone = "+15555550000"
1634						end
1635					)),
1636					["+15555550000"]
1637				)
1638
1639				Command::COMMAND_MANAGER.expect(
1640					:write,
1641					EMPromise.reject(:test_result),
1642					[Matching.new do |iq|
1643						assert_equal :form, iq.form.type
1644						assert iq.form.field("subdomain")
1645					end]
1646				)
1647
1648				Registration::Finish.new(
1649					customer(
1650						sgx: @sgx,
1651						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1652					),
1653					TelSelections::ChooseTel::Tn::LocalInventory.new(
1654						TelSelections::ChooseTel::Tn.new("+15555550000"),
1655						"bandwidth_account_id"
1656					)
1657				).write.catch { |e| e }
1658			end
1659			assert_equal :test_result, result
1660			assert_mock @sgx
1661			assert_mock Registration::Finish::REDIS
1662			assert_mock Bwmsgsv2Repo::REDIS
1663			assert_mock Command::COMMAND_MANAGER
1664		end
1665		em :test_write_local_inventory
1666
1667		def test_write_local_inventory_must_pay
1668			low_cust = customer(
1669				sgx: @sgx,
1670				jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1671			).with_balance(5.0)
1672			high_cust = customer(
1673				sgx: @sgx,
1674				jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
1675			).with_balance(100.0)
1676
1677			stub_request(
1678				:post,
1679				"https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
1680			).with(
1681				body: {
1682					CustomerOrderId: "test",
1683					SourceAccountId: "bandwidth_account_id",
1684					SiteId: "test_site",
1685					SipPeerId: "test_peer",
1686					TelephoneNumbers: { TelephoneNumber: "5555550000" }
1687				}.to_xml(indent: 0, root: "MoveTnsOrder")
1688			).to_return(status: 200, body: "", headers: {})
1689
1690			Registration::Finish::REDIS.expect(
1691				:get,
1692				nil,
1693				["jmp_customer_pending_invite-test"]
1694			)
1695			Registration::Finish::REDIS.expect(
1696				:del,
1697				nil,
1698				["jmp_customer_pending_invite-test"]
1699			)
1700			Registration::Finish::REDIS.expect(
1701				:hget,
1702				nil,
1703				["jmp_group_codes", nil]
1704			)
1705			Registration::Finish::DB.expect(
1706				:exec_defer,
1707				EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
1708				[String, ["+15555550000"]]
1709			)
1710			Bwmsgsv2Repo::REDIS.expect(
1711				:get,
1712				EMPromise.resolve(nil),
1713				["jmp_customer_backend_sgx-test"]
1714			)
1715			Bwmsgsv2Repo::REDIS.expect(
1716				:set,
1717				nil,
1718				[
1719					"catapult_fwd-+15555550000",
1720					"xmpp:test\\40onboarding.example.com@proxy"
1721				]
1722			)
1723			Bwmsgsv2Repo::REDIS.expect(
1724				:set,
1725				nil,
1726				["catapult_fwd_timeout-customer_test@component", 25]
1727			)
1728
1729			local_tel = Minitest::Mock.new(
1730				TelSelections::ChooseTel::Tn::LocalInventory.new(
1731					TelSelections::ChooseTel::Tn.new("+15555550000"),
1732					"bandwidth_account_id",
1733					price: 10.0
1734				)
1735			)
1736
1737			result = execute_command do
1738				local_tel.expect(:charge, EMPromise.reject(:test_result), [Customer])
1739				@sgx.expect(
1740					:register!,
1741					EMPromise.resolve(@sgx.with(
1742						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
1743							ibr.phone = "+15555550000"
1744						end
1745					)),
1746					["+15555550000"]
1747				)
1748
1749				Command::COMMAND_MANAGER.expect(
1750					:write,
1751					EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
1752						iq.from = "customer@example.org"
1753						iq.form.fields = [
1754							{ var: "activation_method", value: "credit_card" }
1755						]
1756					}),
1757					[Matching.new do |iq|
1758						assert_equal :form, iq.form.type
1759						assert_equal "Purchase Number", iq.form.title
1760					end]
1761				)
1762
1763				Command.execution.customer_repo.expect(
1764					:find,
1765					EMPromise.resolve(high_cust),
1766					["test"]
1767				)
1768
1769				Command::COMMAND_MANAGER.expect(
1770					:write,
1771					EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
1772						iq.from = "customer@example.org"
1773					}),
1774					[Matching.new do |iq|
1775						assert_equal(
1776							"Pay by credit card, save, then next here to continue: " \
1777							"http://creditcard.example.com?&amount=10",
1778							iq.note.text
1779						)
1780					end]
1781				)
1782
1783				Registration::Finish.new(
1784					low_cust,
1785					local_tel
1786				).write.catch { |e| e }
1787			end
1788
1789			assert_equal :test_result, result
1790			assert_mock @sgx
1791			assert_mock Registration::Finish::REDIS
1792			assert_mock Bwmsgsv2Repo::REDIS
1793			assert_mock Command::COMMAND_MANAGER
1794		end
1795		em :test_write_local_inventory_must_pay
1796
1797		def test_write_tn_fail
1798			create_order = stub_request(
1799				:post,
1800				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
1801			).to_return(status: 201, body: <<~RESPONSE)
1802				<OrderResponse>
1803					<Order>
1804						<id>test_order</id>
1805					</Order>
1806				</OrderResponse>
1807			RESPONSE
1808			stub_request(
1809				:get,
1810				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
1811			).to_return(status: 201, body: <<~RESPONSE)
1812				<OrderResponse>
1813					<OrderStatus>FAILED</OrderStatus>
1814				</OrderResponse>
1815			RESPONSE
1816
1817			result = execute_command do
1818				Command::COMMAND_MANAGER.expect(
1819					:write,
1820					EMPromise.reject(:test_result),
1821					[Matching.new do |iq|
1822						assert_equal :form, iq.form.type
1823						assert_equal(
1824							"The JMP number (555) 555-0000 is no longer available.",
1825							iq.form.instructions
1826						)
1827					end]
1828				)
1829
1830				@finish.write.catch { |e| e }
1831			end
1832
1833			assert_equal :test_result, result
1834			assert_mock Command::COMMAND_MANAGER
1835			assert_instance_of(
1836				TelSelections::ChooseTel,
1837				Registration::Finish::TEL_SELECTIONS[
1838					OpenStruct.new(jid: "test@example.com")
1839				]
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 = execute_command do |exe|
2272				exe.customer_repo.expect(:find, cust, [cust.customer_id])
2273				Registration::RegistrationType.for(cust, nil, tel).sync
2274			end
2275			assert_kind_of Registration::Finish, result
2276		end
2277		em :test_for_with_telephone_number
2278	end
2279
2280	class DataOnlyTest < Minitest::Test
2281		def setup
2282			@customer = customer(plan_name: "test_usd").with_balance(5)
2283			@sim_kind = SIMKind.new("sim")
2284		end
2285
2286		def test_for_returns_pay_for_sim_when_balance_insufficient
2287			low_balance_customer = @customer.with_balance(0.50)
2288			result = Registration::DataOnly.for(low_balance_customer, @sim_kind)
2289			assert_kind_of Registration::PayForSim, result
2290		end
2291
2292		def test_for_returns_pay_for_sim_when_config_missing
2293			no_currency_customer = customer(currency: nil)
2294			result = Registration::DataOnly.for(no_currency_customer, @sim_kind)
2295			assert_kind_of Registration::PayForSim, result
2296		end
2297
2298		def test_for_returns_data_only_when_balance_sufficient
2299			result =
2300				Registration::DataOnly.for(@customer, @sim_kind)
2301			assert_kind_of Registration::DataOnly, result
2302		end
2303
2304		def test_write_calls_sim_kind_for_and_process
2305			result = execute_command do
2306				Command::COMMAND_MANAGER.expect(
2307					:write,
2308					EMPromise.reject(:test_result),
2309					[Matching.new do |iq|
2310						assert_equal iq.form.title, "Order SIM"
2311						assert(
2312							iq.form.instructions.start_with?("Our SIMs provide a plan")
2313						)
2314					end]
2315				)
2316				Registration::DataOnly.new(
2317					@customer,
2318					@sim_kind
2319				).write.catch { |e| e }.sync
2320			end
2321			assert_equal result, :test_result
2322			assert_mock Command::COMMAND_MANAGER
2323		end
2324		em :test_write_calls_sim_kind_for_and_process
2325	end
2326
2327	class PayForSimTest < Minitest::Test
2328		Command::COMMAND_MANAGER = Minitest::Mock.new
2329		Registration::PayForSim::Payment = Minitest::Mock.new
2330
2331		def setup
2332			@customer = customer(plan_name: "test_usd")
2333			@sim_kind = SIMKind.new("sim")
2334			@pay_for_sim = Registration::PayForSim.new(@customer, @sim_kind)
2335		end
2336
2337		def test_write_displays_payment_form
2338			iq = Blather::Stanza::Iq::Command.new
2339			iq.form.fields = [
2340				{ var: "activation_method", value: "credit_card" }
2341			]
2342
2343			result = execute_command do
2344				Command::COMMAND_MANAGER.expect(
2345					:write,
2346					EMPromise.resolve(iq),
2347					[Matching.new do |reply|
2348						assert_equal :form, reply.form.type
2349						assert_equal "Pay for SIM", reply.form.title
2350					end]
2351				)
2352
2353				ejector_mock = Minitest::Mock.new
2354				ejector_mock.expect(
2355					:write,
2356					EMPromise.reject(:test_result),
2357					[]
2358				)
2359				Registration::PayForSim::Payment.expect(
2360					:for,
2361					ejector_mock
2362				) do |*, price:, maybe_bill:|
2363					assert_equal 500, price
2364					assert_equal(
2365						Registration::Payment::JustCharge,
2366						maybe_bill
2367					)
2368				end
2369				@pay_for_sim.write.catch { |e| e }
2370			end
2371
2372			assert_equal :test_result, result
2373			assert_mock Command::COMMAND_MANAGER
2374		end
2375		em :test_write_displays_payment_form
2376
2377		def test_write_with_no_currency_shows_plan_selection
2378			no_currency_customer = customer(currency: nil)
2379			pay_for_sim = Registration::PayForSim.new(no_currency_customer, @sim_kind)
2380
2381			iq = Blather::Stanza::Iq::Command.new
2382			iq.form.fields = [
2383				{ var: "plan_name", value: "test_usd" },
2384				{ var: "activation_method", value: "credit_card" }
2385			]
2386
2387			result = execute_command do
2388				Command::COMMAND_MANAGER.expect(
2389					:write,
2390					EMPromise.resolve(iq),
2391					[Matching.new do |reply|
2392						assert_equal :form, reply.form.type
2393						assert_equal "Pay for SIM", reply.form.title
2394					end]
2395				)
2396
2397				CustomerPlan::DB.expect(
2398					:exec_defer,
2399					EMPromise.resolve(nil),
2400					[String, ["test", "test_usd", nil]]
2401				)
2402				ejector_mock = Minitest::Mock.new
2403				ejector_mock.expect(
2404					:write,
2405					EMPromise.reject(:test_result),
2406					[]
2407				)
2408				Registration::PayForSim::Payment.expect(
2409					:for,
2410					ejector_mock
2411				) do |*, price:, maybe_bill:|
2412					assert_equal 500, price
2413					assert_equal(
2414						Registration::Payment::JustCharge,
2415						maybe_bill
2416					)
2417				end
2418				pay_for_sim.write.catch { |e| e }
2419			end
2420
2421			assert_equal :test_result, result
2422			assert_mock Command::COMMAND_MANAGER
2423			assert_mock CustomerPlan::DB
2424		end
2425		em :test_write_with_no_currency_shows_plan_selection
2426
2427		def test_process_payment_uses_just_charge_strategy
2428			iq = Blather::Stanza::Iq::Command.new
2429			iq.form.fields = [
2430				{ var: "activation_method", value: "credit_card" }
2431			]
2432
2433			reloaded_customer = @customer.with_balance(4).with_plan("test_usd")
2434
2435			result = execute_command do |exe|
2436				payment = Minitest::Mock.new
2437				payment.expect(
2438					:write,
2439					EMPromise.resolve(nil),
2440					[]
2441				)
2442				Registration::PayForSim::Payment.expect(
2443					:for,
2444					payment
2445				) do |_, customer, sim_kind, price:, maybe_bill:|
2446					assert_equal @customer, customer
2447					assert_equal @sim_kind, sim_kind
2448					assert_equal Registration::Payment::JustCharge, maybe_bill
2449					assert_equal 500, price
2450				end
2451				exe.customer_repo.expect(
2452					:find,
2453					EMPromise.resolve(reloaded_customer),
2454					[@customer.customer_id]
2455				)
2456
2457				result_ = @pay_for_sim.process_payment(iq).sync
2458				assert_mock payment
2459				assert_mock Command.execution.customer_repo
2460				assert_mock Registration::PayForSim::Payment
2461				result_
2462			end
2463			assert_kind_of Registration::PayForSim, result
2464		end
2465		em :test_process_payment_uses_just_charge_strategy
2466	end
2467end