forked from solidusio/solidus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
payment_spec.rb
247 lines (204 loc) · 8.22 KB
/
payment_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
require 'spec_helper'
module Spree
describe Spree::Order, type: :model do
let(:order) { stub_model(Spree::Order) }
let(:updater) { Spree::OrderUpdater.new(order) }
context "processing payments" do
let(:order) { create(:order_with_line_items, shipment_cost: 0, line_items_price: 100) }
before do
# So that Payment#purchase! is called during processing
Spree::Config[:auto_capture] = true
end
it 'processes all checkout payments' do
payment_1 = create(:payment, order: order, amount: 50)
payment_2 = create(:payment, order: order, amount: 50)
order.process_payments!
updater.update_payment_state
expect(order.payment_state).to eq('paid')
expect(order.payment_total).to eq(100)
expect(payment_1).to be_completed
expect(payment_2).to be_completed
end
it 'does not go over total for order' do
payment_1 = create(:payment, order: order, amount: 50)
payment_2 = create(:payment, order: order, amount: 50)
payment_3 = create(:payment, order: order, amount: 50)
order.process_payments!
updater.update_payment_state
expect(order.payment_state).to eq('paid')
expect(order.payment_total).to eq(100)
expect(payment_1).to be_completed
expect(payment_2).to be_completed
expect(payment_3).to be_checkout
end
it "does not use failed payments" do
payment1 = create(:payment, order: order, amount: 50)
payment2 = create(:payment, order: order, amount: 50, state: 'failed')
expect(payment1).to receive(:process!).and_call_original
expect(payment2).not_to receive(:process!)
order.process_payments!
expect(order.payment_total).to eq(50)
end
end
context "with payments completed" do
it "should not fail transitioning to complete when paid" do
expect(order).to receive_messages total: 100, payment_total: 100
expect(order.process_payments!).to be_truthy
end
end
context "ensure source attributes stick around" do
let(:order){ Spree::Order.create }
let(:payment_method){ create(:credit_card_payment_method) }
let(:payment_attributes) do
{
payment_method_id: payment_method.id,
source_attributes: {
name: "Ryan Bigg",
number: "41111111111111111111",
expiry: "01 / 15",
verification_value: "123"
}
}
end
it "keeps source attributes on assignment" do
OrderUpdateAttributes.new(order, payments_attributes: [payment_attributes]).apply
expect(order.unprocessed_payments.last.source.number).to be_present
end
# For the reason of this test, please see spree/spree_gateway#132
it "keeps source attributes through OrderUpdateAttributes" do
OrderUpdateAttributes.new(order, payments_attributes: [payment_attributes]).apply
expect(order.unprocessed_payments.last.source.number).to be_present
end
end
context "checking if order is paid" do
context "payment_state is paid" do
before { allow(order).to receive_messages payment_state: 'paid' }
it { expect(order).to be_paid }
end
context "payment_state is credit_owned" do
before { allow(order).to receive_messages payment_state: 'credit_owed' }
it { expect(order).to be_paid }
end
end
context "#process_payments!" do
let(:payment) { stub_model(Spree::Payment) }
before { allow(order).to receive_messages unprocessed_payments: [payment], total: 10 }
it "should process the payments" do
expect(payment).to receive(:process!)
expect(order.process_payments!).to be_truthy
end
context "when a payment raises a GatewayError" do
before { expect(payment).to receive(:process!).and_raise(Spree::Core::GatewayError) }
it "should return true when configured to allow checkout on gateway failures" do
Spree::Config.set allow_checkout_on_gateway_error: true
expect(order.process_payments!).to be true
end
it "should return false when not configured to allow checkout on gateway failures" do
Spree::Config.set allow_checkout_on_gateway_error: false
expect(order.process_payments!).to be false
end
end
end
context "#authorize_payments!" do
let(:payment) { stub_model(Spree::Payment) }
before { allow(order).to receive_messages unprocessed_payments: [payment], total: 10 }
subject { order.authorize_payments! }
it "processes payments with attempt_authorization!" do
expect(payment).to receive(:authorize!)
subject
end
it { is_expected.to be_truthy }
end
context "#capture_payments!" do
let(:payment) { stub_model(Spree::Payment) }
before { allow(order).to receive_messages unprocessed_payments: [payment], total: 10 }
subject { order.capture_payments! }
it "processes payments with attempt_authorization!" do
expect(payment).to receive(:purchase!)
subject
end
it { is_expected.to be_truthy }
end
context "#outstanding_balance" do
it "should return positive amount when payment_total is less than total" do
order.payment_total = 20.20
order.total = 30.30
expect(order.outstanding_balance).to eq(10.10)
end
it "should return negative amount when payment_total is greater than total" do
order.total = 8.20
order.payment_total = 10.20
expect(order.outstanding_balance).to be_within(0.001).of(-2.00)
end
context "with reimburesements on the order" do
let(:amount) { 10.0 }
let(:reimbursement) { create(:reimbursement) }
let(:order) { reimbursement.order.reload }
before do
# Set the payment amount to actually be the order total of 110
reimbursement.order.payments.first.update_column :amount, amount
# Creates a refund of 110
create :refund, amount: amount,
payment: reimbursement.order.payments.first,
reimbursement: reimbursement
# Update the order totals so payment_total goes to 0 reflecting the refund..
order.recalculate
end
context "for canceled orders" do
before { order.update_attributes(state: 'canceled') }
it "it should be zero" do
expect(order.total).to eq(110)
expect(order.payments.sum(:amount)).to eq(10)
expect(order.refund_total).to eq(10)
expect(order.reimbursement_total).to eq(10)
expect(order.payment_total).to eq(0)
expect(order.outstanding_balance).to eq(0)
end
end
context "for non-canceled orders" do
it 'should incorporate refund reimbursements' do
# Order Total - (Payment Total + Reimbursed)
# 110 - (0 + 10) = 100
expect(order.outstanding_balance).to eq 100
end
end
end
end
context "#outstanding_balance?" do
it "should be true when total greater than payment_total" do
order.total = 10.10
order.payment_total = 9.50
expect(order.outstanding_balance?).to be true
end
it "should be true when total less than payment_total" do
order.total = 8.25
order.payment_total = 10.44
expect(order.outstanding_balance?).to be true
end
it "should be false when total equals payment_total" do
order.total = 10.10
order.payment_total = 10.10
expect(order.outstanding_balance?).to be false
end
end
context "payment_required?" do
before { order.total = total }
context "total is zero" do
let(:total) { 0 }
it { expect(order).not_to be_payment_required }
end
context "total is once cent" do
let(:total) { 1 }
it { expect(order).to be_payment_required }
end
context "total is once dollar" do
let(:total) { 1 }
it { expect(order).to be_payment_required }
end
context "total is huge" do
let(:total) { 2**32 }
it { expect(order).to be_payment_required }
end
end
end
end