# frozen_string_literal: true require "test_helper" require "customer" require "registration" class RegistrationTest < Minitest::Test def test_for_registered sgx = OpenStruct.new( registered?: OpenStruct.new(phone: "+15555550000") ) iq = Blather::Stanza::Iq::Command.new iq.from = "test@example.com" result = execute_command(iq) do Registration.for( customer(sgx: sgx), Minitest::Mock.new ) end assert_kind_of Registration::Registered, result end em :test_for_registered def test_for_activated web_manager = TelSelections.new(redis: FakeRedis.new) web_manager.set("test@example.net", "+15555550000") result = execute_command do sgx = OpenStruct.new(registered?: false) Registration.for( customer( plan_name: "test_usd", expires_at: Time.now + 999, sgx: sgx ), web_manager ) end assert_kind_of Registration::Finish, result end em :test_for_activated def test_for_not_activated_approved sgx = OpenStruct.new(registered?: false) web_manager = TelSelections.new(redis: FakeRedis.new) web_manager.set("test\\40approved.example.com@component", "+15555550000") iq = Blather::Stanza::Iq::Command.new iq.from = "test@approved.example.com" result = execute_command(iq) do Registration.for( customer( sgx: sgx, jid: Blather::JID.new("test\\40approved.example.com@component") ), web_manager ) end assert_kind_of Registration::Activation::Allow, result end em :test_for_not_activated_approved def test_for_not_activated_with_customer_id sgx = OpenStruct.new(registered?: false) web_manager = TelSelections.new(redis: FakeRedis.new) web_manager.set("test@example.net", "+15555550000") iq = Blather::Stanza::Iq::Command.new iq.from = "test@example.com" result = execute_command(iq) do Registration.for( customer(sgx: sgx), web_manager ) end assert_kind_of Registration::Activation, result end em :test_for_not_activated_with_customer_id class ActivationTest < Minitest::Test Command::COMMAND_MANAGER = Minitest::Mock.new def setup @activation = Registration::Activation.new("test", "+15555550000") end def test_write stub_request( :get, "https://dashboard.bandwidth.com/v1.0/tns/+15555550000" ).to_return(status: 201, body: <<~RESPONSE) 5555550000 RESPONSE stub_request( :get, "https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter" ).to_return(status: 201, body: <<~RESPONSE) KE FA RESPONSE Command::COMMAND_MANAGER.expect( :write, EMPromise.reject(:test_result), [Matching.new do |iq| assert_equal :form, iq.form.type assert_equal( "You've selected +15555550000 (FA, KE) as your JMP number.", iq.form.instructions.lines.first.chomp ) end] ) assert_equal( :test_result, execute_command { @activation.write.catch { |e| e } } ) assert_mock Command::COMMAND_MANAGER end em :test_write end class AllowTest < Minitest::Test Command::COMMAND_MANAGER = Minitest::Mock.new Registration::Activation::Allow::DB = Minitest::Mock.new def test_write_credit_to_nil cust = Minitest::Mock.new(customer("test")) allow = Registration::Activation::Allow.new(cust, "+15555550000", nil) stub_request( :get, "https://dashboard.bandwidth.com/v1.0/tns/+15555550000" ).to_return(status: 201, body: <<~RESPONSE) 5555550000 RESPONSE stub_request( :get, "https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter" ).to_return(status: 201, body: <<~RESPONSE) KE FA RESPONSE Command::COMMAND_MANAGER.expect( :write, EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq| iq.form.fields = [{ var: "plan_name", value: "test_usd" }] }), [Matching.new do |iq| assert_equal :form, iq.form.type assert_equal( "You've selected +15555550000 (FA, KE) as your JMP number.", iq.form.instructions.lines.first.chomp ) assert_equal 1, iq.form.fields.length end] ) Registration::Activation::Allow::DB.expect( :transaction, EMPromise.reject(:test_result) ) do |&blk| blk.call true end cust.expect(:with_plan, cust, ["test_usd"]) cust.expect(:activate_plan_starting_now, nil) assert_equal( :test_result, execute_command { allow.write.catch { |e| e } } ) assert_mock Command::COMMAND_MANAGER end em :test_write_credit_to_nil def test_write_credit_to_refercust cust = Minitest::Mock.new(customer("test")) allow = Registration::Activation::Allow.new( cust, "+15555550000", "refercust" ) stub_request( :get, "https://dashboard.bandwidth.com/v1.0/tns/+15555550000" ).to_return(status: 201, body: <<~RESPONSE) 5555550000 RESPONSE stub_request( :get, "https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter" ).to_return(status: 201, body: <<~RESPONSE) KE FA RESPONSE Command::COMMAND_MANAGER.expect( :write, EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq| iq.form.fields = [{ var: "plan_name", value: "test_usd" }] }), [Matching.new do |iq| assert_equal :form, iq.form.type assert_equal( "You've selected +15555550000 (FA, KE) as your JMP number.", iq.form.instructions.lines.first.chomp ) assert_equal 1, iq.form.fields.length end] ) Registration::Activation::Allow::DB.expect( :transaction, EMPromise.reject(:test_result) ) do |&blk| blk.call true end Registration::Activation::Allow::DB.expect( :exec, nil, [String, ["refercust", "test"]] ) cust.expect(:with_plan, cust, ["test_usd"]) cust.expect(:activate_plan_starting_now, nil) assert_equal( :test_result, execute_command { allow.write.catch { |e| e } } ) assert_mock Command::COMMAND_MANAGER end em :test_write_credit_to_refercust end class PaymentTest < Minitest::Test CustomerFinancials::BRAINTREE = Minitest::Mock.new def test_for_bitcoin cust = Minitest::Mock.new(customer) cust.expect(:with_plan, cust, ["test_usd"]) cust.expect(:save_plan!, nil) iq = Blather::Stanza::Iq::Command.new iq.form.fields = [ { var: "activation_method", value: "bitcoin" }, { var: "plan_name", value: "test_usd" } ] result = Registration::Payment.for(iq, cust, "+15555550000") assert_kind_of Registration::Payment::Bitcoin, result assert_mock cust end def test_for_credit_card cust = Minitest::Mock.new(customer) cust.expect(:with_plan, cust, ["test_usd"]) cust.expect(:save_plan!, nil) braintree_customer = Minitest::Mock.new CustomerFinancials::BRAINTREE.expect( :customer, braintree_customer ) CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"]) braintree_customer.expect( :find, EMPromise.resolve(OpenStruct.new(payment_methods: [])), ["test"] ) iq = Blather::Stanza::Iq::Command.new iq.from = "test@example.com" iq.form.fields = [ { var: "activation_method", value: "credit_card" }, { var: "plan_name", value: "test_usd" } ] result = Registration::Payment.for( iq, cust, "+15555550000" ).sync assert_kind_of Registration::Payment::CreditCard, result assert_mock cust end em :test_for_credit_card def test_for_code cust = Minitest::Mock.new(customer) cust.expect(:with_plan, cust, ["test_usd"]) cust.expect(:save_plan!, nil) iq = Blather::Stanza::Iq::Command.new iq.form.fields = [ { var: "activation_method", value: "code" }, { var: "plan_name", value: "test_usd" } ] result = Registration::Payment.for( iq, cust, "+15555550000" ) assert_kind_of Registration::Payment::InviteCode, result assert_mock cust end class BitcoinTest < Minitest::Test Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new CustomerFinancials::REDIS = Minitest::Mock.new def setup @customer = Minitest::Mock.new( customer(plan_name: "test_usd") ) @customer.expect( :add_btc_address, EMPromise.resolve("testaddr") ) @bitcoin = Registration::Payment::Bitcoin.new( @customer, "+15555550000" ) end def test_write CustomerFinancials::REDIS.expect( :smembers, EMPromise.resolve([]), ["jmp_customer_btc_addresses-test"] ) reply_text = <<~NOTE Activate your account by sending at least 1.000000 BTC to testaddr You will receive a notification when your payment is complete. NOTE blather = Minitest::Mock.new blather.expect( :<<, nil, [Matching.new do |reply| assert_equal :canceled, reply.status assert_equal :info, reply.note_type assert_equal reply_text, reply.note.content true end] ) Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect( :usd, EMPromise.resolve(BigDecimal(1)) ) @bitcoin.stub(:save, EMPromise.resolve(nil)) do execute_command(blather: blather) do @bitcoin.write end end assert_mock blather end em :test_write end class CreditCardTest < Minitest::Test def setup @credit_card = Registration::Payment::CreditCard.new( customer, "+15555550000" ) end def test_for customer = Minitest::Mock.new(customer) customer.expect( :payment_methods, EMPromise.resolve(OpenStruct.new(default_payment_method: :test)) ) assert_kind_of( Registration::Payment::CreditCard::Activate, Registration::Payment::CreditCard.for( customer, "+15555550000" ).sync ) end em :test_for def test_write result = execute_command do Command::COMMAND_MANAGER.expect( :write, EMPromise.reject(:test_result), [Matching.new do |reply| assert_equal [:execute, :next], reply.allowed_actions assert_equal( "Add credit card, then return here to continue: " \ "http://creditcard.example.com", reply.note.content ) end] ) @credit_card.write.catch { |e| e } end assert_equal :test_result, result end em :test_write end class ActivateTest < Minitest::Test Registration::Payment::CreditCard::Activate::Finish = Minitest::Mock.new Registration::Payment::CreditCard::Activate::Transaction = Minitest::Mock.new Command::COMMAND_MANAGER = Minitest::Mock.new def test_write transaction = PromiseMock.new transaction.expect( :insert, EMPromise.resolve(nil) ) customer = Minitest::Mock.new( customer(plan_name: "test_usd") ) Registration::Payment::CreditCard::Activate::Transaction.expect( :sale, transaction ) do |acustomer, amount:, payment_method:| assert_operator customer, :===, acustomer assert_equal CONFIG[:activation_amount], amount assert_equal :test_default_method, payment_method end customer.expect(:bill_plan, nil, [{ note: "Bill for first month" }]) Registration::Payment::CreditCard::Activate::Finish.expect( :new, OpenStruct.new(write: nil), [customer, "+15555550000"] ) execute_command do Registration::Payment::CreditCard::Activate.new( customer, :test_default_method, "+15555550000" ).write end Registration::Payment::CreditCard::Activate::Transaction.verify transaction.verify customer.verify Registration::Payment::CreditCard::Activate::Finish.verify end em :test_write def test_write_declines customer = Minitest::Mock.new( customer(plan_name: "test_usd") ) iq = Blather::Stanza::Iq::Command.new iq.from = "test@example.com" msg = Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE Command::COMMAND_MANAGER.expect( :write, EMPromise.reject(:test_result), [Matching.new do |reply| assert_equal :error, reply.note_type assert_equal( "#{msg}: http://creditcard.example.com", reply.note.content ) end] ) result = execute_command do Registration::Payment::CreditCard::Activate::Transaction.expect( :sale, EMPromise.reject("declined") ) do |acustomer, amount:, payment_method:| assert_operator customer, :===, acustomer assert_equal CONFIG[:activation_amount], amount assert_equal :test_default_method, payment_method end Registration::Payment::CreditCard::Activate.new( customer, :test_default_method, "+15555550000" ).write.catch { |e| e } end assert_equal :test_result, result Registration::Payment::CreditCard::Activate::Transaction.verify end em :test_write_declines end class InviteCodeTest < Minitest::Test Registration::Payment::InviteCode::DB = Minitest::Mock.new Registration::Payment::InviteCode::REDIS = Minitest::Mock.new Command::COMMAND_MANAGER = Minitest::Mock.new Registration::Payment::InviteCode::Finish = Minitest::Mock.new def test_write customer = customer(plan_name: "test_usd") Registration::Payment::InviteCode::DB.expect(:transaction, true, []) Registration::Payment::InviteCode::Finish.expect( :new, OpenStruct.new(write: nil), [ customer, "+15555550000" ] ) execute_command do Registration::Payment::InviteCode::REDIS.expect( :get, EMPromise.resolve(nil), ["jmp_invite_tries-test"] ) Command::COMMAND_MANAGER.expect( :write, EMPromise.resolve( Blather::Stanza::Iq::Command.new.tap { |iq| iq.form.fields = [{ var: "code", value: "abc" }] } ), [Matching.new do |reply| assert_equal :form, reply.form.type assert_nil reply.form.instructions end] ) Registration::Payment::InviteCode.new( customer, "+15555550000" ).write end assert_mock Command::COMMAND_MANAGER assert_mock Registration::Payment::InviteCode::DB assert_mock Registration::Payment::InviteCode::REDIS assert_mock Registration::Payment::InviteCode::Finish end em :test_write def test_write_bad_code result = execute_command do customer = customer(plan_name: "test_usd") Registration::Payment::InviteCode::REDIS.expect( :get, EMPromise.resolve(0), ["jmp_invite_tries-test"] ) Registration::Payment::InviteCode::DB.expect(:transaction, []) do raise Registration::Payment::InviteCode::Invalid, "wut" end Registration::Payment::InviteCode::REDIS.expect( :incr, EMPromise.resolve(nil), ["jmp_invite_tries-test"] ) Registration::Payment::InviteCode::REDIS.expect( :expire, EMPromise.resolve(nil), ["jmp_invite_tries-test", 60 * 60] ) Command::COMMAND_MANAGER.expect( :write, EMPromise.resolve( Blather::Stanza::Iq::Command.new.tap { |iq| iq.form.fields = [{ var: "code", value: "abc" }] } ), [Matching.new do |reply| assert_equal :form, reply.form.type assert_nil reply.form.instructions end] ) Command::COMMAND_MANAGER.expect( :write, EMPromise.reject(:test_result), [Matching.new do |reply| assert_equal :form, reply.form.type assert_equal "wut", reply.form.instructions end] ) Registration::Payment::InviteCode.new( customer, "+15555550000" ).write.catch { |e| e } end assert_equal :test_result, result assert_mock Command::COMMAND_MANAGER assert_mock Registration::Payment::InviteCode::DB assert_mock Registration::Payment::InviteCode::REDIS end em :test_write_bad_code def test_write_bad_code_over_limit result = execute_command do customer = customer(plan_name: "test_usd") Registration::Payment::InviteCode::REDIS.expect( :get, EMPromise.resolve(11), ["jmp_invite_tries-test"] ) Command::COMMAND_MANAGER.expect( :write, EMPromise.resolve( Blather::Stanza::Iq::Command.new.tap { |iq| iq.form.fields = [{ var: "code", value: "abc" }] } ), [Matching.new do |reply| assert_equal :form, reply.form.type assert_nil reply.form.instructions end] ) Registration::Payment::InviteCode::REDIS.expect( :incr, EMPromise.resolve(nil), ["jmp_invite_tries-test"] ) Registration::Payment::InviteCode::REDIS.expect( :expire, EMPromise.resolve(nil), ["jmp_invite_tries-test", 60 * 60] ) Command::COMMAND_MANAGER.expect( :write, EMPromise.reject(:test_result), [Matching.new do |reply| assert_equal :form, reply.form.type assert_equal "Too many wrong attempts", reply.form.instructions end] ) Registration::Payment::InviteCode.new( customer, "+15555550000" ).write.catch { |e| e } end assert_equal :test_result, result assert_mock Command::COMMAND_MANAGER assert_mock Registration::Payment::InviteCode::REDIS end em :test_write_bad_code_over_limit end end class FinishTest < Minitest::Test Command::COMMAND_MANAGER = Minitest::Mock.new Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new Registration::Finish::REDIS = Minitest::Mock.new Bwmsgsv2Repo::REDIS = Minitest::Mock.new def setup @sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test")) iq = Blather::Stanza::Iq::Command.new iq.from = "test\\40example.com@cheogram.com" @finish = Registration::Finish.new( customer(sgx: @sgx), "+15555550000" ) end def test_write create_order = stub_request( :post, "https://dashboard.bandwidth.com/v1.0/accounts//orders" ).to_return(status: 201, body: <<~RESPONSE) test_order RESPONSE stub_request( :get, "https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order" ).to_return(status: 201, body: <<~RESPONSE) COMPLETE 5555550000 RESPONSE stub_request( :post, "https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns" ) Registration::Finish::REDIS.expect( :del, nil, ["pending_tel_for-test@example.net"] ) Bwmsgsv2Repo::REDIS.expect( :set, nil, [ "catapult_fwd-+15555550000", "xmpp:test@example.net" ] ) Bwmsgsv2Repo::REDIS.expect( :set, nil, ["catapult_fwd_timeout-customer_test@component", 25] ) blather = Minitest::Mock.new blather.expect( :<<, nil, [Matching.new do |reply| assert_equal :completed, reply.status assert_equal :info, reply.note_type assert_equal( "Your JMP account has been activated as +15555550000", reply.note.content ) end] ) execute_command(blather: blather) do @sgx.expect( :register!, EMPromise.resolve(@sgx.with(registered?: IBR.new.tap do |ibr| ibr.phone = "+15555550000" end)), ["+15555550000"] ) @finish.write end assert_requested create_order assert_mock @sgx assert_mock Registration::Finish::REDIS assert_mock Bwmsgsv2Repo::REDIS assert_mock blather end em :test_write def test_write_tn_fail create_order = stub_request( :post, "https://dashboard.bandwidth.com/v1.0/accounts//orders" ).to_return(status: 201, body: <<~RESPONSE) test_order RESPONSE stub_request( :get, "https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order" ).to_return(status: 201, body: <<~RESPONSE) FAILED RESPONSE result = execute_command do Command::COMMAND_MANAGER.expect( :write, EMPromise.reject(:test_result), [Matching.new do |iq| assert_equal :form, iq.form.type assert_equal( "The JMP number +15555550000 is no longer available.", iq.form.instructions ) end] ) @finish.write.catch { |e| e } end assert_equal :test_result, result assert_mock Command::COMMAND_MANAGER assert_instance_of( TelSelections::ChooseTel, Registration::Finish::TEL_SELECTIONS["test@example.com"] ) assert_requested create_order end em :test_write_tn_fail end end