2019-07-30 21:29:24 +00:00
# frozen_string_literal: true
2020-06-12 20:03:43 +00:00
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
2018-03-25 17:30:42 +00:00
require 'rails_helper'
describe UpdateRecurringDonations do
# deactivate a recurring donation
describe '.cancel' do
2021-02-15 23:22:19 +00:00
let! ( :np ) { force_create ( :nm_justice ) }
2021-01-19 20:00:23 +00:00
let ( :s ) { force_create ( :supporter , nonprofit : np ) }
2019-07-30 21:29:24 +00:00
let ( :donation ) { force_create ( :donation , nonprofit_id : np . id , supporter_id : s . id ) }
let ( :email ) { 'test@test.com' }
let! ( :rd ) do
inner_rd = force_create ( :recurring_donation , amount : 999 , active : true , supporter_id : s . id , donation_id : donation . id , nonprofit_id : np . id )
UpdateRecurringDonations . cancel ( inner_rd . id , email )
end
2018-03-25 17:30:42 +00:00
it 'sets active to false' do
expect ( rd [ 'active' ] ) . to eq false
end
it 'sets cancelled_at to today' do
2019-08-02 08:57:17 +00:00
expect ( rd [ 'cancelled_at' ] . to_date . end_of_day ) . to eq ( Time . now . end_of_day )
2018-03-25 17:30:42 +00:00
end
it 'sets the cancelled_by to the given email' do
expect ( rd [ 'cancelled_by' ] ) . to eq email
end
it 'returns the full fetch_for_edit data' do
expect ( rd [ 'nonprofit_name' ] ) . to eq np . name
end
it 'creates a supporter note table describing the cancellation' do
note = Qx . select ( :content ) . from ( :supporter_notes ) . limit ( 1 ) . order_by ( 'id DESC' ) . execute . first
2019-07-30 21:29:24 +00:00
expect ( note [ 'content' ] ) . to include ( 'cancelled' )
2018-03-25 17:30:42 +00:00
end
end
describe '.update_amount' do
include_context :shared_rd_donation_value_context
describe 'param validation' do
it 'rejects totally invalid data' do
2019-07-30 21:29:24 +00:00
expect { UpdateRecurringDonations . update_amount ( nil , nil , nil ) }
2018-03-25 17:30:42 +00:00
. to ( raise_error do | error |
expect ( error ) . to be_a ParamValidation :: ValidationError
2019-07-30 21:29:24 +00:00
expect_validation_errors ( error , [ { key : 'rd' , name : :required } ,
{ key : 'rd' , name : :is_a } ,
{ key : :token , name : :required } ,
{ key : :token , name : :format } ,
{ key : 'amount' , name : :required } ,
{ key : 'amount' , name : :is_integer } ,
{ key : 'amount' , name : :min } ] )
2018-03-25 17:30:42 +00:00
end )
end
end
describe 'token validation' do
it 'invalid token errors' do
2019-07-30 21:29:24 +00:00
validation_invalid_token { UpdateRecurringDonations . update_amount ( recurring_donation , fake_uuid , 500 ) }
2018-03-25 17:30:42 +00:00
end
it 'unauthorized token errors' do
2019-07-30 21:29:24 +00:00
validation_unauthorized { UpdateRecurringDonations . update_amount ( recurring_donation , fake_uuid , 500 ) }
2018-03-25 17:30:42 +00:00
end
it 'validation expired errors' do
2019-07-30 21:29:24 +00:00
validation_expired { UpdateRecurringDonations . update_amount ( recurring_donation , fake_uuid , 500 ) }
2018-03-25 17:30:42 +00:00
end
end
describe 'validate entities' do
it 'errors when rd is cancelled' do
2019-07-30 21:29:24 +00:00
error_when_rd_cancelled { UpdateRecurringDonations . update_amount ( recurring_donation , source_token . id , 500 ) }
2018-03-25 17:30:42 +00:00
end
it 'errors when card is deleted' do
2019-07-30 21:29:24 +00:00
error_when_card_deleted { UpdateRecurringDonations . update_amount ( recurring_donation , source_token . id , 500 ) }
2018-03-25 17:30:42 +00:00
end
it 'errors when card holder and supporter arent the same' do
2019-07-30 21:29:24 +00:00
errors_when_card_holder_and_supporter_neq { UpdateRecurringDonations . update_amount ( recurring_donation , other_source_token . id , 500 ) }
2018-03-25 17:30:42 +00:00
end
end
2021-06-07 18:56:03 +00:00
let ( :np_builder_expanded ) do
{
'id' = > nonprofit . id ,
'name' = > nonprofit . name ,
'object' = > 'nonprofit'
}
end
let ( :supporter_builder_expanded ) do
supporter_to_builder_base . merge ( { 'name' = > 'Fake Supporter Name' } )
end
let ( :common_builder_expanded ) do
{
'supporter' = > supporter_builder_expanded ,
'nonprofit' = > np_builder_expanded
}
end
2018-03-25 17:30:42 +00:00
it 'changes amount properly' do
recurring_donation . n_failures = 2
recurring_donation . save!
2021-06-07 18:56:03 +00:00
recurrence
orig_recurrence = recurring_donation . recurrence
2018-03-25 17:30:42 +00:00
orig_rd = recurring_donation . attributes . with_indifferent_access
orig_donation = recurring_donation . donation . attributes . with_indifferent_access
2021-06-07 18:56:03 +00:00
expect ( Houdini . event_publisher ) . to receive ( :announce ) . with ( :recurrence_updated , {
'id' = > match_houid ( 'objevt' ) ,
'object' = > 'object_event' ,
'type' = > 'recurrence.updated' ,
'data' = > {
'object' = > common_builder_expanded . merge ( {
'object' = > 'recurrence' ,
'id' = > orig_recurrence . id ,
'start_date' = > orig_recurrence . start_date ,
'recurrences' = > [
{
'interval' = > 1 ,
'type' = > 'monthly'
} ] ,
'invoice_template' = > {
'supporter' = > supporter . id ,
'amount' = > { 'cents' = > 1000 , 'currency' = > 'usd' } ,
'payment_method' = > { 'type' = > 'stripe' } ,
'trx_assignments' = > [
{
'assignment_object' = > 'donation' ,
'designation' = > nil ,
'amount' = > { 'cents' = > 1000 , 'currency' = > 'usd' }
} ]
}
} )
} } )
2018-03-25 17:30:42 +00:00
2019-11-07 18:45:57 +00:00
result = nil
expect {
result = UpdateRecurringDonations . update_amount ( recurring_donation ,
source_token . token , 1000 )
2019-11-08 17:24:42 +00:00
} . to have_enqueued_job ( RecurringDonationChangeAmountJob ) . with ( recurring_donation , orig_rd [ 'amount' ] )
2018-03-25 17:30:42 +00:00
expectations = {
2019-07-30 21:29:24 +00:00
donation : orig_donation . merge ( amount : 1000 , card_id : source_token . tokenizable . id ) ,
recurring_donation : orig_rd . merge ( amount : 1000 , n_failures : 0 , start_date : Time . current . to_date )
2018-03-25 17:30:42 +00:00
}
2021-06-07 18:56:03 +00:00
2018-03-25 17:30:42 +00:00
expect ( result . attributes ) . to eq expectations [ :recurring_donation ]
recurring_donation . reload
donation_for_rd . reload
2019-07-30 21:29:24 +00:00
expect ( recurring_donation . attributes ) . to eq expectations [ :recurring_donation ]
2018-03-25 17:30:42 +00:00
expect ( donation_for_rd . attributes ) . to eq expectations [ :donation ]
end
end
describe '.update_card_id' do
include_context :shared_rd_donation_value_context
describe 'basic validation' do
it 'basic param validation' do
2019-07-30 21:29:24 +00:00
expect { UpdateRecurringDonations . update_card_id ( nil , nil ) } . to raise_error { | e |
2018-03-25 17:30:42 +00:00
expect ( e ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( e . data , [
2019-07-30 21:29:24 +00:00
{ key : :rd , name : :is_hash } ,
{ key : :rd , name : :required } ,
{ key : :token , name : :required } ,
{ key : :token , name : :format }
] )
2018-03-25 17:30:42 +00:00
}
end
it 'rd[:id] validation' do
2019-07-30 21:29:24 +00:00
expect { UpdateRecurringDonations . update_card_id ( { } , fake_uuid ) } . to raise_error { | e |
2018-03-25 17:30:42 +00:00
expect ( e ) . to be_a ParamValidation :: ValidationError
expect_validation_errors ( e . data , [
2019-07-30 21:29:24 +00:00
{ key : :id , name : :is_reference } ,
{ key : :id , name : :required }
] )
2018-03-25 17:30:42 +00:00
}
end
end
describe 'token validation' do
it 'invalid token errors' do
2019-07-30 21:29:24 +00:00
validation_invalid_token { UpdateRecurringDonations . update_card_id ( { id : 555 } , fake_uuid ) }
2018-03-25 17:30:42 +00:00
end
it 'unauthorized token errors' do
2019-07-30 21:29:24 +00:00
validation_unauthorized { UpdateRecurringDonations . update_card_id ( { id : 555 } , fake_uuid ) }
2018-03-25 17:30:42 +00:00
end
it 'validation expired errors' do
2019-07-30 21:29:24 +00:00
validation_expired { UpdateRecurringDonations . update_card_id ( { id : 555 } , fake_uuid ) }
2018-03-25 17:30:42 +00:00
end
end
describe 'entity retrieval errors' do
it 'find error on recurring donation' do
2019-07-30 21:29:24 +00:00
find_error_recurring_donation { UpdateRecurringDonations . update_card_id ( { id : 55_555 } , source_token . token ) }
2018-03-25 17:30:42 +00:00
end
end
it 'finishes properly' do
2019-07-30 21:29:24 +00:00
expect ( InsertSupporterNotes ) . to receive ( :create ) . with ( [ { content : " This supporter updated their card for their recurring donation with ID #{ recurring_donation . id } " , supporter_id : supporter . id , user_id : 540 } ] )
2018-03-25 17:30:42 +00:00
recurring_donation . n_failures = 2
recurring_donation . save!
orig_rd = recurring_donation . attributes . with_indifferent_access
orig_donation = recurring_donation . donation . attributes . with_indifferent_access
2019-07-30 21:29:24 +00:00
result = UpdateRecurringDonations . update_card_id ( { id : recurring_donation . id } , source_token . token )
2018-03-25 17:30:42 +00:00
2019-08-02 08:57:17 +00:00
expectations = {
2019-07-30 21:29:24 +00:00
donation : orig_donation . merge ( card_id : card . id ) ,
2019-08-02 08:57:17 +00:00
recurring_donation : orig_rd . merge ( n_failures : 0 , start_date : DateTime . now )
2018-03-25 17:30:42 +00:00
}
expectations [ :result ] = expectations [ :recurring_donation ] . merge ( nonprofit_name : nonprofit . name , card_name : card . name )
2021-01-06 22:09:03 +00:00
expectations [ :result ] [ :start_date ] = expectations [ :result ] [ " start_date " ] . to_date . strftime ( " %Y-%m-%d " )
expectations [ :result ] [ :created_at ] = expectations [ :result ] [ " created_at " ] . to_date
expectations [ :result ] [ :updated_at ] = expectations [ :result ] [ " updated_at " ] . to_date
2019-08-02 08:57:17 +00:00
expect ( result ) . to match expectations [ :result ]
2018-03-25 17:30:42 +00:00
donation_for_rd . reload
recurring_donation . reload
2019-08-02 08:57:17 +00:00
2018-03-25 17:30:42 +00:00
expect ( recurring_donation . attributes ) . to eq expectations [ :recurring_donation ]
expect ( donation_for_rd . attributes ) . to eq expectations [ :donation ]
end
end
def find_error_recurring_donation
2019-07-30 21:29:24 +00:00
expect { yield ( ) } . to raise_error { | e |
2018-03-25 17:30:42 +00:00
expect ( e ) . to be_a ParamValidation :: ValidationError
2019-07-30 21:29:24 +00:00
expect_validation_errors ( e . data , [ { key : :id } ] )
2018-03-25 17:30:42 +00:00
}
end
def error_when_rd_cancelled
recurring_donation . cancelled_at = Time . now
recurring_donation . save!
2019-07-30 21:29:24 +00:00
expect { yield ( ) } . to raise_error { | e |
2018-03-25 17:30:42 +00:00
expect ( e ) . to be_a ParamValidation :: ValidationError
2019-07-30 21:29:24 +00:00
expect_validation_errors ( e . data , [ { key : :id } ] )
2018-03-25 17:30:42 +00:00
expect ( e . message ) . to eq " Recurring Donation #{ recurring_donation . id } is already cancelled. "
}
end
def error_when_card_deleted
card . deleted = true
card . save!
2019-07-30 21:29:24 +00:00
expect { yield ( ) } . to raise_error { | e |
2018-03-25 17:30:42 +00:00
expect ( e ) . to be_a ParamValidation :: ValidationError
2019-07-30 21:29:24 +00:00
expect_validation_errors ( e . data , [ { key : :token } ] )
2018-03-25 17:30:42 +00:00
expect ( e . message ) . to eq " Tokenized card #{ card . id } is not valid. "
}
end
def errors_when_card_holder_and_supporter_neq
2019-07-30 21:29:24 +00:00
expect { yield ( ) } . to raise_error { | e |
2018-03-25 17:30:42 +00:00
expect ( e ) . to be_a ParamValidation :: ValidationError
2019-07-30 21:29:24 +00:00
expect_validation_errors ( e . data , [ { key : :token } ] )
2018-03-25 17:30:42 +00:00
expect ( e . message ) . to eq " Supporter #{ supporter . id } does not own card #{ other_source_token . tokenizable . id } "
}
end
end