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