# frozen_string_literal: true
require "test_helper"
require "customer"
require "registration"
class RegistrationTest < Minitest::Test
def test_for_registered
sgx = OpenStruct.new(
registered?: EMPromise.resolve(OpenStruct.new(phone: "+15555550000"))
)
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
result = Registration.for(
iq,
Customer.new("test", sgx: sgx),
Minitest::Mock.new
).sync
assert_kind_of Registration::Registered, result
end
em :test_for_registered
def test_for_activated
sgx = OpenStruct.new(registered?: EMPromise.resolve(nil))
web_manager = WebRegisterManager.new
web_manager["test@example.com"] = "+15555550000"
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
result = Registration.for(
iq,
Customer.new(
"test",
plan_name: "test_usd",
expires_at: Time.now + 999,
sgx: sgx
),
web_manager
).sync
assert_kind_of Registration::Finish, result
end
em :test_for_activated
def test_for_not_activated_with_customer_id
sgx = OpenStruct.new(registered?: EMPromise.resolve(nil))
web_manager = WebRegisterManager.new
web_manager["test@example.com"] = "+15555550000"
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
result = Registration.for(
iq,
Customer.new("test", sgx: sgx),
web_manager
).sync
assert_kind_of Registration::Activation, result
end
em :test_for_not_activated_with_customer_id
class ActivationTest < Minitest::Test
Registration::Activation::COMMAND_MANAGER = Minitest::Mock.new
def setup
iq = Blather::Stanza::Iq::Command.new
@activation = Registration::Activation.new(iq, "test", "+15555550000")
end
def test_write
stub_request(
:get,
"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
).to_return(status: 201, body: <<~RESPONSE)
<TelephoneNumberResponse>
<TelephoneNumber>5555550000</TelephoneNumber>
</TelephoneNumberResponse>
RESPONSE
stub_request(
:get,
"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
).to_return(status: 201, body: <<~RESPONSE)
<TelephoneNumberResponse>
<TelephoneNumberDetails>
<State>KE</State>
<RateCenter>FA</RateCenter>
</TelephoneNumberDetails>
</TelephoneNumberResponse>
RESPONSE
result = Minitest::Mock.new
result.expect(:then, result)
result.expect(:then, EMPromise.resolve(:test_result))
Registration::Activation::COMMAND_MANAGER.expect(
:write,
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
)
end]
)
assert_equal :test_result, @activation.write.sync
end
em :test_write
end
class PaymentTest < Minitest::Test
Customer::BRAINTREE = Minitest::Mock.new
Registration::Payment::Bitcoin::ELECTRUM = Minitest::Mock.new
def test_for_bitcoin
Registration::Payment::Bitcoin::ELECTRUM.expect(:createnewaddress, "addr")
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,
Customer.new("test"),
"+15555550000"
)
assert_kind_of Registration::Payment::Bitcoin, result
end
def test_for_credit_card
braintree_customer = Minitest::Mock.new
Customer::BRAINTREE.expect(
:customer,
braintree_customer
)
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,
Customer.new("test"),
"+15555550000"
).sync
assert_kind_of Registration::Payment::CreditCard, result
end
em :test_for_credit_card
def test_for_code
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,
Customer.new("test"),
"+15555550000"
)
assert_kind_of Registration::Payment::InviteCode, result
end
class BitcoinTest < Minitest::Test
Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
Registration::Payment::Bitcoin::BLATHER = Minitest::Mock.new
Customer::REDIS = Minitest::Mock.new
Customer::ELECTRUM = Minitest::Mock.new
def setup
Customer::ELECTRUM.expect(
:createnewaddress,
EMPromise.resolve("testaddr")
)
iq = Blather::Stanza::Iq::Command.new
@bitcoin = Registration::Payment::Bitcoin.new(
iq,
Customer.new("test", plan_name: "test_usd"),
"+15555550000"
)
end
def test_write
Customer::REDIS.expect(
:smembers,
EMPromise.resolve([]),
["jmp_customer_btc_addresses-test"]
)
Customer::REDIS.expect(
:sadd,
EMPromise.resolve(1),
["jmp_customer_btc_addresses-test", "testaddr"]
)
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
Registration::Payment::Bitcoin::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.new(1))
)
@bitcoin.stub(:save, EMPromise.resolve(nil)) do
@bitcoin.write.sync
end
Registration::Payment::Bitcoin::BLATHER.verify
end
em :test_write
end
class CreditCardTest < Minitest::Test
def setup
@iq = Blather::Stanza::Iq::Command.new
@iq.from = "test@example.com"
@credit_card = Registration::Payment::CreditCard.new(
@iq,
Customer.new("test"),
"+15555550000"
)
end
def test_for
customer = Minitest::Mock.new(Customer.new("test"))
customer.expect(
:payment_methods,
EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
)
assert_kind_of(
Registration::Payment::CreditCard::Activate,
Registration::Payment::CreditCard.for(
@iq,
customer,
"+15555550000"
).sync
)
end
em :test_for
def test_reply
assert_equal [:execute, :next], @credit_card.reply.allowed_actions
assert_equal(
"Add credit card, then return here and choose next: " \
"http://creditcard.example.com",
@credit_card.reply.note.content
)
end
end
class ActivateTest < Minitest::Test
Registration::Payment::CreditCard::Activate::Finish =
Minitest::Mock.new
Registration::Payment::CreditCard::Activate::Transaction =
Minitest::Mock.new
Registration::Payment::CreditCard::Activate::COMMAND_MANAGER =
Minitest::Mock.new
def test_write
transaction = PromiseMock.new
transaction.expect(
:insert,
EMPromise.resolve(nil)
)
customer = Minitest::Mock.new(
Customer.new("test", 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
iq = Blather::Stanza::Iq::Command.new
customer.expect(:bill_plan, nil)
Registration::Payment::CreditCard::Activate::Finish.expect(
:new,
OpenStruct.new(write: nil),
[Blather::Stanza::Iq, customer, "+15555550000"]
)
Registration::Payment::CreditCard::Activate.new(
iq,
customer,
:test_default_method,
"+15555550000"
).write.sync
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.new("test", plan_name: "test_usd")
)
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
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
result = Minitest::Mock.new
result.expect(:then, nil)
Registration::Payment::CreditCard::Activate::COMMAND_MANAGER.expect(
:write,
result,
[Matching.new do |reply|
assert_equal :error, reply.note_type
assert_equal(
Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE +
": http://creditcard.example.com",
reply.note.content
)
end]
)
Registration::Payment::CreditCard::Activate.new(
iq,
customer,
:test_default_method,
"+15555550000"
).write.sync
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
Registration::Payment::InviteCode::COMMAND_MANAGER =
Minitest::Mock.new
Registration::Payment::InviteCode::Finish =
Minitest::Mock.new
def test_write
customer = Customer.new("test", plan_name: "test_usd")
Registration::Payment::InviteCode::REDIS.expect(
:get,
EMPromise.resolve(nil),
["jmp_invite_tries-test"]
)
Registration::Payment::InviteCode::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::DB.expect(:transaction, true, [])
Registration::Payment::InviteCode::Finish.expect(
:new,
OpenStruct.new(write: nil),
[
Blather::Stanza::Iq::Command,
customer,
"+15555550000"
]
)
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
Registration::Payment::InviteCode.new(
iq,
customer,
"+15555550000"
).write.sync
Registration::Payment::InviteCode::COMMAND_MANAGER.verify
Registration::Payment::InviteCode::DB.verify
Registration::Payment::InviteCode::REDIS.verify
Registration::Payment::InviteCode::Finish.verify
end
em :test_write
def test_write_bad_code
customer = Customer.new("test", plan_name: "test_usd")
Registration::Payment::InviteCode::REDIS.expect(
:get,
EMPromise.resolve(0),
["jmp_invite_tries-test"]
)
Registration::Payment::InviteCode::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::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]
)
Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
:write,
EMPromise.reject(Promise::Error.new),
[Matching.new do |reply|
assert_equal :form, reply.form.type
assert_equal "wut", reply.form.instructions
end]
)
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
assert_raises Promise::Error do
Registration::Payment::InviteCode.new(
iq,
customer,
"+15555550000"
).write.sync
end
Registration::Payment::InviteCode::COMMAND_MANAGER.verify
Registration::Payment::InviteCode::DB.verify
Registration::Payment::InviteCode::REDIS.verify
end
em :test_write_bad_code
def test_write_bad_code_over_limit
customer = Customer.new("test", plan_name: "test_usd")
Registration::Payment::InviteCode::REDIS.expect(
:get,
EMPromise.resolve(11),
["jmp_invite_tries-test"]
)
Registration::Payment::InviteCode::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]
)
Registration::Payment::InviteCode::COMMAND_MANAGER.expect(
:write,
EMPromise.reject(Promise::Error.new),
[Matching.new do |reply|
assert_equal :form, reply.form.type
assert_equal "Too many wrong attempts", reply.form.instructions
end]
)
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
assert_raises Promise::Error do
Registration::Payment::InviteCode.new(
iq,
customer,
"+15555550000"
).write.sync
end
Registration::Payment::InviteCode::COMMAND_MANAGER.verify
Registration::Payment::InviteCode::REDIS.verify
end
em :test_write_bad_code_over_limit
end
end
class FinishTest < Minitest::Test
Registration::Finish::BLATHER = Minitest::Mock.new
Registration::Finish::REDIS = Minitest::Mock.new
BackendSgx::REDIS = Minitest::Mock.new
def setup
@sgx = Minitest::Mock.new(BackendSgx.new("test"))
iq = Blather::Stanza::Iq::Command.new
iq.from = "test\\40example.com@cheogram.com"
@finish = Registration::Finish.new(
iq,
Customer.new("test", 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)
<OrderResponse>
<Order>
<id>test_order</id>
</Order>
</OrderResponse>
RESPONSE
stub_request(
:get,
"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
).to_return(status: 201, body: <<~RESPONSE)
<OrderResponse>
<OrderStatus>COMPLETE</OrderStatus>
<CompletedNumbers>
<TelephoneNumber>
<FullNumber>5555550000</FullNumber>
</TelephoneNumber>
</CompletedNumbers>
</OrderResponse>
RESPONSE
stub_request(
:post,
"https://api.catapult.inetwork.com/v1/users/catapult_user/phoneNumbers"
).with(
body: open(__dir__ + "/data/catapult_import_body.json").read.chomp,
headers: {
"Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0",
"Content-Type" => "application/json"
}
).to_return(status: 201)
@sgx.expect(
:register!,
EMPromise.resolve(OpenStruct.new(error?: false)),
["+15555550000"]
)
Registration::Finish::REDIS.expect(
:set,
nil,
[
"catapult_fwd-+15555550000",
"sip:test%5C40example.com%40cheogram.com@sip.cheogram.com"
]
)
BackendSgx::REDIS.expect(
:set,
nil,
["catapult_fwd_timeout-customer_test@component", 25]
)
Registration::Finish::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]
)
@finish.write.sync
assert_requested create_order
@sgx.verify
Registration::Finish::REDIS.verify
BackendSgx::REDIS.verify
Registration::Finish::BLATHER.verify
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)
<OrderResponse>
<Order>
<id>test_order</id>
</Order>
</OrderResponse>
RESPONSE
stub_request(
:get,
"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
).to_return(status: 201, body: <<~RESPONSE)
<OrderResponse>
<OrderStatus>FAILED</OrderStatus>
</OrderResponse>
RESPONSE
Registration::Finish::BLATHER.expect(
:<<,
nil,
[Matching.new do |reply|
assert_equal :completed, reply.status
assert_equal :error, reply.note_type
assert_equal(
"The JMP number +15555550000 is no longer available, " \
"please visit https://jmp.chat and choose another.",
reply.note.content
)
end]
)
@finish.write.sync
assert_requested create_order
Registration::Finish::BLATHER.verify
end
em :test_write_tn_fail
end
end