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