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