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(
 632						:transaction,
 633						[]
 634					) { |&blk| blk.call }
 635					Registration::Payment::InviteCode::DB.expect(
 636						:exec,
 637						OpenStruct.new(cmd_tuples: 0),
 638						[String, ["test", "abc"]]
 639					)
 640					Registration::Payment::InviteCode::REDIS.expect(
 641						:incr,
 642						EMPromise.resolve(nil),
 643						["jmp_invite_tries-test"]
 644					)
 645					Registration::Payment::InviteCode::REDIS.expect(
 646						:expire,
 647						EMPromise.resolve(nil),
 648						["jmp_invite_tries-test", 60 * 60]
 649					)
 650					Command::COMMAND_MANAGER.expect(
 651						:write,
 652						EMPromise.resolve(
 653							Blather::Stanza::Iq::Command.new.tap { |iq|
 654								iq.form.fields = [{ var: "code", value: "abc" }]
 655							}
 656						),
 657						[Matching.new do |reply|
 658							assert_equal :form, reply.form.type
 659							assert_nil reply.form.instructions
 660						end]
 661					)
 662					Command::COMMAND_MANAGER.expect(
 663						:write,
 664						EMPromise.reject(:test_result),
 665						[Matching.new do |reply|
 666							assert_equal :form, reply.form.type
 667							assert_equal(
 668								"Not a valid invite code: abc",
 669								reply.form.instructions
 670							)
 671						end]
 672					)
 673
 674					Registration::Payment::InviteCode.new(
 675						customer,
 676						"+15555550000"
 677					).write.catch { |e| e }
 678				end
 679				assert_equal :test_result, result
 680				assert_mock Command::COMMAND_MANAGER
 681				assert_mock Registration::Payment::InviteCode::DB
 682				assert_mock Registration::Payment::InviteCode::REDIS
 683			end
 684			em :test_write_bad_code
 685
 686			def test_write_bad_code_over_limit
 687				result = execute_command do
 688					customer = customer(plan_name: "test_usd")
 689					Registration::Payment::InviteCode::REDIS.expect(
 690						:get,
 691						EMPromise.resolve(11),
 692						["jmp_invite_tries-test"]
 693					)
 694					Command::COMMAND_MANAGER.expect(
 695						:write,
 696						EMPromise.resolve(
 697							Blather::Stanza::Iq::Command.new.tap { |iq|
 698								iq.form.fields = [{ var: "code", value: "abc" }]
 699							}
 700						),
 701						[Matching.new do |reply|
 702							assert_equal :form, reply.form.type
 703							assert_nil reply.form.instructions
 704						end]
 705					)
 706					Command::COMMAND_MANAGER.expect(
 707						:write,
 708						EMPromise.reject(:test_result),
 709						[Matching.new do |reply|
 710							assert_equal :form, reply.form.type
 711							assert_equal "Too many wrong attempts", reply.form.instructions
 712						end]
 713					)
 714					Registration::Payment::InviteCode.new(
 715						customer,
 716						"+15555550000"
 717					).write.catch { |e| e }
 718				end
 719				assert_equal :test_result, result
 720				assert_mock Command::COMMAND_MANAGER
 721				assert_mock Registration::Payment::InviteCode::REDIS
 722			end
 723			em :test_write_bad_code_over_limit
 724		end
 725	end
 726
 727	class FinishTest < Minitest::Test
 728		Customer::BLATHER = Minitest::Mock.new
 729		Command::COMMAND_MANAGER = Minitest::Mock.new
 730		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
 731		Registration::Finish::REDIS = Minitest::Mock.new
 732		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
 733		Registration::FinishOnboarding::DB = FakeDB.new
 734
 735		def setup
 736			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
 737			iq = Blather::Stanza::Iq::Command.new
 738			iq.from = "test\\40example.com@cheogram.com"
 739			@finish = Registration::Finish.new(
 740				customer(sgx: @sgx),
 741				"+15555550000"
 742			)
 743		end
 744
 745		def test_write
 746			create_order = stub_request(
 747				:post,
 748				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 749			).to_return(status: 201, body: <<~RESPONSE)
 750				<OrderResponse>
 751					<Order>
 752						<id>test_order</id>
 753					</Order>
 754				</OrderResponse>
 755			RESPONSE
 756			stub_request(
 757				:get,
 758				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 759			).to_return(status: 201, body: <<~RESPONSE)
 760				<OrderResponse>
 761					<OrderStatus>COMPLETE</OrderStatus>
 762					<CompletedNumbers>
 763						<TelephoneNumber>
 764							<FullNumber>5555550000</FullNumber>
 765						</TelephoneNumber>
 766					</CompletedNumbers>
 767				</OrderResponse>
 768			RESPONSE
 769			stub_request(
 770				:post,
 771				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
 772			)
 773			Registration::Finish::REDIS.expect(
 774				:del,
 775				nil,
 776				["pending_tel_for-test@example.net"]
 777			)
 778			Bwmsgsv2Repo::REDIS.expect(
 779				:set,
 780				nil,
 781				[
 782					"catapult_fwd-+15555550000",
 783					"xmpp:test@example.net"
 784				]
 785			)
 786			Bwmsgsv2Repo::REDIS.expect(
 787				:set,
 788				nil,
 789				["catapult_fwd_timeout-customer_test@component", 25]
 790			)
 791			Customer::BLATHER.expect(
 792				:<<,
 793				nil,
 794				[Matching.new do |m|
 795					assert_equal :chat, m.type
 796					assert m.body =~ /^Welcome to JMP/
 797				end]
 798			)
 799			blather = Minitest::Mock.new
 800			blather.expect(
 801				:<<,
 802				nil,
 803				[Matching.new do |reply|
 804					assert_equal :completed, reply.status
 805					assert_equal :info, reply.note_type
 806					assert_equal(
 807						"Your JMP account has been activated as +15555550000",
 808						reply.note.content
 809					)
 810				end]
 811			)
 812			execute_command(blather: blather) do
 813				@sgx.expect(
 814					:register!,
 815					EMPromise.resolve(@sgx.with(
 816						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
 817							ibr.phone = "+15555550000"
 818						end
 819					)),
 820					["+15555550000"]
 821				)
 822
 823				@finish.write
 824			end
 825			assert_requested create_order
 826			assert_mock @sgx
 827			assert_mock Registration::Finish::REDIS
 828			assert_mock Bwmsgsv2Repo::REDIS
 829			assert_mock Customer::BLATHER
 830			assert_mock blather
 831		end
 832		em :test_write
 833
 834		def test_write_onboarding
 835			create_order = stub_request(
 836				:post,
 837				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 838			).to_return(status: 201, body: <<~RESPONSE)
 839				<OrderResponse>
 840					<Order>
 841						<id>test_order</id>
 842					</Order>
 843				</OrderResponse>
 844			RESPONSE
 845			stub_request(
 846				:get,
 847				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 848			).to_return(status: 201, body: <<~RESPONSE)
 849				<OrderResponse>
 850					<OrderStatus>COMPLETE</OrderStatus>
 851					<CompletedNumbers>
 852						<TelephoneNumber>
 853							<FullNumber>5555550000</FullNumber>
 854						</TelephoneNumber>
 855					</CompletedNumbers>
 856				</OrderResponse>
 857			RESPONSE
 858			stub_request(
 859				:post,
 860				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
 861			)
 862			Registration::Finish::REDIS.expect(
 863				:del,
 864				nil,
 865				["pending_tel_for-test\\40onboarding.example.com@proxy"]
 866			)
 867			Bwmsgsv2Repo::REDIS.expect(
 868				:set,
 869				nil,
 870				[
 871					"catapult_fwd-+15555550000",
 872					"xmpp:test\\40onboarding.example.com@proxy"
 873				]
 874			)
 875			Bwmsgsv2Repo::REDIS.expect(
 876				:set,
 877				nil,
 878				["catapult_fwd_timeout-customer_test@component", 25]
 879			)
 880			result = execute_command do
 881				@sgx.expect(
 882					:register!,
 883					EMPromise.resolve(@sgx.with(
 884						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
 885							ibr.phone = "+15555550000"
 886						end
 887					)),
 888					["+15555550000"]
 889				)
 890
 891				Command::COMMAND_MANAGER.expect(
 892					:write,
 893					EMPromise.reject(:test_result),
 894					[Matching.new do |iq|
 895						assert_equal :form, iq.form.type
 896						assert iq.form.field("subdomain")
 897					end]
 898				)
 899
 900				Registration::Finish.new(
 901					customer(
 902						sgx: @sgx,
 903						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
 904					),
 905					"+15555550000"
 906				).write.catch { |e| e }
 907			end
 908			assert_equal :test_result, result
 909			assert_requested create_order
 910			assert_mock @sgx
 911			assert_mock Registration::Finish::REDIS
 912			assert_mock Bwmsgsv2Repo::REDIS
 913			assert_mock Command::COMMAND_MANAGER
 914		end
 915		em :test_write_onboarding
 916
 917		def test_write_tn_fail
 918			create_order = stub_request(
 919				:post,
 920				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
 921			).to_return(status: 201, body: <<~RESPONSE)
 922				<OrderResponse>
 923					<Order>
 924						<id>test_order</id>
 925					</Order>
 926				</OrderResponse>
 927			RESPONSE
 928			stub_request(
 929				:get,
 930				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
 931			).to_return(status: 201, body: <<~RESPONSE)
 932				<OrderResponse>
 933					<OrderStatus>FAILED</OrderStatus>
 934				</OrderResponse>
 935			RESPONSE
 936
 937			result = execute_command do
 938				Command::COMMAND_MANAGER.expect(
 939					:write,
 940					EMPromise.reject(:test_result),
 941					[Matching.new do |iq|
 942						assert_equal :form, iq.form.type
 943						assert_equal(
 944							"The JMP number +15555550000 is no longer available.",
 945							iq.form.instructions
 946						)
 947					end]
 948				)
 949
 950				@finish.write.catch { |e| e }
 951			end
 952
 953			assert_equal :test_result, result
 954			assert_mock Command::COMMAND_MANAGER
 955			assert_instance_of(
 956				TelSelections::ChooseTel,
 957				Registration::Finish::TEL_SELECTIONS["test@example.com"]
 958			)
 959			assert_requested create_order
 960		end
 961		em :test_write_tn_fail
 962	end
 963
 964	class SnikketTest < Minitest::Test
 965		Command::COMMAND_MANAGER = Minitest::Mock.new
 966		Registration::FinishOnboarding::Snikket::IQ_MANAGER = Minitest::Mock.new
 967
 968		def setup
 969			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
 970			@snikket = Registration::FinishOnboarding::Snikket.new(
 971				customer,
 972				"+15555550000",
 973				db: FakeDB.new
 974			)
 975		end
 976
 977		def test_write
 978			xmpp_uri = "xmpp:test.snikket.chat?register;preauth=NEWTOKEN"
 979
 980			subdomain_form = Blather::Stanza::Iq::Command.new
 981			subdomain_form.form.fields = [
 982				{ var: "subdomain", value: "test" }
 983			]
 984
 985			launched = Snikket::Launched.new
 986			launched << Niceogiri::XML::Node.new(
 987				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
 988			).tap { |inner|
 989				inner << Niceogiri::XML::Node.new(
 990					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
 991				).tap { |id|
 992					id.content = "si-1234"
 993				}
 994				inner << Niceogiri::XML::Node.new(
 995					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
 996				).tap { |bootstrap|
 997					bootstrap << Niceogiri::XML::Node.new(
 998						:token, launched.document, "xmpp:snikket.org/hosting/v1"
 999					).tap { |token|
1000						token.content = "TOKEN"
1001					}
1002				}
1003			}
1004
1005			blather = Minitest::Mock.new
1006			blather.expect(
1007				:<<,
1008				nil,
1009				[Matching.new do |reply|
1010					assert_equal :completed, reply.status
1011					assert_equal(
1012						xmpp_uri,
1013						OOB.find_or_create(reply.command).url
1014					)
1015				end]
1016			)
1017
1018			execute_command(blather: blather) do
1019				Command::COMMAND_MANAGER.expect(
1020					:write,
1021					EMPromise.resolve(subdomain_form),
1022					[Matching.new do |iq|
1023						assert_equal :form, iq.form.type
1024						assert iq.form.field("subdomain")
1025					end]
1026				)
1027
1028				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1029					:write,
1030					EMPromise.resolve(launched),
1031					[Matching.new do |iq|
1032						assert_equal :set, iq.type
1033						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1034						assert_equal(
1035							"test.snikket.chat",
1036							iq.xpath(
1037								"./ns:launch/ns:domain",
1038								ns: "xmpp:snikket.org/hosting/v1"
1039							).text
1040						)
1041					end]
1042				)
1043
1044				# Webmock doesn't support redirects properly, but they work live
1045				stub_request(
1046					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1047				).to_return(
1048					status: 200,
1049					headers: {
1050						"link" => "<#{xmpp_uri}>; rel=\"alternate\""
1051					}
1052				)
1053
1054				@snikket.write
1055			end
1056
1057			assert_mock Command::COMMAND_MANAGER
1058			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1059			assert_mock blather
1060		end
1061		em :test_write
1062
1063		def test_write_not_yet
1064			subdomain_form = Blather::Stanza::Iq::Command.new
1065			subdomain_form.form.fields = [
1066				{ var: "subdomain", value: "test" }
1067			]
1068
1069			launched = Snikket::Launched.new
1070			launched << Niceogiri::XML::Node.new(
1071				:launched, launched.document, "xmpp:snikket.org/hosting/v1"
1072			).tap { |inner|
1073				inner << Niceogiri::XML::Node.new(
1074					:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
1075				).tap { |id|
1076					id.content = "si-1234"
1077				}
1078				inner << Niceogiri::XML::Node.new(
1079					:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
1080				).tap { |bootstrap|
1081					bootstrap << Niceogiri::XML::Node.new(
1082						:token, launched.document, "xmpp:snikket.org/hosting/v1"
1083					).tap { |token|
1084						token.content = "TOKEN"
1085					}
1086				}
1087			}
1088
1089			result = execute_command do
1090				Command::COMMAND_MANAGER.expect(
1091					:write,
1092					EMPromise.resolve(subdomain_form),
1093					[Matching.new do |iq|
1094						assert_equal :form, iq.form.type
1095						assert iq.form.field("subdomain")
1096					end]
1097				)
1098
1099				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1100					:write,
1101					EMPromise.resolve(launched),
1102					[Matching.new do |iq|
1103						assert_equal :set, iq.type
1104						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1105						assert_equal(
1106							"test.snikket.chat",
1107							iq.xpath(
1108								"./ns:launch/ns:domain",
1109								ns: "xmpp:snikket.org/hosting/v1"
1110							).text
1111						)
1112					end]
1113				)
1114
1115				stub_request(
1116					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1117				).to_timeout
1118
1119				Command::COMMAND_MANAGER.expect(
1120					:write,
1121					EMPromise.reject(:test_result),
1122					[Matching.new do |iq|
1123						assert_equal :result, iq.form.type
1124						assert iq.form.instructions =~ / test\.snikket\.chat /
1125						assert_equal "jid-single", iq.form.field("support").type
1126					end]
1127				)
1128
1129				@snikket.write.catch { |e| e }
1130			end
1131
1132			assert_equal :test_result, result
1133			assert_mock Command::COMMAND_MANAGER
1134			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1135		end
1136		em :test_write_not_yet
1137
1138		def test_write_already_taken
1139			subdomain_form = Blather::Stanza::Iq::Command.new
1140			subdomain_form.form.fields = [
1141				{ var: "subdomain", value: "test" }
1142			]
1143
1144			launched = Snikket::Launched.new.as_error(
1145				"internal-server-error",
1146				:wait,
1147				"This is an error"
1148			)
1149
1150			result = execute_command do
1151				Command::COMMAND_MANAGER.expect(
1152					:write,
1153					EMPromise.resolve(subdomain_form),
1154					[Matching.new do |iq|
1155						assert_equal :form, iq.form.type
1156						assert iq.form.field("subdomain")
1157					end]
1158				)
1159
1160				Registration::FinishOnboarding::Snikket::IQ_MANAGER.expect(
1161					:write,
1162					EMPromise.reject(launched),
1163					[Matching.new do |iq|
1164						assert_equal :set, iq.type
1165						assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
1166						assert_equal(
1167							"test.snikket.chat",
1168							iq.xpath(
1169								"./ns:launch/ns:domain",
1170								ns: "xmpp:snikket.org/hosting/v1"
1171							).text
1172						)
1173					end]
1174				)
1175
1176				stub_request(
1177					:head, "https://test.snikket.chat/invites_bootstrap?token=TOKEN"
1178				).to_timeout
1179
1180				Command::COMMAND_MANAGER.expect(
1181					:write,
1182					EMPromise.reject(:test_result),
1183					[Matching.new do |iq|
1184						assert iq.executing?
1185						assert_equal(
1186							"This is an error",
1187							iq.form.field("subdomain").desc
1188						)
1189					end]
1190				)
1191
1192				@snikket.write.catch { |e| e }
1193			end
1194
1195			assert_equal :test_result, result
1196			assert_mock Command::COMMAND_MANAGER
1197			assert_mock Registration::FinishOnboarding::Snikket::IQ_MANAGER
1198		end
1199		em :test_write_already_taken
1200	end
1201end