# frozen_string_literal: true # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' describe InsertBankAccount do let(:stripe_helper) { StripeMock.create_test_helper } before(:each) do Timecop.freeze(2020, 5, 4) StripeMock.start end after(:each) do StripeMock.stop Timecop.return end let(:nonprofit) { force_create(:nonprofit) } let(:user) { force_create(:user, email: 'x@example.com') } describe '.with_stripe' do describe 'param validation' do it 'validates np and user' do expect { InsertBankAccount.with_stripe(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [{ key: :nonprofit, name: :required }, { key: :nonprofit, name: :is_a }, { key: :user, name: :required }, { key: :user, name: :is_a }]) end) expect { InsertBankAccount.with_stripe(1, 2, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ { key: :nonprofit, name: :is_a }, { key: :user, name: :is_a } ]) end) end it 'validate stripe_bank_account_token' do expect { InsertBankAccount.with_stripe(nonprofit, user, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [{ key: :stripe_bank_account_token, name: :required }, { key: :stripe_bank_account_token, name: :not_blank }]) end) end it 'validates whether vetted' do expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: 'blah') }.to(raise_error do |error| expect(error).to be_a ArgumentError expect(error.message).to include('vetted') end) end end describe 'exceptions in main function' do before (:each) { nonprofit.vetted = true } it 'StripeAccount.find_or_create fails' do expect(StripeAccount).to receive(:find_or_create).and_raise(StandardError.new) expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: 'blah') }.to(raise_error do |error| expect(error).to be_a StandardError end) end it 'Stripe::Account.retrieve fails' do expect(StripeAccount).to receive(:find_or_create).and_return('account_id') StripeMock.prepare_error(Stripe::StripeError.new('some error happened'), :get_account) expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: 'blah') }.to(raise_error do |error| expect(error).to be_a Stripe::StripeError end) end end describe 'works with account retrieval' do before (:each) { nonprofit.vetted = true; nonprofit.save! } let(:stripe_acct) { Stripe::Account.create(managed: true, country: 'US', display_name: 'test_display_name') } let(:stripe_bank_account_token) { StripeMock.generate_bank_token(country: 'US', routing_number: '110000000', account_number: '000123456789') } it 'sets failure message when external_account create fails' do expect(Stripe::Account).to receive(:retrieve).and_return(stripe_acct) StripeMock.prepare_error(Stripe::StripeError.new('hmm'), :create_external_account) expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: stripe_bank_account_token) }.to raise_error { |error| expect(error).to be_a ArgumentError expect(error.message).to eq 'Failed to connect the bank account: #' } end it 'works with external account creation' do expect(Stripe::Account).to receive(:retrieve).and_return(stripe_acct) result = InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: stripe_bank_account_token) expected = { email: user.email, stripe_bank_account_token: stripe_bank_account_token, pending_verification: true, created_at: Time.now, updated_at: Time.now, status: nil, # doesn't seem to be used id: 1, deleted: nil, account_number: nil, # doesn't seem to be used nonprofit_id: nonprofit.id, bank_name: nil }.with_indifferent_access expect(result.attributes.with_indifferent_access.except(:confirmation_token, :stripe_bank_account_id, :name)).to eq expected expect(result[:confirmation_token]).to_not be_blank expect(result[:stripe_bank_account_id]).to_not be_blank expect(result[:name]).to_not be_blank end end describe 'handles replacing the old accounts' do before (:each) do nonprofit.vetted = true; nonprofit.save! old_bank_account_false old_bank_account_nil old_bank_account_true end let(:stripe_acct) { Stripe::Account.create(managed: true, country: 'US', display_name: 'test_display_name') } let(:stripe_bank_account_token) { StripeMock.generate_bank_token(country: 'US', routing_number: '110000000', account_number: '000123456789') } let(:old_bank_account_nil) { force_create(:bank_account, nonprofit: nonprofit, deleted: nil) } let(:old_bank_account_false) { force_create(:bank_account, nonprofit: nonprofit, deleted: false) } let(:old_bank_account_true) { force_create(:bank_account, nonprofit: nonprofit, deleted: true) } it 'works with external account creation' do expect(Stripe::Account).to receive(:retrieve).and_return(stripe_acct) result = InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: stripe_bank_account_token) expected = { email: user.email, stripe_bank_account_token: stripe_bank_account_token, pending_verification: true, created_at: Time.now, updated_at: Time.now, status: nil, # doesn't seem to be used id: result['id'], deleted: nil, account_number: nil, # doesn't seem to be used nonprofit_id: nonprofit.id, bank_name: nil }.with_indifferent_access expect(result.attributes.with_indifferent_access.except(:confirmation_token, :stripe_bank_account_id, :name)).to eq expected expect(result[:confirmation_token]).to_not be_blank expect(result[:stripe_bank_account_id]).to_not be_blank expect(result[:name]).to_not be_blank expect(nonprofit.bank_account).to eq result expect(BankAccount.where('nonprofit_id = ?', nonprofit.id).count).to eq 4 expect(BankAccount.where('nonprofit_id = ? and deleted = true', nonprofit.id).count).to eq 3 end end end end