6772312ea7
The primary license of the project is changing to: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later with some specific files to be licensed under the one of two licenses: CC0-1.0 LGPL-3.0-or-later This commit is one of the many steps to relicense the entire codebase. Documentation granting permission for this relicensing (from all past contributors who hold copyrights) is on file with Software Freedom Conservancy, Inc.
479 lines
19 KiB
Ruby
479 lines
19 KiB
Ruby
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
|
require 'rails_helper'
|
|
describe InsertCard do
|
|
describe'.with_stripe' do
|
|
|
|
let(:stripe_helper) { StripeMock.create_test_helper }
|
|
|
|
let(:stripe_card_token) { StripeMock.generate_card_token(last4: '9191', exp_year:2011)}
|
|
let(:default_card_attribs) {
|
|
{
|
|
created_at: Time.now,
|
|
updated_at: Time.now,
|
|
profile_id: nil,
|
|
status: nil,
|
|
inactive: nil,
|
|
deleted: nil,
|
|
expiration_month: nil,
|
|
expiration_year: nil,
|
|
email:nil,
|
|
supporter_id: nil
|
|
}
|
|
}
|
|
|
|
let(:nonprofit) { force_create(:nonprofit)}
|
|
let(:user) { user = force_create(:user)
|
|
|
|
force_create(:role, name: :nonprofit_admin, host: nonprofit, user: user)
|
|
user
|
|
}
|
|
|
|
around(:each) {|example|
|
|
Timecop.freeze(2020, 5, 4) do
|
|
StripeMock.start
|
|
example.run
|
|
StripeMock.stop
|
|
end
|
|
}
|
|
|
|
it 'params are invalid' do
|
|
ret = InsertCard::with_stripe({ })
|
|
expect(ret[:status]).to eq(:unprocessable_entity)
|
|
expect(ret[:json][:error]).to start_with('Validation error')
|
|
expect(ret[:json][:errors].length).to be(9)
|
|
|
|
expect_validation_errors(ret[:json][:errors], [ {key: 'holder_id', name: :required},
|
|
{key: 'holder_type', name: 'included_in'},
|
|
{key: 'holder_type', name: 'required'},
|
|
{key: 'stripe_card_id', name: 'required'},
|
|
{key: 'stripe_card_id', name: 'not_blank'},
|
|
{key: 'stripe_card_token', name: 'required'},
|
|
{key: 'stripe_card_token', name: 'not_blank'},
|
|
{key: 'name', name: 'required'},
|
|
{key: 'name', name: 'not_blank'}
|
|
])
|
|
|
|
end
|
|
|
|
describe 'for nonprofits' do
|
|
|
|
|
|
|
|
|
|
let(:supporter) { nonprofit.supporters.first }
|
|
it 'nonprofit doesn\'t exist' do
|
|
ret = InsertCard::with_stripe({:holder_id => 3, :holder_type => 'Nonprofit', :stripe_card_id => 'card_fafjeht', :stripe_card_token => stripe_card_token, :name => 'name'})
|
|
expect(ret[:status]).to eq(:unprocessable_entity)
|
|
expect(ret[:json][:error]).to include("Sorry, you need to provide a nonprofit or supporter")
|
|
end
|
|
|
|
it 'should properly add nonprofit card when no card exists' do
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
card_data = { :holder_type => 'Nonprofit', :holder_id => nonprofit.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
orig_card = nonprofit.active_card
|
|
expect(orig_card).to be_nil
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
nonprofit.reload
|
|
card = nonprofit.active_card
|
|
|
|
compare_card_returned_to_real(card_ret, card)
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_card_id: 'card_88888',
|
|
holder_type: 'Nonprofit',
|
|
holder_id: nonprofit.id,
|
|
stripe_customer_id: stripe_customer['id']
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
|
|
|
|
expect(Card.where('holder_id = ? and holder_type = ?', nonprofit.id, 'Nonprofit').count).to eq(1)
|
|
|
|
customer = verify_cust_added_np(card.stripe_customer_id, nonprofit.id)
|
|
expect(customer.sources.count).to eq(1)
|
|
expect(customer.sources.data[0].object).to eq('card')
|
|
expect(customer.sources.data[0].last4).to eq('9191')
|
|
expect(customer.sources.data[0].exp_year).to eq(2011)
|
|
end
|
|
|
|
it 'invalid params get ignored' do
|
|
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
card_data = { :holder_type => 'Nonprofit', :holder_id => nonprofit.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token,
|
|
:name => "card_name", :created_at => DateTime.new(0), :updated_at => DateTime.new(0), :inactive => true}
|
|
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
|
|
nonprofit.reload
|
|
card = Card.find(card_ret[:json][:id])
|
|
|
|
expect(nonprofit.active_card).to eq card
|
|
compare_card_returned_to_real(card_ret, card)
|
|
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_card_id: 'card_88888',
|
|
holder_type: 'Nonprofit',
|
|
holder_id: nonprofit.id,
|
|
stripe_customer_id: stripe_customer['id']
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
end
|
|
|
|
|
|
describe 'card exists' do
|
|
before(:each) {
|
|
@first_card_tok = StripeMock.generate_card_token(:last4 => '9999', :exp_year => '2122')
|
|
@stripe_customer = Stripe::Customer.create()
|
|
@stripe_customer.sources.create({token: @first_card_tok})
|
|
|
|
|
|
}
|
|
|
|
it 'should properly add nonprofit card and make old inactive' do
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
first_card = nonprofit.create_active_card(:stripe_card_id => 'fake mcfake', :stripe_card_token => @first_card_tok, :name=> 'fake name')
|
|
|
|
card_data = { :holder_type => 'Nonprofit', :holder_id => nonprofit.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
|
|
|
|
nonprofit.reload
|
|
card = nonprofit.active_card
|
|
|
|
compare_card_returned_to_real(card_ret, card)
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_card_id: 'card_88888',
|
|
holder_type: 'Nonprofit',
|
|
holder_id: nonprofit.id,
|
|
stripe_customer_id: stripe_customer['id']
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
expect(Card.where('holder_id = ? and holder_type = ?', nonprofit.id, 'Nonprofit').count).to eq(2)
|
|
expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', nonprofit.id, 'Nonprofit', false).count).to eq(1)
|
|
|
|
customer = verify_cust_added_np(card.stripe_customer_id, nonprofit.id)
|
|
|
|
expect(customer.sources.count).to eq(1)
|
|
expect(customer.sources.data.any?{|s| s.object == 'card' && s.last4 == '9191' && s.exp_year == 2011}).to eq(true)
|
|
|
|
#verify the original card didn't change
|
|
expect(nonprofit.cards.find(first_card.id).attributes.select{|k,_| k != 'inactive'}).to eq first_card.attributes.select{|k, _| k != 'inactive'}
|
|
|
|
expect(nonprofit.cards.find(first_card.id).inactive).to eq true
|
|
|
|
end
|
|
end
|
|
|
|
it 'handle card errors' do
|
|
StripeMock.prepare_error(Stripe::CardError.new('card error', nil, nil, 300,{},{error: {message: 'a message'}}), :new_customer)
|
|
card_data = { :holder_type => 'Nonprofit', :holder_id => nonprofit.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
|
|
expect(card_ret[:status]).to be :unprocessable_entity
|
|
expect(card_ret[:json][:error]).to start_with('Oops!')
|
|
end
|
|
|
|
it 'handle stripe errors' do
|
|
StripeMock.prepare_error(Stripe::StripeError.new('card error', nil, nil), :new_customer)
|
|
card_data = { :holder_type => 'Nonprofit', :holder_id => nonprofit.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
|
|
expect(card_ret[:status]).to eq :unprocessable_entity
|
|
expect(card_ret[:json][:error]).to start_with('Oops!')
|
|
end
|
|
|
|
|
|
def verify_cust_added_np(stripe_customer_id, holder_id)
|
|
verify_cust_added(stripe_customer_id, holder_id, 'Nonprofit')
|
|
end
|
|
|
|
|
|
end
|
|
|
|
describe 'for supporter' do
|
|
let(:supporter) {force_create(:supporter, nonprofit: nonprofit)}
|
|
let(:event) {
|
|
force_create(:event, nonprofit: nonprofit, end_datetime: Time.now.since(1.day))}
|
|
let(:user_not_from_nonprofit) {force_create(:user)}
|
|
def verify_cust_added_supporter(stripe_customer_id, holder_id)
|
|
verify_cust_added(stripe_customer_id, holder_id, 'Supporter')
|
|
end
|
|
|
|
def verify_supporter_source_token(source_token, card)
|
|
verify_source_token(source_token, card, 1, Time.now.since(20.minutes))
|
|
end
|
|
|
|
def verify_event_source_token(source_token, card, event)
|
|
verify_source_token(source_token, card, 20, event.end_datetime.since(20.days), event)
|
|
end
|
|
|
|
context 'card exists' do
|
|
|
|
let(:supporter) {create(:supporter, :has_a_card, nonprofit:nonprofit)}
|
|
|
|
|
|
it 'should properly add supporter card' do
|
|
expect(supporter.cards.count).to eq(1)
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
card_data = { :holder_type => 'Supporter', :holder_id => supporter.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
orig_card = supporter.cards.first
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
supporter.reload
|
|
card = supporter.cards.where('cards.name = ?', 'card_name').first
|
|
compare_card_returned_to_real(card_ret, card, card_ret[:json]['token'])
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_card_id: 'card_88888',
|
|
holder_id: supporter.id,
|
|
holder_type: 'Supporter',
|
|
stripe_customer_id: stripe_customer['id'],
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
expect(supporter.cards.count).to eq(2)
|
|
|
|
expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(2)
|
|
expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0)
|
|
|
|
expect(supporter.cards.find(orig_card.id)).to eq(orig_card)
|
|
|
|
verify_cust_added_supporter(card.stripe_customer_id, supporter.id)
|
|
|
|
verify_supporter_source_token(card_ret[:json]['token'], card)
|
|
end
|
|
|
|
it 'should properly add card for event' do
|
|
expect(supporter.cards.count).to eq(1)
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
card_data = { :holder_type => 'Supporter', :holder_id => supporter.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
orig_card = supporter.cards.first
|
|
card_ret = InsertCard::with_stripe(card_data, nil, event.id, user);
|
|
supporter.reload
|
|
card = supporter.cards.where('cards.name = ?', 'card_name').first
|
|
compare_card_returned_to_real(card_ret, card, card_ret[:json]['token'])
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_card_id: 'card_88888',
|
|
holder_id: supporter.id,
|
|
holder_type: 'Supporter',
|
|
stripe_customer_id: stripe_customer['id'],
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
expect(supporter.cards.count).to eq(2)
|
|
|
|
expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(2)
|
|
expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0)
|
|
|
|
expect(supporter.cards.find(orig_card.id)).to eq(orig_card)
|
|
|
|
verify_cust_added_supporter(card.stripe_customer_id, supporter.id)
|
|
|
|
|
|
verify_event_source_token(card_ret[:json]['token'], card, event)
|
|
end
|
|
end
|
|
|
|
context 'card doesnt exist' do
|
|
|
|
|
|
it 'invalid params get ignored' do
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
card_data = { :holder_type => 'Supporter', :holder_id => supporter.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token,
|
|
:name => "card_name", :created_at => DateTime.new(0), :updated_at => DateTime.new(0), :inactive => true}
|
|
|
|
card_ret = InsertCard.with_stripe(card_data);
|
|
|
|
|
|
card = Card.find(card_ret[:json][:id])
|
|
|
|
supporter.reload
|
|
|
|
compare_card_returned_to_real(card_ret, card, card_ret[:json]['token'])
|
|
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
holder_type: 'Supporter',
|
|
holder_id: supporter.id,
|
|
stripe_card_token: stripe_card_token,
|
|
name: 'card_name',
|
|
stripe_card_id: 'card_88888',
|
|
stripe_customer_id: stripe_customer['id']
|
|
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
verify_supporter_source_token(card_ret[:json]['token'], card)
|
|
|
|
|
|
end
|
|
|
|
it 'should properly add supporter card when no card exist' do
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
|
|
card_data = { :holder_type => 'Supporter', :holder_id => supporter.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
card_ret = InsertCard::with_stripe(card_data);
|
|
supporter.reload
|
|
card = supporter.cards.where('cards.name = ?', 'card_name').first
|
|
compare_card_returned_to_real(card_ret, card, card_ret[:json]['token'])
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_id: 'card_88888',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_customer_id: stripe_customer['id'],
|
|
holder_type: 'Supporter',
|
|
holder_id: supporter.id
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
expect(supporter.cards.count).to eq(1)
|
|
|
|
expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(1)
|
|
expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0)
|
|
verify_cust_added_supporter(card.stripe_customer_id, supporter.id)
|
|
|
|
verify_supporter_source_token(card_ret[:json]['token'], card)
|
|
end
|
|
|
|
it 'should properly add card for event' do
|
|
|
|
stripe_customer = nil
|
|
expect(Stripe::Customer).to receive(:create).and_wrap_original{|m, *args| stripe_customer = m.call(*args); stripe_customer}
|
|
card_data = { :holder_type => 'Supporter', :holder_id => supporter.id, :stripe_card_id => 'card_88888', :stripe_card_token => stripe_card_token, :name => "card_name" }
|
|
card_ret = InsertCard::with_stripe(card_data, nil, event.id, user);
|
|
supporter.reload
|
|
card = supporter.cards.where('cards.name = ?', 'card_name').first
|
|
compare_card_returned_to_real(card_ret, card, card_ret[:json]['token'])
|
|
|
|
expected_card = {
|
|
id: card.id,
|
|
name: 'card_name',
|
|
stripe_card_token: stripe_card_token,
|
|
stripe_card_id: 'card_88888',
|
|
holder_id: supporter.id,
|
|
holder_type: 'Supporter',
|
|
stripe_customer_id: stripe_customer['id'],
|
|
}.merge(default_card_attribs).with_indifferent_access
|
|
|
|
expect(card.attributes).to eq expected_card
|
|
|
|
expect(supporter.cards.count).to eq(1)
|
|
|
|
expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(1)
|
|
expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0)
|
|
|
|
verify_cust_added_supporter(card.stripe_customer_id, supporter.id)
|
|
|
|
verify_event_source_token(card_ret[:json]['token'], card, event)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
it 'should return proper error when no supporter exists' do
|
|
ret = InsertCard::with_stripe({:holder_id => 5555555, :holder_type => 'Supporter', :stripe_card_id => 'card_fafjeht', :stripe_card_token => stripe_card_token, :name => 'name'})
|
|
expect(ret[:status]).to eq(:unprocessable_entity)
|
|
expect(ret[:json][:error]).to include("Sorry, you need to provide a nonprofit or supporter")
|
|
end
|
|
|
|
it 'should return proper error when you try to add using an event with unauthorized user' do
|
|
ret = InsertCard::with_stripe({holder_id: supporter.id, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', stripe_card_token: stripe_card_token, name: 'name'}, nil, event.id, user_not_from_nonprofit)
|
|
|
|
expect(ret[:json][:error]).to eq "You're not authorized to perform that action"
|
|
expect(ret[:status]).to eq (:unauthorized)
|
|
end
|
|
|
|
it 'should return proper error when an invalid event_id is provided' do
|
|
ret = InsertCard.with_stripe({holder_id: supporter.id, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', stripe_card_token: stripe_card_token, name: 'name'}, nil, 55555, user_not_from_nonprofit)
|
|
expect(ret).to eq({ status: :unprocessable_entity, json: {error: 'Oops! There was an error: 55555 is not a valid event'}})
|
|
end
|
|
|
|
it 'should return proper error when event doesnt match the supporters nonprofit' do
|
|
supporter2 = force_create(:supporter)
|
|
ret = InsertCard.with_stripe({holder_id: supporter2.id, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', stripe_card_token: stripe_card_token, name: 'name'}, nil, event.id, user_not_from_nonprofit)
|
|
expect(ret).to eq({ status: :unprocessable_entity, json: {error: "Oops! There was an error: Event #{event.id} is not for the same nonprofit as supporter #{supporter2.id}"}})
|
|
end
|
|
|
|
|
|
end
|
|
def compare_card_returned_to_real(card_ret, db_card, token=nil)
|
|
expect(card_ret[:status]).to eq(:ok)
|
|
|
|
expected_json = db_card.attributes
|
|
expected_json.merge!({'token' => token})
|
|
if token
|
|
expect(token).to match(UUID::Regex)
|
|
end
|
|
expect(card_ret[:json]).to eq(expected_json)
|
|
end
|
|
|
|
def verify_cust_added(stripe_customer_id, holder_id, holder_type)
|
|
customer = Stripe::Customer.retrieve(stripe_customer_id)
|
|
# does the customer exist? Was it set properly? Was the card set properly
|
|
expect(customer).to_not be_nil
|
|
expected_metadata = {
|
|
holder_id: holder_id,
|
|
holder_type: holder_type,
|
|
cardholders_name: nil
|
|
}
|
|
|
|
expect(customer.metadata.to_hash).to eq expected_metadata
|
|
customer
|
|
end
|
|
|
|
def verify_source_token(source_token, card, max_uses, expiration_time, event=nil)
|
|
tok = SourceToken.where('token = ?', source_token).first
|
|
expected = {
|
|
created_at: Time.now,
|
|
updated_at: Time.now,
|
|
tokenizable_id: card.id,
|
|
tokenizable_type: 'Card',
|
|
max_uses: max_uses,
|
|
total_uses: 0,
|
|
expiration: expiration_time,
|
|
event_id: event ? event.id : nil,
|
|
token: source_token
|
|
}.with_indifferent_access
|
|
|
|
expect(tok.attributes).to eq expected
|
|
end
|
|
|
|
end
|
|
end
|