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