From c4d934d711f0b36175186898b2e77b397fe54806 Mon Sep 17 00:00:00 2001 From: Rishabh Saxena Date: Tue, 19 Jul 2016 12:37:19 +0530 Subject: [PATCH] refactor payment model and its tests --- app/models/payment.rb | 33 ++++++------ spec/factories/payments.rb | 17 ++++-- spec/features/payments_spec.rb | 6 +-- spec/models/payment_spec.rb | 94 ++++++++++++++++++++++++++++------ 4 files changed, 111 insertions(+), 39 deletions(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index b89b8377..cc94db2d 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -24,7 +24,7 @@ class Payment < ActiveRecord::Base } def credit_card - @credit_card = ActiveMerchant::Billing::CreditCard.new( + @credit_card ||= ActiveMerchant::Billing::CreditCard.new( first_name: first_name, last_name: last_name, number: credit_card_number, @@ -35,26 +35,25 @@ class Payment < ActiveRecord::Base end def purchase(user, conference, price_in_cents) - begin - recieve = GATEWAY.purchase(price_in_cents, credit_card, currency: conference.tickets.first.price_currency) + gateway_response = begin + GATEWAY.purchase(price_in_cents, credit_card, currency: conference.tickets.first.price_currency) rescue - false + ActiveMerchant::Billing::Response.new(false, 'Unable to receive any response from the payment gateway.') end - unless recieve - errors.add(:base, 'Unable to recieve any response') - return false - end - unless recieve.success? - errors.add(:base, recieve.message) + + if gateway_response.success? + self.user_id = user.id + self.conference_id = conference.id + self.last4 = credit_card.display_number + self.authorization_code = gateway_response.authorization + self.status = 'success' + else + errors.add(:base, gateway_response.message) self.status = 'failure' - return false end - self.user_id = user.id - self.conference_id = conference.id - self.last4 = credit_card.display_number - self.authorization_code = recieve.authorization - self.status = 'success' - recieve.success? + + success? end end + diff --git a/spec/factories/payments.rb b/spec/factories/payments.rb index e4ccaee4..de852124 100644 --- a/spec/factories/payments.rb +++ b/spec/factories/payments.rb @@ -2,10 +2,19 @@ FactoryGirl.define do factory :payment do first_name { "#{Faker::Hipster.word} abc" } last_name { "#{Faker::Hipster.word} xyz" } - credit_card_number { '4242424242424242' } - card_verification_value { '123' } - expiration_month { '06' } + credit_card_number '4242424242424111' + card_verification_value '123' + expiration_month 6 expiration_year { Date.current.year + 2 } - amount { '10' } + amount 10 + end + + trait :invalid_credit_card do + credit_card_number '4242424242424222' + end + + trait :exception_credit_card do + credit_card_number '4242424242424333' end end + diff --git a/spec/features/payments_spec.rb b/spec/features/payments_spec.rb index d69f9545..15937113 100644 --- a/spec/features/payments_spec.rb +++ b/spec/features/payments_spec.rb @@ -37,7 +37,7 @@ feature Registration do fill_in 'last_name', with: 'bar' select Date.current.year + 2, from: 'expiration_year' fill_in 'card_verification_value', with: '123' - fill_in 'credit_card_number', with: '3' + fill_in 'credit_card_number', with: '4242424242423333' click_button 'Charge Card' @@ -65,7 +65,7 @@ feature Registration do fill_in 'last_name', with: 'bar' select Date.current.year + 2, from: 'expiration_year' fill_in 'card_verification_value', with: '123' - fill_in 'credit_card_number', with: '2' + fill_in 'credit_card_number', with: '4242424242422222' click_button 'Charge Card' @@ -93,7 +93,7 @@ feature Registration do fill_in 'last_name', with: 'bar' select Date.current.year + 2, from: 'expiration_year' fill_in 'card_verification_value', with: '123' - fill_in 'credit_card_number', with: '4242424242424242' + fill_in 'credit_card_number', with: '4242424242421111' click_button 'Charge Card' diff --git a/spec/models/payment_spec.rb b/spec/models/payment_spec.rb index d077db5a..a5906f65 100644 --- a/spec/models/payment_spec.rb +++ b/spec/models/payment_spec.rb @@ -2,6 +2,13 @@ require 'spec_helper' describe Payment do + context 'new payment' do + let(:payment) { create(:payment) } + it 'sets status to "unpaid" by default' do + expect(payment.status).to eq('unpaid') + end + end + describe 'validations' do it 'has a valid factory' do expect(build(:payment)).to be_valid @@ -35,28 +42,85 @@ describe Payment do end - describe 'purchase' do - let!(:participant) { create(:user) } + describe '#purchase' do + let!(:user) { create(:user) } let!(:ticket_1) { create(:ticket) } let!(:conference) { create(:conference, tickets: [ticket_1]) } let(:payment) { create(:payment) } - it 'creates a purchase and payment for one ticket' do - tickets = { ticket_1.id.to_s => '1' } - message = TicketPurchase.purchase(conference, participant, tickets) - purchase = TicketPurchase.where(conference_id: conference.id, - user_id: participant.id, - ticket_id: ticket_1.id).first + it 'calls the payment gateway with the correct parameters' do + expect(GATEWAY).to receive(:purchase).with(1000, payment.credit_card, currency: 'USD') + .and_return(ActiveMerchant::Billing::Response.new(true, 'Success.')) - expect(TicketPurchase.count).to eq(1) - expect(purchase.quantity).to eq(1) - expect(message.blank?).to be true + payment.purchase(user, conference, 1000) + end - payment.purchase(participant, conference, 1000) + context 'when the payment is successful' do + before { payment.purchase(user, conference, 1000) } - purchase = Payment.first - expect(Payment.count).to be(1) - expect(purchase.amount).to eq(10) + it 'returns true' do + payment_result = payment.purchase(user, conference, 1000) + expect(payment_result).to eq true + end + + it "assigns 'success' to payment.status" do + expect(payment.status).to eq('success') + end + + it 'assigns user_id' do + expect(payment.user_id).to eq(user.id) + end + + it 'assigns conference_id' do + expect(payment.conference_id).to eq(conference.id) + end + + it 'assigns last4' do + expect(payment.last4).to eq('XXXX-XXXX-XXXX-4111') + end + + it 'assigns authorization_code' do + expect(payment.authorization_code).to eq("53433") + end + end + + context 'if the payment is not successful' do + before { payment.purchase(user, conference, 1000) } + + let(:payment) { create(:payment, :invalid_credit_card) } + + context 'when the card is invalid' do + it 'returns false' do + payment_result = payment.purchase(user, conference, 1000) + 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 + + context 'when there is a connection problem with the gateway' do + let(:payment) { create(:payment, :exception_credit_card) } + + it 'returns false' do + payment_result = payment.purchase(user, conference, 1000) + 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 +