houdini/spec/support/contexts/shared_rd_donation_value_context.rb

464 lines
16 KiB
Ruby

# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
# holy cow, this is confusing
RSpec.shared_context :shared_rd_donation_value_context do
include_context :shared_donation_charge_context
let(:fake_uuid) { '53a6bc06-0789-11e8-bb3f-f34cac607737' }
let(:valid_uuid) { 'fcf61bac-078a-11e8-aa53-cba5bdb8dcdd' }
let(:other_uuid) { 'a713018c-078f-11e8-ae3b-bf5007844fea' }
let(:source_token) { force_create(:source_token, tokenizable: card, expiration: Time.now + 1.day, max_uses: 1, token: valid_uuid) }
let(:source_tokens) do
(0..10).map do |_i|
force_create(:source_token, tokenizable: card, expiration: Time.now + 1.day, max_uses: 1, token: SecureRandom.uuid)
end
end
let(:other_source_token) { force_create(:source_token, tokenizable: card_for_other_supporter, expiration: Time.now + 1.day, max_uses: 1, token: other_uuid) }
let(:charge_amount) { 100 }
let(:default_edit_token) { '7903e34c-10fe-11e8-9ead-d302c690bee4' }
before(:each) do
allow_any_instance_of(Event).to receive(:geocode).and_return([1, 1])
end
def generate_expected(donation_id, payment_id, charge_id, card, supporter, nonprofit, stripe_charge_id, data = {})
payment_stuff = {}
payment_stuff[:card_id] = card.id if card.is_a? Card
payment_stuff[:direct_debit_detail_id] = card.id if card.is_a? DirectDebitDetail
payment_stuff[:provider] = card.is_a?(Card) ? 'credit_card' : 'sepa'
payment_stuff[:fee] = card.is_a?(Card) ? 33 : 0
result = {
donation: {
id: donation_id,
nonprofit_id: nonprofit.id,
supporter_id: supporter.id,
card_id: payment_stuff[:card_id],
date: Time.now,
created_at: Time.now,
updated_at: Time.now,
event_id: data[:event] ? event.id : nil,
campaign_id: data[:campaign] ? campaign.id : nil,
anonymous: nil,
amount: charge_amount,
comment: nil,
category: nil,
dedication: 'dedication',
designation: 'designation',
imported_at: nil,
manual: nil,
offsite: nil,
recurring: nil,
recurring_donation_id: nil,
origin_url: nil,
payment_id: nil,
profile_id: nil,
charge_id: nil,
payment_provider: payment_stuff[:provider],
queued_for_import_at: nil,
direct_debit_detail_id: payment_stuff[:direct_debit_detail_id]
}
}.with_indifferent_access
unless payment_id.nil?
result[:activity] = {}
result[:payment] = {
date: Time.now,
donation_id: donation_id,
fee_total: -payment_stuff[:fee],
gross_amount: 100,
id: payment_id || 55_555,
kind: data[:recurring_donation] ? 'RecurringDonation' : 'Donation',
net_amount: 100 - payment_stuff[:fee],
nonprofit_id: nonprofit.id,
refund_total: 0,
supporter_id: supporter.id,
towards: 'designation',
created_at: Time.now,
updated_at: Time.now,
search_vectors: nil
}
result[:charge] = {
id: charge_id || 55_555,
amount: charge_amount,
card_id: payment_stuff[:card_id],
created_at: Time.now,
updated_at: Time.now,
stripe_charge_id: stripe_charge_id,
fee: payment_stuff[:fee],
disbursed: nil,
failure_message: nil,
payment_id: payment_id || 55_555,
nonprofit_id: nonprofit.id,
status: 'pending',
profile_id: nil,
supporter_id: supporter.id,
ticket_id: nil,
donation_id: donation_id,
direct_debit_detail_id: payment_stuff[:direct_debit_detail_id]
}
end
if data[:recurring_donation]
result[:recurring_donation] = {
id: data[:recurring_donation].id,
active: true,
paydate: data[:recurring_donation_expected][:paydate],
interval: data[:recurring_donation_expected][:interval],
time_unit: data[:recurring_donation_expected][:time_unit],
start_date: data[:recurring_donation_expected][:start_date],
end_date: nil,
n_failures: 0,
edit_token: default_edit_token,
cancelled_by: nil,
cancelled_at: nil,
donation_id: donation_id,
nonprofit_id: nonprofit.id,
created_at: Time.now,
updated_at: Time.now,
failure_message: nil,
origin_url: nil,
amount: charge_amount,
supporter_id: supporter.id,
# removable fields
card_id: nil,
campaign_id: nil,
anonymous: nil,
email: supporter.email,
profile_id: nil
}
end
result
end
def generate_expected_refund(_data = {})
result = {}.with_indifferent_access
result
end
def validation_unauthorized
expect(QuerySourceToken).to receive(:get_and_increment_source_token).with(fake_uuid, nil).and_raise(AuthenticationError)
expect { yield() }.to raise_error { |e|
expect(e).to be_a(AuthenticationError)
}
end
def validation_expired
expect(QuerySourceToken).to receive(:get_and_increment_source_token).with(fake_uuid, nil).and_raise(ExpiredTokenError)
expect { yield() }.to raise_error { |e|
expect(e).to be_a(ExpiredTokenError)
}
end
def validation_basic_validation
expect { yield() }.to raise_error { |e|
expect(e).to be_a(ParamValidation::ValidationError)
expect(e.message).to start_with 'amount'
expect_validation_errors(e.data, [
{ key: :amount, name: :required },
{ key: :amount, name: :is_integer },
{ key: :nonprofit_id, name: :required },
{ key: :nonprofit_id, name: :is_reference },
{ key: :supporter_id, name: :required },
{ key: :supporter_id, name: :is_reference },
{ key: :designation, name: :is_a },
{ key: :dedication, name: :is_a },
{ key: :campaign_id, name: :is_reference },
{ key: :event_id, name: :is_reference },
{ key: :token, name: :required },
{ key: :token, name: :format }
])
}
end
def validation_invalid_token
expect { yield() }.to raise_error { |e|
expect(e).to be_a(ParamValidation::ValidationError)
expect(e.message).to eq "#{fake_uuid} doesn't represent a valid source"
}
end
def find_error_supporter
expect { yield() }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect_validation_errors(e.data, [{ key: :supporter_id }])
}
end
def find_error_nonprofit
expect { yield() }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect_validation_errors(e.data, [{ key: :nonprofit_id }])
}
end
def find_error_campaign
expect { yield() }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect_validation_errors(e.data, [{ key: :campaign_id }])
}
end
def find_error_event
expect { yield() }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect_validation_errors(e.data, [{ key: :event_id }])
}
end
def find_error_ticket
expect { yield() }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect_validation_errors(e.data, [{ key: :ticket_id }])
}
end
def find_error_profile
expect { yield() }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect_validation_errors(e.data, [{ key: :profile_id }])
}
end
def validation_supporter_deleted
supporter
supporter.deleted = true
supporter.save!
expect { yield }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect(e.message).to include 'deleted'
expect_validation_errors(e.data, [{ key: :supporter_id }])
}
end
def validation_event_deleted
event.deleted = true
event.save!
expect { yield }.to raise_error { |error|
expect(error).to be_a ParamValidation::ValidationError
expect_validation_errors(error.data, [{ key: :event_id }])
expect(error.message).to include 'deleted'
expect(error.message).to include "Event #{event.id}"
}
end
def validation_campaign_deleted
campaign.deleted = true
campaign.save!
expect { yield }.to raise_error { |error|
expect(error).to be_a ParamValidation::ValidationError
expect_validation_errors(error.data, [{ key: :campaign_id }])
expect(error.message).to include 'deleted'
expect(error.message).to include "Campaign #{campaign.id}"
}
end
def validation_supporter_not_with_nonprofit
expect { yield }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect(e.message).to include 'Supporter'
expect(e.message).to include 'does not belong to nonprofit'
expect_validation_errors(e.data, [{ key: :supporter_id }])
}
end
def validation_campaign_not_with_nonprofit
expect { yield }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect(e.message).to include 'Campaign'
expect(e.message).to include 'does not belong to nonprofit'
expect_validation_errors(e.data, [{ key: :campaign_id }])
}
end
def validation_event_not_with_nonprofit
expect { yield }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect(e.message).to include 'Event'
expect(e.message).to include 'does not belong to nonprofit'
expect_validation_errors(e.data, [{ key: :event_id }])
}
end
def validation_card_not_with_supporter
expect { yield }.to raise_error { |e|
expect(e).to be_a ParamValidation::ValidationError
expect(e.message).to include 'Supporter'
expect(e.message).to include 'does not own card'
expect_validation_errors(e.data, [{ key: :token }])
}
end
def handle_charge_failed
failure_message = 'failure message'
expect(InsertCharge).to receive(:with_stripe).and_return('charge' => { 'status' => 'failed', 'failure_message' => failure_message })
expect { yield }.to raise_error { |e|
expect(e).to be_a ChargeError
expect(e.message).to eq failure_message
expect(Donation.count).to eq 0
expect(Charge.count).to eq 0
expect(Activity.count).to eq 0
expect(Payment.count).to eq 0
}
end
def before_each_success(expect_charge = true)
expect(InsertDonation).to receive(:insert_donation).and_wrap_original do |m, *args|
result = m.call(*args)
@donation_id = result.id
result
end
if expect_charge
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!
expect(Stripe::Charge).to receive(:create).and_wrap_original { |m, *args|
a = m.call(*args)
@stripe_charge_id = a['id']
a
}
end
end
def before_each_successful_refund
expect(InsertRefund).to receive(:with_stripe).and_wrap_original do |m, *args|
result = m.call(*args)
@all_refunds&.push(result) || @all_refunds = [result]
@fifo_refunds&.unshift(result) || @fifo_refunds = [result]
result
end
expect(Stripe::Refund).to receive(:create).and_wrap_original do |m, *args|
a = m.call(*args)
@stripe_refund_ids&.unshift(a['id']) || @stripe_refund_ids = [a['id']]
a
end
end
def before_each_sepa_success
expect(InsertDonation).to receive(:insert_donation).and_wrap_original do |m, *args|
result = m.call(*args)
@donation_id = result.id
result
end
end
def process_event_donation(data = {})
pay_method = data[:sepa] ? direct_debit_detail : card
result = yield
expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, event: event, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
expect(result.count).to eq expected.count
expect(result['donation'].attributes).to eq expected[:donation]
expect(result['charge'].attributes).to eq expected[:charge]
# expect(result[:json]['activity']).to eq expected[:activity]
expect(result['payment'].attributes).to eq expected[:payment]
if data[:recurring_donation]
expect(result['recurring_donation'].attributes).to eq expected[:recurring_donation]
end
if (data[:sepa])
expect(DirectDebitCreateJob).to have_been_enqueued.with(result['donation']['id'], supporter.locale)
else
expect(PaymentNotificationJob).to have_been_enqueued.with(result['donation'], supporter.locale)
end
expect(WeMoveExecuteForDonationsJob).to have_been_enqueued
result
end
def process_campaign_donation(data = {})
pay_method = data[:sepa] ? direct_debit_detail : card
result = yield
expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, campaign: campaign, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
expect(result.count).to eq expected.count
expect(result['donation'].attributes).to eq expected[:donation]
expect(result['charge'].attributes).to eq expected[:charge]
# expect(result[:json]['activity']).to eq expected[:activity]
expect(result['payment'].attributes).to eq expected[:payment]
if data[:recurring_donation]
expect(result['recurring_donation'].attributes).to eq expected[:recurring_donation]
end
if (data[:sepa])
else
expect(PaymentNotificationJob).to have_been_enqueued.with(result['donation'], supporter.locale)
end
expect(WeMoveExecuteForDonationsJob).to have_been_enqueued
result
end
def process_general_donation(data = {})
pay_method = data[:sepa] ? direct_debit_detail : card
result = yield
expect_payment = nil_or_true(data[:expect_payment])
expect_charge = nil_or_true(data[:expect_charge])
expected = generate_expected(@donation_id, nil_or_true(data[:expect_payment]) ? result['payment'].id : nil, nil_or_true(data[:expect_payment]) ? result['charge'].id : nil, pay_method, supporter, nonprofit, @stripe_charge_id, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
expected['donation'][:profile_id] = profile.id
expect(result.count).to eq expected.count
expect(result['donation'].attributes).to eq expected[:donation]
expect(result['charge'].attributes).to eq expected[:charge] if expect_charge
# expect(result[:json]['activity']).to eq expected[:activity]
if expect_payment
expect(result['payment'].attributes).to eq expected[:payment]
end
if data[:recurring_donation]
expect(result['recurring_donation'].attributes).to eq expected[:recurring_donation]
end
if (data[:sepa])
else
expect(PaymentNotificationJob).to have_been_enqueued.with(result['donation'], supporter.locale)
end
expect(WeMoveExecuteForDonationsJob).to have_been_enqueued
result
end
def process_general_refund(_data = {})
result = yield
expected = generate_expected_refund
expect(result['payment']).to eq expected[:payment]
expect(result['refund']).to eq expected[:refund]
result
end
def nil_or_true(item)
item.nil? || item
end
end