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(redis: FakeRedis.new)
  33		web_manager.set("test@example.net", "+15555550000")
  34		result = execute_command do
  35			sgx = OpenStruct.new(registered?: false)
  36			Registration.for(
  37				customer(
  38					plan_name: "test_usd",
  39					expires_at: Time.now + 999,
  40					sgx: sgx
  41				),
  42				nil,
  43				web_manager
  44			)
  45		end
  46		assert_kind_of Registration::Finish, result
  47		assert_requested reservation_req
  48	end
  49	em :test_for_activated
  50
  51	def test_for_not_activated_approved
  52		sgx = OpenStruct.new(registered?: false)
  53		web_manager = TelSelections.new(redis: FakeRedis.new)
  54		web_manager.set("test\\40approved.example.com@component", "+15555550000")
  55		iq = Blather::Stanza::Iq::Command.new
  56		iq.from = "test@approved.example.com"
  57		result = execute_command(iq) do
  58			Registration::Activation.for(
  59				customer(
  60					sgx: sgx,
  61					jid: Blather::JID.new("test\\40approved.example.com@component")
  62				),
  63				nil,
  64				web_manager
  65			)
  66		end
  67		assert_kind_of Registration::Activation::Allow, result
  68	end
  69	em :test_for_not_activated_approved
  70
  71	def test_for_not_activated_googleplay
  72		sgx = OpenStruct.new(registered?: false)
  73		web_manager = TelSelections.new(redis: FakeRedis.new)
  74		web_manager.set("test@example.net", "+15555550000")
  75		iq = Blather::Stanza::Iq::Command.new
  76		iq.from = "test@approved.example.com"
  77		result = execute_command(iq) do
  78			Registration::Activation.for(
  79				customer(sgx: sgx),
  80				"GARBLEDYGOOK==",
  81				web_manager
  82			)
  83		end
  84		assert_kind_of Registration::Activation::GooglePlay, result
  85	end
  86	em :test_for_not_activated_googleplay
  87
  88	def test_for_not_activated_with_customer_id
  89		sgx = OpenStruct.new(registered?: false)
  90		web_manager = TelSelections.new(redis: FakeRedis.new)
  91		web_manager.set("test@example.net", "+15555550000")
  92		iq = Blather::Stanza::Iq::Command.new
  93		iq.from = "test@example.com"
  94		result = execute_command(iq) do
  95			Registration::Activation.for(
  96				customer(sgx: sgx),
  97				nil,
  98				web_manager
  99			)
 100		end
 101		assert_kind_of Registration::Activation, result
 102	end
 103	em :test_for_not_activated_with_customer_id
 104
 105	class ActivationTest < Minitest::Test
 106		Command::COMMAND_MANAGER = Minitest::Mock.new
 107		def setup
 108			@activation = Registration::Activation.new("test", "+15555550000")
 109		end
 110
 111		def test_write
 112			stub_request(
 113				:get,
 114				"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
 115			).to_return(status: 201, body: <<~RESPONSE)
 116				<TelephoneNumberResponse>
 117					<TelephoneNumber>5555550000</TelephoneNumber>
 118				</TelephoneNumberResponse>
 119			RESPONSE
 120			stub_request(
 121				:get,
 122				"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
 123			).to_return(status: 201, body: <<~RESPONSE)
 124				<TelephoneNumberResponse>
 125					<TelephoneNumberDetails>
 126						<State>KE</State>
 127						<RateCenter>FA</RateCenter>
 128					</TelephoneNumberDetails>
 129				</TelephoneNumberResponse>
 130			RESPONSE
 131			Command::COMMAND_MANAGER.expect(
 132				:write,
 133				EMPromise.reject(:test_result),
 134				[Matching.new do |iq|
 135					assert_equal :form, iq.form.type
 136					assert_equal(
 137						"You've selected +15555550000 (FA, KE) as your JMP number.",
 138						iq.form.instructions.lines.first.chomp
 139					)
 140				end]
 141			)
 142			assert_equal(
 143				:test_result,
 144				execute_command { @activation.write.catch { |e| e } }
 145			)
 146			assert_mock Command::COMMAND_MANAGER
 147		end
 148		em :test_write
 149	end
 150
 151	class AllowTest < Minitest::Test
 152		Command::COMMAND_MANAGER = Minitest::Mock.new
 153		Registration::Activation::Allow::DB = Minitest::Mock.new
 154
 155		def test_write_credit_to_nil
 156			cust = Minitest::Mock.new(customer("test"))
 157			allow = Registration::Activation::Allow.new(cust, "+15555550000", nil)
 158
 159			stub_request(
 160				:get,
 161				"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
 162			).to_return(status: 201, body: <<~RESPONSE)
 163				<TelephoneNumberResponse>
 164					<TelephoneNumber>5555550000</TelephoneNumber>
 165				</TelephoneNumberResponse>
 166			RESPONSE
 167			stub_request(
 168				:get,
 169				"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
 170			).to_return(status: 201, body: <<~RESPONSE)
 171				<TelephoneNumberResponse>
 172					<TelephoneNumberDetails>
 173						<State>KE</State>
 174						<RateCenter>FA</RateCenter>
 175					</TelephoneNumberDetails>
 176				</TelephoneNumberResponse>
 177			RESPONSE
 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" }]
 182				}),
 183				[Matching.new do |iq|
 184					assert_equal :form, iq.form.type
 185					assert_equal(
 186						"You've selected +15555550000 (FA, KE) as your JMP number.",
 187						iq.form.instructions.lines.first.chomp
 188					)
 189					assert_equal 1, iq.form.fields.length
 190				end]
 191			)
 192			Registration::Activation::Allow::DB.expect(
 193				:transaction,
 194				EMPromise.reject(:test_result)
 195			) do |&blk|
 196				blk.call
 197				true
 198			end
 199			cust.expect(:with_plan, cust, ["test_usd"])
 200			cust.expect(:activate_plan_starting_now, nil)
 201			assert_equal(
 202				:test_result,
 203				execute_command { allow.write.catch { |e| e } }
 204			)
 205			assert_mock Command::COMMAND_MANAGER
 206		end
 207		em :test_write_credit_to_nil
 208
 209		def test_write_credit_to_refercust
 210			cust = Minitest::Mock.new(customer("test"))
 211			allow = Registration::Activation::Allow.new(
 212				cust, "+15555550000", "refercust"
 213			)
 214
 215			stub_request(
 216				:get,
 217				"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
 218			).to_return(status: 201, body: <<~RESPONSE)
 219				<TelephoneNumberResponse>
 220					<TelephoneNumber>5555550000</TelephoneNumber>
 221				</TelephoneNumberResponse>
 222			RESPONSE
 223			stub_request(
 224				:get,
 225				"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
 226			).to_return(status: 201, body: <<~RESPONSE)
 227				<TelephoneNumberResponse>
 228					<TelephoneNumberDetails>
 229						<State>KE</State>
 230						<RateCenter>FA</RateCenter>
 231					</TelephoneNumberDetails>
 232				</TelephoneNumberResponse>
 233			RESPONSE
 234			Command::COMMAND_MANAGER.expect(
 235				:write,
 236				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
 237					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
 238				}),
 239				[Matching.new do |iq|
 240					assert_equal :form, iq.form.type
 241					assert_equal(
 242						"You've selected +15555550000 (FA, KE) as your JMP number.",
 243						iq.form.instructions.lines.first.chomp
 244					)
 245					assert_equal 1, iq.form.fields.length
 246				end]
 247			)
 248			Registration::Activation::Allow::DB.expect(
 249				:transaction,
 250				EMPromise.reject(:test_result)
 251			) do |&blk|
 252				blk.call
 253				true
 254			end
 255			Registration::Activation::Allow::DB.expect(
 256				:exec,
 257				nil,
 258				[String, ["refercust", "test"]]
 259			)
 260			cust.expect(:with_plan, cust, ["test_usd"])
 261			cust.expect(:activate_plan_starting_now, nil)
 262			assert_equal(
 263				:test_result,
 264				execute_command { allow.write.catch { |e| e } }
 265			)
 266			assert_mock Command::COMMAND_MANAGER
 267		end
 268		em :test_write_credit_to_refercust
 269	end
 270
 271	class PaymentTest < Minitest::Test
 272		CustomerFinancials::BRAINTREE = Minitest::Mock.new
 273
 274		def test_for_bitcoin
 275			cust = Minitest::Mock.new(customer)
 276			cust.expect(:with_plan, cust, ["test_usd"])
 277			cust.expect(:save_plan!, nil)
 278			iq = Blather::Stanza::Iq::Command.new
 279			iq.form.fields = [
 280				{ var: "activation_method", value: "bitcoin" },
 281				{ var: "plan_name", value: "test_usd" }
 282			]
 283			result = Registration::Payment.for(iq, cust, "+15555550000")
 284			assert_kind_of Registration::Payment::Bitcoin, result
 285			assert_mock cust
 286		end
 287
 288		def test_for_credit_card
 289			cust = Minitest::Mock.new(customer)
 290			cust.expect(:with_plan, cust, ["test_usd"])
 291			cust.expect(:save_plan!, nil)
 292			braintree_customer = Minitest::Mock.new
 293			CustomerFinancials::BRAINTREE.expect(
 294				:customer,
 295				braintree_customer
 296			)
 297			CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
 298			braintree_customer.expect(
 299				:find,
 300				EMPromise.resolve(OpenStruct.new(payment_methods: [])),
 301				["test"]
 302			)
 303			iq = Blather::Stanza::Iq::Command.new
 304			iq.from = "test@example.com"
 305			iq.form.fields = [
 306				{ var: "activation_method", value: "credit_card" },
 307				{ var: "plan_name", value: "test_usd" }
 308			]
 309			result = execute_command do
 310				Command.execution.customer_repo.expect(:find, cust, ["test"])
 311				Registration::Payment.for(
 312					iq,
 313					cust,
 314					""
 315				).sync
 316			end
 317			assert_kind_of Registration::Payment::CreditCard, result
 318			assert_mock cust
 319		end
 320		em :test_for_credit_card
 321
 322		def test_for_code
 323			cust = Minitest::Mock.new(customer)
 324			cust.expect(:with_plan, cust, ["test_usd"])
 325			cust.expect(:save_plan!, nil)
 326			iq = Blather::Stanza::Iq::Command.new
 327			iq.form.fields = [
 328				{ var: "activation_method", value: "code" },
 329				{ var: "plan_name", value: "test_usd" }
 330			]
 331			result = Registration::Payment.for(
 332				iq,
 333				cust,
 334				"+15555550000"
 335			)
 336			assert_kind_of Registration::Payment::InviteCode, result
 337			assert_mock cust
 338		end
 339
 340		class BitcoinTest < Minitest::Test
 341			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
 342			CustomerFinancials::REDIS = Minitest::Mock.new
 343
 344			def setup
 345				@customer = Minitest::Mock.new(
 346					customer(plan_name: "test_usd")
 347				)
 348				@customer.expect(
 349					:add_btc_address,
 350					EMPromise.resolve("testaddr")
 351				)
 352				@bitcoin = Registration::Payment::Bitcoin.new(
 353					@customer,
 354					"+15555550000"
 355				)
 356			end
 357
 358			def test_write
 359				CustomerFinancials::REDIS.expect(
 360					:smembers,
 361					EMPromise.resolve([]),
 362					["jmp_customer_btc_addresses-test"]
 363				)
 364				blather = Minitest::Mock.new
 365				Command::COMMAND_MANAGER.expect(
 366					:write,
 367					EMPromise.reject(SessionManager::Timeout.new),
 368					[Matching.new do |reply|
 369						assert_equal :canceled, reply.status
 370						assert_equal "1.000000", reply.form.field("amount").value
 371						assert_equal "testaddr", reply.form.field("btc_addresses").value
 372						true
 373					end]
 374				)
 375				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
 376					:usd,
 377					EMPromise.resolve(BigDecimal(1))
 378				)
 379				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
 380					execute_command(blather: blather) do
 381						@bitcoin.write
 382					end
 383				end
 384				assert_mock blather
 385			end
 386			em :test_write
 387		end
 388
 389		class CreditCardTest < Minitest::Test
 390			def setup
 391				@credit_card = Registration::Payment::CreditCard.new(
 392					customer,
 393					"+15555550000"
 394				)
 395			end
 396
 397			def test_for
 398				cust = Minitest::Mock.new(customer)
 399				cust.expect(
 400					:payment_methods,
 401					EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
 402				)
 403				execute_command do
 404					Command.execution.customer_repo.expect(:find, cust, ["test"])
 405					assert_kind_of(
 406						Registration::Payment::CreditCard::Activate,
 407						Registration::Payment::CreditCard.for(
 408							cust,
 409							"+15555550000"
 410						).sync
 411					)
 412				end
 413			end
 414			em :test_for
 415
 416			def test_for_has_balance
 417				cust = Minitest::Mock.new(customer)
 418				cust.expect(:balance, 100)
 419				cust.expect(:payment_methods, EMPromise.resolve(nil))
 420				execute_command do
 421					Command.execution.customer_repo.expect(:find, cust, ["test"])
 422					assert_kind_of(
 423						Registration::BillPlan,
 424						Registration::Payment::CreditCard.for(
 425							cust,
 426							"+15555550000"
 427						).sync
 428					)
 429				end
 430			end
 431			em :test_for_has_balance
 432
 433			def test_write
 434				result = execute_command do
 435					Command::COMMAND_MANAGER.expect(
 436						:write,
 437						EMPromise.reject(:test_result),
 438						[Matching.new do |reply|
 439							assert_equal [:execute, :next, :prev], reply.allowed_actions
 440							assert_equal(
 441								"Add credit card, save, then next here to continue: " \
 442								"http://creditcard.example.com?&amount=1",
 443								reply.note.content
 444							)
 445						end]
 446					)
 447
 448					@credit_card.write.catch { |e| e }
 449				end
 450
 451				assert_equal :test_result, result
 452			end
 453			em :test_write
 454		end
 455
 456		class MailTest < Minitest::Test
 457			def setup
 458				@mail = Registration::Payment::Mail.new(
 459					customer(plan_name: "test_cad"),
 460					"+15555550000"
 461				)
 462			end
 463
 464			def test_write
 465				result = execute_command do
 466					Command::COMMAND_MANAGER.expect(
 467						:write,
 468						EMPromise.reject(:test_result),
 469						[Matching.new do |reply|
 470							assert_equal [:execute, :prev], reply.allowed_actions
 471							refute reply.form.instructions.empty?
 472							assert_equal(
 473								"A Mailing Address",
 474								reply.form.field("adr").value
 475							)
 476							assert_equal(
 477								"interac@example.com",
 478								reply.form.field("interac_email").value
 479							)
 480						end]
 481					)
 482
 483					@mail.write.catch { |e| e }
 484				end
 485
 486				assert_equal :test_result, result
 487			end
 488			em :test_write
 489		end
 490
 491		class ActivateTest < Minitest::Test
 492			Registration::Payment::CreditCard::Activate::Finish =
 493				Minitest::Mock.new
 494			Registration::Payment::CreditCard::Activate::CreditCardSale =
 495				Minitest::Mock.new
 496			Command::COMMAND_MANAGER = Minitest::Mock.new
 497
 498			def test_write
 499				customer = Minitest::Mock.new(
 500					customer(plan_name: "test_usd")
 501				)
 502				Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
 503					:create,
 504					EMPromise.resolve(nil)
 505				) do |acustomer, amount:, payment_method:|
 506					assert_operator customer, :===, acustomer
 507					assert_equal CONFIG[:activation_amount], amount
 508					assert_equal :test_default_method, payment_method
 509				end
 510				customer.expect(
 511					:bill_plan,
 512					nil,
 513					note: "Bill +15555550000 for first month"
 514				)
 515				Registration::Payment::CreditCard::Activate::Finish.expect(
 516					:new,
 517					OpenStruct.new(write: nil),
 518					[customer, "+15555550000"]
 519				)
 520				execute_command do
 521					Registration::Payment::CreditCard::Activate.new(
 522						customer,
 523						:test_default_method,
 524						"+15555550000"
 525					).write
 526				end
 527				Registration::Payment::CreditCard::Activate::CreditCardSale.verify
 528				customer.verify
 529				Registration::Payment::CreditCard::Activate::Finish.verify
 530			end
 531			em :test_write
 532
 533			def test_write_declines
 534				customer = Minitest::Mock.new(
 535					customer(plan_name: "test_usd")
 536				)
 537				iq = Blather::Stanza::Iq::Command.new
 538				iq.from = "test@example.com"
 539				msg = Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE
 540				Command::COMMAND_MANAGER.expect(
 541					:write,
 542					EMPromise.reject(:test_result),
 543					[Matching.new do |reply|
 544						assert_equal :error, reply.note_type
 545						assert_equal(
 546							"#{msg}: http://creditcard.example.com?&amount=1",
 547							reply.note.content
 548						)
 549					end]
 550				)
 551				result = execute_command do
 552					Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
 553						:create,
 554						EMPromise.reject("declined")
 555					) do |acustomer, amount:, payment_method:|
 556						assert_operator customer, :===, acustomer
 557						assert_equal CONFIG[:activation_amount], amount
 558						assert_equal :test_default_method, payment_method
 559					end
 560
 561					Registration::Payment::CreditCard::Activate.new(
 562						customer,
 563						:test_default_method,
 564						"+15555550000"
 565					).write.catch { |e| e }
 566				end
 567				assert_equal :test_result, result
 568				Registration::Payment::CreditCard::Activate::CreditCardSale.verify
 569			end
 570			em :test_write_declines
 571		end
 572
 573		class InviteCodeTest < Minitest::Test
 574			Registration::Payment::InviteCode::DB =
 575				Minitest::Mock.new
 576			Registration::Payment::InviteCode::REDIS =
 577				Minitest::Mock.new
 578			Command::COMMAND_MANAGER = Minitest::Mock.new
 579			Registration::Payment::InviteCode::Finish =
 580				Minitest::Mock.new
 581			def test_write
 582				customer = customer(plan_name: "test_usd")
 583				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
 584				Registration::Payment::InviteCode::Finish.expect(
 585					:new,
 586					OpenStruct.new(write: nil),
 587					[
 588						customer,
 589						"+15555550000"
 590					]
 591				)
 592				execute_command do
 593					Registration::Payment::InviteCode::REDIS.expect(
 594						:get,
 595						EMPromise.resolve(nil),
 596						["jmp_invite_tries-test"]
 597					)
 598					Command::COMMAND_MANAGER.expect(
 599						:write,
 600						EMPromise.resolve(
 601							Blather::Stanza::Iq::Command.new.tap { |iq|
 602								iq.form.fields = [{ var: "code", value: "abc" }]
 603							}
 604						),
 605						[Matching.new do |reply|
 606							assert_equal :form, reply.form.type
 607							assert_nil reply.form.instructions
 608						end]
 609					)
 610
 611					Registration::Payment::InviteCode.new(
 612						customer,
 613						"+15555550000"
 614					).write
 615				end
 616				assert_mock Command::COMMAND_MANAGER
 617				assert_mock Registration::Payment::InviteCode::DB
 618				assert_mock Registration::Payment::InviteCode::REDIS
 619				assert_mock Registration::Payment::InviteCode::Finish
 620			end
 621			em :test_write
 622
 623			def test_write_bad_code
 624				result = execute_command do
 625					customer = customer(plan_name: "test_usd")
 626					Registration::Payment::InviteCode::REDIS.expect(
 627						:get,
 628						EMPromise.resolve(0),
 629						["jmp_invite_tries-test"]
 630					)
 631					Registration::Payment::InviteCode::DB.expect(:transaction, []) do
 632						raise InvitesRepo::Invalid, "wut"
 633					end
 634					Registration::Payment::InviteCode::REDIS.expect(
 635						:incr,
 636						EMPromise.resolve(nil),
 637						["jmp_invite_tries-test"]
 638					)
 639					Registration::Payment::InviteCode::REDIS.expect(
 640						:expire,
 641						EMPromise.resolve(nil),
 642						["jmp_invite_tries-test", 60 * 60]
 643					)
 644					Command::COMMAND_MANAGER.expect(
 645						:write,
 646						EMPromise.resolve(
 647							Blather::Stanza::Iq::Command.new.tap { |iq|
 648								iq.form.fields = [{ var: "code", value: "abc" }]
 649							}
 650						),
 651						[Matching.new do |reply|
 652							assert_equal :form, reply.form.type
 653							assert_nil reply.form.instructions
 654						end]
 655					)
 656					Command::COMMAND_MANAGER.expect(
 657						:write,
 658						EMPromise.reject(:test_result),
 659						[Matching.new do |reply|
 660							assert_equal :form, reply.form.type
 661							assert_equal "wut", reply.form.instructions
 662						end]
 663					)
 664
 665					Registration::Payment::InviteCode.new(
 666						customer,
 667						"+15555550000"
 668					).write.catch { |e| e }
 669				end
 670				assert_equal :test_result, result
 671				assert_mock Command::COMMAND_MANAGER
 672				assert_mock Registration::Payment::InviteCode::DB
 673				assert_mock Registration::Payment::InviteCode::REDIS
 674			end
 675			em :test_write_bad_code
 676
 677			def test_write_bad_code_over_limit
 678				result = execute_command do
 679					customer = customer(plan_name: "test_usd")
 680					Registration::Payment::InviteCode::REDIS.expect(
 681						:get,
 682						EMPromise.resolve(11),
 683						["jmp_invite_tries-test"]
 684					)
 685					Command::COMMAND_MANAGER.expect(
 686						:write,
 687						EMPromise.resolve(
 688							Blather::Stanza::Iq::Command.new.tap { |iq|
 689								iq.form.fields = [{ var: "code", value: "abc" }]
 690							}
 691						),
 692						[Matching.new do |reply|
 693							assert_equal :form, reply.form.type
 694							assert_nil reply.form.instructions
 695						end]
 696					)
 697					Registration::Payment::InviteCode::REDIS.expect(
 698						:incr,
 699						EMPromise.resolve(nil),
 700						["jmp_invite_tries-test"]
 701					)
 702					Registration::Payment::InviteCode::REDIS.expect(
 703						:expire,
 704						EMPromise.resolve(nil),
 705						["jmp_invite_tries-test", 60 * 60]
 706					)
 707					Command::COMMAND_MANAGER.expect(
 708						:write,
 709						EMPromise.reject(:test_result),
 710						[Matching.new do |reply|
 711							assert_equal :form, reply.form.type
 712							assert_equal "Too many wrong attempts", reply.form.instructions
 713						end]
 714					)
 715					Registration::Payment::InviteCode.new(
 716						customer,
 717						"+15555550000"
 718					).write.catch { |e| e }
 719				end
 720				assert_equal :test_result, result
 721				assert_mock Command::COMMAND_MANAGER
 722				assert_mock Registration::Payment::InviteCode::REDIS
 723			end
 724			em :test_write_bad_code_over_limit
 725		end
 726	end
 727
 728	class FinishTest < Minitest::Test
 729		Customer::BLATHER = Minitest::Mock.new
 730		Command::COMMAND_MANAGER = Minitest::Mock.new
 731		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
 732		Registration::Finish::REDIS = Minitest::Mock.new
 733		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
 734		Registration::FinishOnboarding::DB = FakeDB.new
 735
 736		def setup
 737			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
 738			iq = Blather::Stanza::Iq::Command.new
 739			iq.from = "test\\40example.com@cheogram.com"
 740			@finish = Registration::Finish.new(
 741				customer(sgx: @sgx),
 742				"+15555550000"
 743			)
 744		end
 745
 746		def test_write
 747			create_order = stub_request(
 748				:post,
 749				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 750			).to_return(status: 201, body: <<~RESPONSE)
 751				<OrderResponse>
 752					<Order>
 753						<id>test_order</id>
 754					</Order>
 755				</OrderResponse>
 756			RESPONSE
 757			stub_request(
 758				:get,
 759				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 760			).to_return(status: 201, body: <<~RESPONSE)
 761				<OrderResponse>
 762					<OrderStatus>COMPLETE</OrderStatus>
 763					<CompletedNumbers>
 764						<TelephoneNumber>
 765							<FullNumber>5555550000</FullNumber>
 766						</TelephoneNumber>
 767					</CompletedNumbers>
 768				</OrderResponse>
 769			RESPONSE
 770			stub_request(
 771				:post,
 772				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
 773			)
 774			Registration::Finish::REDIS.expect(
 775				:del,
 776				nil,
 777				["pending_tel_for-test@example.net"]
 778			)
 779			Bwmsgsv2Repo::REDIS.expect(
 780				:set,
 781				nil,
 782				[
 783					"catapult_fwd-+15555550000",
 784					"xmpp:test@example.net"
 785				]
 786			)
 787			Bwmsgsv2Repo::REDIS.expect(
 788				:set,
 789				nil,
 790				["catapult_fwd_timeout-customer_test@component", 25]
 791			)
 792			Customer::BLATHER.expect(
 793				:<<,
 794				nil,
 795				[Matching.new do |m|
 796					assert_equal :chat, m.type
 797					assert m.body =~ /^Welcome to JMP/
 798				end]
 799			)
 800			blather = Minitest::Mock.new
 801			blather.expect(
 802				:<<,
 803				nil,
 804				[Matching.new do |reply|
 805					assert_equal :completed, reply.status
 806					assert_equal :info, reply.note_type
 807					assert_equal(
 808						"Your JMP account has been activated as +15555550000",
 809						reply.note.content
 810					)
 811				end]
 812			)
 813			execute_command(blather: blather) do
 814				@sgx.expect(
 815					:register!,
 816					EMPromise.resolve(@sgx.with(
 817						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
 818							ibr.phone = "+15555550000"
 819						end
 820					)),
 821					["+15555550000"]
 822				)
 823
 824				@finish.write
 825			end
 826			assert_requested create_order
 827			assert_mock @sgx
 828			assert_mock Registration::Finish::REDIS
 829			assert_mock Bwmsgsv2Repo::REDIS
 830			assert_mock Customer::BLATHER
 831			assert_mock blather
 832		end
 833		em :test_write
 834
 835		def test_write_onboarding
 836			create_order = stub_request(
 837				:post,
 838				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 839			).to_return(status: 201, body: <<~RESPONSE)
 840				<OrderResponse>
 841					<Order>
 842						<id>test_order</id>
 843					</Order>
 844				</OrderResponse>
 845			RESPONSE
 846			stub_request(
 847				:get,
 848				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 849			).to_return(status: 201, body: <<~RESPONSE)
 850				<OrderResponse>
 851					<OrderStatus>COMPLETE</OrderStatus>
 852					<CompletedNumbers>
 853						<TelephoneNumber>
 854							<FullNumber>5555550000</FullNumber>
 855						</TelephoneNumber>
 856					</CompletedNumbers>
 857				</OrderResponse>
 858			RESPONSE
 859			stub_request(
 860				:post,
 861				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
 862			)
 863			Registration::Finish::REDIS.expect(
 864				:del,
 865				nil,
 866				["pending_tel_for-test\\40onboarding.example.com@proxy"]
 867			)
 868			Bwmsgsv2Repo::REDIS.expect(
 869				:set,
 870				nil,
 871				[
 872					"catapult_fwd-+15555550000",
 873					"xmpp:test\\40onboarding.example.com@proxy"
 874				]
 875			)
 876			Bwmsgsv2Repo::REDIS.expect(
 877				:set,
 878				nil,
 879				["catapult_fwd_timeout-customer_test@component", 25]
 880			)
 881			result = execute_command do
 882				@sgx.expect(
 883					:register!,
 884					EMPromise.resolve(@sgx.with(
 885						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
 886							ibr.phone = "+15555550000"
 887						end
 888					)),
 889					["+15555550000"]
 890				)
 891
 892				Command::COMMAND_MANAGER.expect(
 893					:write,
 894					EMPromise.reject(:test_result),
 895					[Matching.new do |iq|
 896						assert_equal :form, iq.form.type
 897						assert iq.form.field("subdomain")
 898					end]
 899				)
 900
 901				Registration::Finish.new(
 902					customer(
 903						sgx: @sgx,
 904						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
 905					),
 906					"+15555550000"
 907				).write.catch { |e| e }
 908			end
 909			assert_equal :test_result, result
 910			assert_requested create_order
 911			assert_mock @sgx
 912			assert_mock Registration::Finish::REDIS
 913			assert_mock Bwmsgsv2Repo::REDIS
 914			assert_mock Command::COMMAND_MANAGER
 915		end
 916		em :test_write_onboarding
 917
 918		def test_write_tn_fail
 919			create_order = stub_request(
 920				:post,
 921				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 922			).to_return(status: 201, body: <<~RESPONSE)
 923				<OrderResponse>
 924					<Order>
 925						<id>test_order</id>
 926					</Order>
 927				</OrderResponse>
 928			RESPONSE
 929			stub_request(
 930				:get,
 931				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 932			).to_return(status: 201, body: <<~RESPONSE)
 933				<OrderResponse>
 934					<OrderStatus>FAILED</OrderStatus>
 935				</OrderResponse>
 936			RESPONSE
 937
 938			result = execute_command do
 939				Command::COMMAND_MANAGER.expect(
 940					:write,
 941					EMPromise.reject(:test_result),
 942					[Matching.new do |iq|
 943						assert_equal :form, iq.form.type
 944						assert_equal(
 945							"The JMP number +15555550000 is no longer available.",
 946							iq.form.instructions
 947						)
 948					end]
 949				)
 950
 951				@finish.write.catch { |e| e }
 952			end
 953
 954			assert_equal :test_result, result
 955			assert_mock Command::COMMAND_MANAGER
 956			assert_instance_of(
 957				TelSelections::ChooseTel,
 958				Registration::Finish::TEL_SELECTIONS["test@example.com"]
 959			)
 960			assert_requested create_order
 961		end
 962		em :test_write_tn_fail
 963	end
 964
 965	class SnikketTest < Minitest::Test
 966		Command::COMMAND_MANAGER = Minitest::Mock.new
 967		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
 968
 969		def setup
 970			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
 971			@snikket = Registration::FinishOnboarding::Snikket.new(
 972				customer,
 973				"+15555550000",
 974				db: FakeDB.new
 975			)
 976		end
 977
 978		def test_write
 979			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
 980
 981			subdomain_form = Blather::Stanza::Iq::Command.new
 982			subdomain_form.form.fields = [
 983				{ var: "subdomain", value: "test" }
 984			]
 985
 986			launched = Snikket::Launched.new
 987			launched << Niceogiri::XML::Node.new(
 988				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
 989			).tap { |inner|
 990				inner << Niceogiri::XML::Node.new(
 991					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
 992				).tap { |id|
 993					id.content = "si-1234"
 994				}
 995				inner << Niceogiri::XML::Node.new(
 996					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
 997				).tap { |bootstrap|
 998					bootstrap << Niceogiri::XML::Node.new(
 999						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1000					).tap { |token|
1001						token.content = "TOKEN"
1002					}
1003				}
1004			}
1005
1006			blather = Minitest::Mock.new
1007			blather.expect(
1008				:<<,
1009				nil,
1010				[Matching.new do |reply|
1011					assert_equal :completed, reply.status
1012					assert_equal(
1013						xmpp_uri,
1014						OOB.find_or_create(reply.command).url
1015					)
1016				end]
1017			)
1018
1019			execute_command(blather: blather) do
1020				Command::COMMAND_MANAGER.expect(
1021					:write,
1022					EMPromise.resolve(subdomain_form),
1023					[Matching.new do |iq|
1024						assert_equal :form, iq.form.type
1025						assert iq.form.field("subdomain")
1026					end]
1027				)
1028
1029				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1030					:write,
1031					EMPromise.resolve(launched),
1032					[Matching.new do |iq|
1033						assert_equal :set, iq.type
1034						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1035						assert_equal(
1036							"test.snikket.chat",
1037							iq.xpath(
1038								"./ns:launch/ns:domain",
1039								ns: "xmpp:snikket.org/hosting/v1"
1040							).text
1041						)
1042					end]
1043				)
1044
1045				# Webmock doesn't support redirects properly, but they work live
1046				stub_request(
1047					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1048				).to_return(
1049					status: 200,
1050					headers: {
1051						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1052					}
1053				)
1054
1055				@snikket.write
1056			end
1057
1058			assert_mock Command::COMMAND_MANAGER
1059			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1060			assert_mock blather
1061		end
1062		em :test_write
1063
1064		def test_write_not_yet
1065			subdomain_form = Blather::Stanza::Iq::Command.new
1066			subdomain_form.form.fields = [
1067				{ var: "subdomain", value: "test" }
1068			]
1069
1070			launched = Snikket::Launched.new
1071			launched << Niceogiri::XML::Node.new(
1072				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1073			).tap { |inner|
1074				inner << Niceogiri::XML::Node.new(
1075					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1076				).tap { |id|
1077					id.content = "si-1234"
1078				}
1079				inner << Niceogiri::XML::Node.new(
1080					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1081				).tap { |bootstrap|
1082					bootstrap << Niceogiri::XML::Node.new(
1083						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1084					).tap { |token|
1085						token.content = "TOKEN"
1086					}
1087				}
1088			}
1089
1090			result = execute_command do
1091				Command::COMMAND_MANAGER.expect(
1092					:write,
1093					EMPromise.resolve(subdomain_form),
1094					[Matching.new do |iq|
1095						assert_equal :form, iq.form.type
1096						assert iq.form.field("subdomain")
1097					end]
1098				)
1099
1100				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1101					:write,
1102					EMPromise.resolve(launched),
1103					[Matching.new do |iq|
1104						assert_equal :set, iq.type
1105						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1106						assert_equal(
1107							"test.snikket.chat",
1108							iq.xpath(
1109								"./ns:launch/ns:domain",
1110								ns: "xmpp:snikket.org/hosting/v1"
1111							).text
1112						)
1113					end]
1114				)
1115
1116				stub_request(
1117					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1118				).to_timeout
1119
1120				Command::COMMAND_MANAGER.expect(
1121					:write,
1122					EMPromise.reject(:test_result),
1123					[Matching.new do |iq|
1124						assert_equal :result, iq.form.type
1125						assert iq.form.instructions =~ / test\.snikket\.chat /
1126						assert_equal "jid-single", iq.form.field("support").type
1127					end]
1128				)
1129
1130				@snikket.write.catch { |e| e }
1131			end
1132
1133			assert_equal :test_result, result
1134			assert_mock Command::COMMAND_MANAGER
1135			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1136		end
1137		em :test_write_not_yet
1138
1139		def test_write_already_taken
1140			subdomain_form = Blather::Stanza::Iq::Command.new
1141			subdomain_form.form.fields = [
1142				{ var: "subdomain", value: "test" }
1143			]
1144
1145			launched = Snikket::Launched.new.as_error(
1146				"internal-server-error",
1147				:wait,
1148				"This is an error"
1149			)
1150
1151			result = execute_command do
1152				Command::COMMAND_MANAGER.expect(
1153					:write,
1154					EMPromise.resolve(subdomain_form),
1155					[Matching.new do |iq|
1156						assert_equal :form, iq.form.type
1157						assert iq.form.field("subdomain")
1158					end]
1159				)
1160
1161				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1162					:write,
1163					EMPromise.reject(launched),
1164					[Matching.new do |iq|
1165						assert_equal :set, iq.type
1166						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1167						assert_equal(
1168							"test.snikket.chat",
1169							iq.xpath(
1170								"./ns:launch/ns:domain",
1171								ns: "xmpp:snikket.org/hosting/v1"
1172							).text
1173						)
1174					end]
1175				)
1176
1177				stub_request(
1178					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1179				).to_timeout
1180
1181				Command::COMMAND_MANAGER.expect(
1182					:write,
1183					EMPromise.reject(:test_result),
1184					[Matching.new do |iq|
1185						assert iq.executing?
1186						assert_equal(
1187							"This is an error",
1188							iq.form.field("subdomain").desc
1189						)
1190					end]
1191				)
1192
1193				@snikket.write.catch { |e| e }
1194			end
1195
1196			assert_equal :test_result, result
1197			assert_mock Command::COMMAND_MANAGER
1198			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1199		end
1200		em :test_write_already_taken
1201	end
1202end