2018-03-25 16:15:39 +00:00
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
2018-03-25 17:30:42 +00:00
require 'rails_helper'
require 'stripe_mock'
describe InsertCharge do
include_context :shared_donation_charge_context
let! ( :donation ) { force_create ( :donation , id : 555 ) }
describe '.with_stripe' do
before ( :each ) {
Settings . payment_provider . stripe_connect = true
}
describe 'param validation' do
it 'does basic validation' do
expect { InsertCharge . with_stripe ( nil ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( error . data ,
[
{ :key = > :amount , :name = > :required } ,
{ :key = > :amount , :name = > :is_integer } ,
{ :key = > :amount , :name = > :min } ,
{ :key = > :nonprofit_id , :name = > :required } ,
{ :key = > :nonprofit_id , :name = > :is_integer } ,
{ :key = > :supporter_id , :name = > :required } ,
{ :key = > :supporter_id , :name = > :is_integer } ,
{ :key = > :card_id , :name = > :required } ,
{ :key = > :card_id , :name = > :is_integer } ,
{ :key = > :statement , :name = > :required } ,
{ :key = > :statement , :name = > :not_blank }
] )
} )
end
it 'verify the amount minimum works' do
expect { InsertCharge . with_stripe ( { amount : - 1 } ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( error . data ,
[
{ :key = > :amount , :name = > :min } ,
{ :key = > :nonprofit_id , :name = > :required } ,
{ :key = > :nonprofit_id , :name = > :is_integer } ,
{ :key = > :supporter_id , :name = > :required } ,
{ :key = > :supporter_id , :name = > :is_integer } ,
{ :key = > :card_id , :name = > :required } ,
{ :key = > :card_id , :name = > :is_integer } ,
{ :key = > :statement , :name = > :required } ,
{ :key = > :statement , :name = > :not_blank }
] )
} )
end
it 'verify that we check for valid nonprofit' do
expect { InsertCharge . with_stripe ( { amount : 100 ,
:nonprofit_id = > 5555 ,
:supporter_id = > 5555 ,
:card_id = > 5555 ,
:statement = > 'our statement' } ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( error . data ,
[
{ :key = > :nonprofit_id }
] )
} )
end
it 'verify that we check for valid supporter' do
expect { InsertCharge . with_stripe ( { amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > 5555 ,
:card_id = > 5555 ,
:statement = > 'our statement' } ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( error . data ,
[
{ :key = > :supporter_id }
] )
} )
end
it 'verify that we check for valid card' do
expect { InsertCharge . with_stripe ( { amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > 5555 ,
:statement = > 'our statement' } ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( error . data ,
[
{ :key = > :card_id }
] )
} )
end
it 'verify that we check that the supporter belongs to the correct nonprofit' do
expect { InsertCharge . with_stripe ( { amount : 100 ,
:nonprofit_id = > other_nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:statement = > 'our statement' } ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect ( error . message ) . to eq " #{ supporter . id } does not belong to this nonprofit #{ other_nonprofit . id } "
expect_validation_errors ( error . data ,
[
{ :key = > :supporter_id }
] )
} )
end
it 'verify that we check that the card belongs to the correct supporter' do
expect { InsertCharge . with_stripe ( { amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card_for_other_supporter . id ,
:statement = > 'our statement' } ) } . to ( raise_error { | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
expect ( error . message ) . to eq " #{ card_for_other_supporter . id } does not belong to this supporter #{ supporter . id } "
expect_validation_errors ( error . data ,
[
{ :key = > :card_id }
] )
} )
end
end
describe 'handle StripeAccount Find and Create failure' do
before ( :each ) {
StripeMock . prepare_error ( Stripe :: StripeError . new ( " chaos " ) , :new_account )
}
it 'does it fail properly' do
expect { InsertCharge . with_stripe ( amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:statement = > 'our statement' ) } . to ( raise_error { | error |
expect ( error ) . to be_a Stripe :: StripeError
} )
expect ( Charge ) . to_not be_exists
expect ( Payment ) . to_not be_exists
end
end
describe 'charge when customer belongs to client' do
before ( :each ) {
nonprofit . stripe_account_id = Stripe :: Account . create ( ) [ 'id' ]
nonprofit . save!
card . stripe_customer_id = 'some other id'
card . save!
StripeMock . prepare_error ( Stripe :: StripeError . new ( " chaos " ) , :get_customer )
}
it 'handles card error' do
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( { application_fee : 33 ,
customer : card . stripe_customer_id ,
amount : 100 ,
currency : 'usd' ,
description : 'our statement<> blah-no-way' ,
statement_descriptor : 'our statement blah-n' ,
metadata : nil
} , { stripe_account : nonprofit . stripe_account_id } ) . and_wrap_original { | m , * args | m . call ( * args ) }
StripeMock . prepare_card_error ( :card_declined )
finished_result = InsertCharge . with_stripe ( amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:statement = > 'our statement<> blah-no-way' )
common_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : nil , status : 'failed' , failure_message : 'There was an error with your card: The card was declined' , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_expected = common_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : nil , supporter_id : supporter . id , ticket_id : nil , payment_id : nil , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_expected
expect ( Charge . first . attributes ) . to eq result_expected
expect ( Payment ) . to_not be_exists
end
it 'handles general Stripe error' do
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( { application_fee : 33 ,
customer : card . stripe_customer_id ,
amount : 100 ,
currency : 'usd' ,
description : 'our statement<> blah-no-way' ,
statement_descriptor : 'our statement blah-n' ,
metadata : nil
} , { stripe_account : nonprofit . stripe_account_id } ) . and_wrap_original { | m , * args | m . call ( * args ) }
StripeMock . prepare_error ( Stripe :: StripeError . new ( " blah " ) , :new_charge )
finished_result = InsertCharge . with_stripe ( amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:statement = > 'our statement<> blah-no-way' )
common_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : nil , status : 'failed' , failure_message : " We're sorry, but something went wrong. We've been notified about this issue. " , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_expected = common_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : nil , supporter_id : supporter . id , ticket_id : nil , payment_id : nil , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_expected
expect ( Charge . first . attributes ) . to eq result_expected
expect ( Payment ) . to_not be_exists
end
describe 'input success' do
let ( :valid_input ) { { amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:donation_id = > 555 ,
:towards = > 'blah' ,
:kind = > 'kind' ,
:statement = > 'our statement<> blah-no-way' } }
let ( :date ) { Time . new ( 2002 , 10 , 31 ) }
let ( :valid_input_with_date ) { valid_input . merge ( :date = > date ) }
it 'saves the payment and updates the charge' do
stripe_charge_id = nil
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( { application_fee : 33 ,
customer : card . stripe_customer_id ,
amount : 100 ,
currency : 'usd' ,
description : 'our statement<> blah-no-way' ,
statement_descriptor : 'our statement blah-n' ,
metadata : nil
} , { stripe_account : nonprofit . stripe_account_id } ) . and_wrap_original { | m , * args | a = m . call ( * args ) ;
stripe_charge_id = a [ 'id' ]
a }
finished_result = InsertCharge . with_stripe ( valid_input )
common_charge_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : stripe_charge_id , status : 'pending' , failure_message : nil , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_charge_expected = common_charge_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : 555 , supporter_id : supporter . id , ticket_id : nil , payment_id : Payment . first . id , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_charge_expected
expect ( Charge . first . attributes ) . to eq result_charge_expected
expect ( Charge . count ) . to eq 1
common_payment_expected = { id : Payment . first . id ,
gross_amount : 100 ,
fee_total : - 33 ,
net_amount : 67 ,
towards : 'blah' ,
kind : 'kind' ,
donation_id : 555 ,
nonprofit_id : nonprofit . id ,
supporter_id : supporter . id ,
refund_total : 0 ,
date : Time . now ,
created_at : Time . now ,
updated_at : Time . now ,
search_vectors : nil
} . with_indifferent_access
expect ( finished_result [ 'payment' ] . attributes ) . to eq common_payment_expected
expect ( Payment . first . attributes ) . to eq common_payment_expected
expect ( Payment . count ) . to eq 1
end
it 'saves the payment and updates the charge with passed date' do
stripe_charge_id = nil
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( { application_fee : 33 ,
customer : card . stripe_customer_id ,
amount : 100 ,
currency : 'usd' ,
description : 'our statement<> blah-no-way' ,
statement_descriptor : 'our statement blah-n' ,
metadata : nil
} , { stripe_account : nonprofit . stripe_account_id } ) . and_wrap_original { | m , * args | a = m . call ( * args ) ;
stripe_charge_id = a [ 'id' ]
a }
finished_result = InsertCharge . with_stripe ( valid_input_with_date )
common_charge_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : stripe_charge_id , status : 'pending' , failure_message : nil , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_charge_expected = common_charge_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : 555 , supporter_id : supporter . id , ticket_id : nil , payment_id : Payment . first . id , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_charge_expected
expect ( Charge . first . attributes ) . to eq result_charge_expected
expect ( Charge . count ) . to eq 1
common_payment_expected = { id : Payment . first . id ,
gross_amount : 100 ,
fee_total : - 33 ,
net_amount : 67 ,
towards : 'blah' ,
kind : 'kind' ,
donation_id : 555 ,
nonprofit_id : nonprofit . id ,
supporter_id : supporter . id ,
refund_total : 0 ,
date : date ,
created_at : Time . now ,
updated_at : Time . now ,
search_vectors : nil
} . with_indifferent_access
expect ( finished_result [ 'payment' ] . attributes ) . to eq common_payment_expected
expect ( Payment . first . attributes ) . to eq common_payment_expected
expect ( Payment . count ) . to eq 1
end
end
end
describe 'charge when customer belongs to us' do
before ( :each ) {
nonprofit . stripe_account_id = Stripe :: Account . create ( ) [ 'id' ]
nonprofit . save!
card . stripe_customer_id = 'some other id'
cust = Stripe :: Customer . create ( )
card . stripe_customer_id = cust [ 'id' ]
card . save!
new_cust = Stripe :: Customer . create ( )
card_for_other_supporter . stripe_customer_id = new_cust [ 'id' ]
card_for_other_supporter . save!
# StripeMock.prepare_error(Stripe::StripeError.new("chaos"), :get_customer)
}
def create_expected_charge_args ( expected_card )
[ { application_fee : 33 ,
customer : expected_card . stripe_customer_id ,
amount : 100 ,
currency : 'usd' ,
description : 'our statement<> blah-no-way' ,
statement_descriptor : 'our statement blah-n' ,
metadata : nil ,
destination : nonprofit . stripe_account_id
} , { } ]
end
it 'handles card error' do
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( * create_expected_charge_args ( card ) ) . and_wrap_original { | m , * args | m . call ( * args ) }
StripeMock . prepare_card_error ( :card_declined )
finished_result = InsertCharge . with_stripe ( amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:statement = > 'our statement<> blah-no-way' )
common_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : nil , status : 'failed' , failure_message : 'There was an error with your card: The card was declined' , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_expected = common_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : nil , supporter_id : supporter . id , ticket_id : nil , payment_id : nil , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_expected
expect ( Charge . first . attributes ) . to eq result_expected
expect ( Payment ) . to_not be_exists
end
it 'handles general Stripe error' do
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( * create_expected_charge_args ( card ) ) . and_wrap_original { | m , * args | m . call ( * args ) }
StripeMock . prepare_error ( Stripe :: StripeError . new ( " blah " ) , :new_charge )
finished_result = InsertCharge . with_stripe ( amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
:card_id = > card . id ,
:statement = > 'our statement<> blah-no-way' )
common_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : nil , status : 'failed' , failure_message : " We're sorry, but something went wrong. We've been notified about this issue. " , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_expected = common_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : nil , supporter_id : supporter . id , ticket_id : nil , payment_id : nil , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_expected
expect ( Charge . first . attributes ) . to eq result_expected
expect ( Payment ) . to_not be_exists
end
describe 'input success' do
let ( :date ) { Time . new ( 2002 , 10 , 31 ) }
it 'saves the payment and updates the charge' do
saves_the_payment_updates_the_charge ( card )
end
it 'saves the payment and updates the charge, if old rd and using wrong card' do
saves_the_payment_updates_the_charge ( card_for_other_supporter , true )
end
it 'saves the payment and updates the charge with passed date' do
saves_the_payment_and_updates_the_charge_with_passed_date ( card )
end
it 'saves the payment and updates the charge with passed date, if old rd and using wrong card' do
saves_the_payment_and_updates_the_charge_with_passed_date ( card , true )
end
def insert_charge_input ( expected_card , pass_old_donation = nil , pass_date = nil )
inner = { amount : 100 ,
:nonprofit_id = > nonprofit . id ,
:supporter_id = > supporter . id ,
card_id : expected_card . id ,
:donation_id = > 555 ,
:towards = > 'blah' ,
:kind = > 'kind' ,
:statement = > 'our statement<> blah-no-way' ,
}
if pass_old_donation
inner = inner . merge ( old_donation : true )
end
if pass_date
inner = inner . merge ( date : date )
end
inner
end
def saves_the_payment_updates_the_charge ( expected_card , pass_old_donation = nil )
stripe_charge_id = nil
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( * create_expected_charge_args ( expected_card ) ) . and_wrap_original { | m , * args | a = m . call ( * args ) ;
stripe_charge_id = a [ 'id' ]
a }
finished_result = InsertCharge . with_stripe ( insert_charge_input ( expected_card , pass_old_donation ) )
common_charge_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : stripe_charge_id , status : 'pending' , failure_message : nil , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_charge_expected = common_charge_expected . merge ( { card_id : expected_card . id , nonprofit_id : nonprofit . id , donation_id : 555 , supporter_id : supporter . id , ticket_id : nil , payment_id : Payment . first . id , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_charge_expected
expect ( Charge . first . attributes ) . to eq result_charge_expected
expect ( Charge . count ) . to eq 1
common_payment_expected = { id : Payment . first . id ,
gross_amount : 100 ,
fee_total : - 33 ,
net_amount : 67 ,
towards : 'blah' ,
kind : 'kind' ,
donation_id : 555 ,
nonprofit_id : nonprofit . id ,
supporter_id : supporter . id ,
refund_total : 0 ,
date : Time . now ,
created_at : Time . now ,
updated_at : Time . now ,
search_vectors : nil
} . with_indifferent_access
expect ( finished_result [ 'payment' ] . attributes ) . to eq common_payment_expected
expect ( Payment . first . attributes ) . to eq common_payment_expected
expect ( Payment . count ) . to eq 1
end
def saves_the_payment_and_updates_the_charge_with_passed_date ( expected_card , pass_old_donation = nil )
stripe_charge_id = nil
expect ( Stripe :: Charge ) . to receive ( :create ) . with ( * create_expected_charge_args ( expected_card ) ) . and_wrap_original { | m , * args | a = m . call ( * args ) ;
stripe_charge_id = a [ 'id' ]
a }
finished_result = InsertCharge . with_stripe ( insert_charge_input ( expected_card , pass_old_donation , true ) )
common_charge_expected = { id : Charge . first . id , amount : 100 , fee : 33 , stripe_charge_id : stripe_charge_id , status : 'pending' , failure_message : nil , created_at : Time . now , updated_at : Time . now , disbursed : nil }
result_charge_expected = common_charge_expected . merge ( { card_id : card . id , nonprofit_id : nonprofit . id , donation_id : 555 , supporter_id : supporter . id , ticket_id : nil , payment_id : Payment . first . id , profile_id : nil , direct_debit_detail_id : nil } ) . with_indifferent_access
expect ( finished_result [ 'charge' ] . attributes ) . to eq result_charge_expected
expect ( Charge . first . attributes ) . to eq result_charge_expected
expect ( Charge . count ) . to eq 1
common_payment_expected = { id : Payment . first . id ,
gross_amount : 100 ,
fee_total : - 33 ,
net_amount : 67 ,
towards : 'blah' ,
kind : 'kind' ,
donation_id : 555 ,
nonprofit_id : nonprofit . id ,
supporter_id : supporter . id ,
refund_total : 0 ,
date : date ,
created_at : Time . now ,
updated_at : Time . now ,
search_vectors : nil
} . with_indifferent_access
expect ( finished_result [ 'payment' ] . attributes ) . to eq common_payment_expected
expect ( Payment . first . attributes ) . to eq common_payment_expected
expect ( Payment . count ) . to eq 1
end
end
end
end
end