diff --git a/Gemfile b/Gemfile index 14ef20ad..5a1cae6e 100644 --- a/Gemfile +++ b/Gemfile @@ -225,6 +225,8 @@ group :test do gem 'timecop' # for mocking external requests gem 'webmock' + # for mocking Stripe responses in tests + gem 'stripe-ruby-mock' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 770dcf66..98196af8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,6 +141,7 @@ GEM safe_yaml (~> 1.0.0) currencies (0.4.2) daemons (1.1.9) + dante (0.2.0) database_cleaner (1.3.0) debug_inspector (0.0.2) debugger-linecache (1.2.0) @@ -483,6 +484,10 @@ GEM sqlite3 (1.3.9) stripe (1.43.0) rest-client (~> 1.4) + stripe-ruby-mock (2.3.0) + dante (>= 0.2.0) + multi_json (>= 1.0.0) + stripe (>= 1.31.0, <= 1.43) term-ansicolor (1.3.2) tins (~> 1.0) thor (0.19.1) @@ -618,6 +623,7 @@ DEPENDENCIES spring-commands-rspec sqlite3 stripe + stripe-ruby-mock timecop transitions turbolinks diff --git a/app/models/payment.rb b/app/models/payment.rb index 4ad4df85..9cab6592 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -27,6 +27,7 @@ class Payment < ActiveRecord::Base amount: amount_to_pay, currency: conference.tickets.first.price_currency + self.amount = gateway_response[:amount] self.last4 = gateway_response[:source][:last4] self.authorization_code = gateway_response[:id] self.status = 'success' diff --git a/spec/factories/payments.rb b/spec/factories/payments.rb index f0829c5c..4d4d3c39 100644 --- a/spec/factories/payments.rb +++ b/spec/factories/payments.rb @@ -3,6 +3,5 @@ FactoryGirl.define do user conference status 'unpaid' - amount 1000 end end diff --git a/spec/models/payment_spec.rb b/spec/models/payment_spec.rb index 4512fe80..1a2be88b 100644 --- a/spec/models/payment_spec.rb +++ b/spec/models/payment_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'stripe_mock' describe Payment do @@ -32,4 +33,61 @@ describe Payment do expect(payment.amount_to_pay).to eq(8000) end end + + describe '#purchase' do + let!(:user) { create(:user) } + let!(:conference) { create(:conference) } + let!(:ticket_1) { create(:ticket, price: 10, price_currency: 'USD', conference: conference) } + let!(:tickets) { {ticket_1.id.to_s => '2'} } + let(:stripe_helper) { StripeMock.create_test_helper } + + before { StripeMock.start } + after { StripeMock.stop } + + before { TicketPurchase.purchase(conference, user, tickets) } + let!(:payment) { create(:payment, user: user, conference: conference, stripe_customer_token: stripe_helper.generate_card_token, stripe_customer_email: user.email) } + + context 'when the payment is successful' do + before { payment.purchase } + + it 'assigns amount' do + expect(payment.amount).to eq(2000) + end + + it 'assigns last4' do + expect(payment.last4).to eq('4242') + end + + it "assigns 'success' to payment.status" do + expect(payment.status).to eq('success') + end + + it 'assigns authorization_code' do + expect(payment.authorization_code).to eq('test_ch_3') + end + end + + context 'if the payment is not successful' do + before { StripeMock.prepare_card_error(:invalid_number) } + + let(:payment) { create(:payment, user: user, conference: conference, stripe_customer_token: 'bogus_card_token', stripe_customer_email: user.email) } + + before { payment.purchase } + + context 'when the card is invalid' do + it 'returns false' do + payment_result = payment.purchase + expect(payment_result).to eq false + end + + it 'assigns "failure" to payment.status' do + expect(payment.status).to eq('failure') + end + + it 'adds errors' do + expect(payment.errors[:base].count).to eq(1) + end + end + end + end end