test_registration.rb

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