stripe-ruby-mock 2.3.1 → 2.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env +2 -0
- data/.travis.yml +8 -4
- data/README.md +12 -5
- data/lib/stripe_mock/api/account_balance.rb +14 -0
- data/lib/stripe_mock/api/client.rb +4 -4
- data/lib/stripe_mock/api/conversion_rate.rb +14 -0
- data/lib/stripe_mock/api/errors.rb +25 -13
- data/lib/stripe_mock/api/instance.rb +16 -6
- data/lib/stripe_mock/api/webhooks.rb +8 -1
- data/lib/stripe_mock/client.rb +18 -2
- data/lib/stripe_mock/data/list.rb +14 -2
- data/lib/stripe_mock/data.rb +398 -58
- data/lib/stripe_mock/instance.rb +105 -9
- data/lib/stripe_mock/request_handlers/accounts.rb +41 -2
- data/lib/stripe_mock/request_handlers/balance.rb +17 -0
- data/lib/stripe_mock/request_handlers/balance_transactions.rb +18 -2
- data/lib/stripe_mock/request_handlers/charges.rb +44 -33
- data/lib/stripe_mock/request_handlers/country_spec.rb +22 -0
- data/lib/stripe_mock/request_handlers/coupons.rb +5 -4
- data/lib/stripe_mock/request_handlers/customers.rb +29 -11
- data/lib/stripe_mock/request_handlers/ephemeral_key.rb +13 -0
- data/lib/stripe_mock/request_handlers/external_accounts.rb +55 -0
- data/lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb +1 -1
- data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +9 -7
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +10 -6
- data/lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb +49 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +59 -16
- data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +3 -2
- data/lib/stripe_mock/request_handlers/invoices.rb +93 -14
- data/lib/stripe_mock/request_handlers/orders.rb +5 -5
- data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
- data/lib/stripe_mock/request_handlers/plans.rb +1 -0
- data/lib/stripe_mock/request_handlers/products.rb +43 -0
- data/lib/stripe_mock/request_handlers/recipients.rb +12 -0
- data/lib/stripe_mock/request_handlers/refunds.rb +91 -0
- data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
- data/lib/stripe_mock/request_handlers/subscriptions.rb +101 -39
- data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
- data/lib/stripe_mock/request_handlers/tokens.rb +9 -3
- data/lib/stripe_mock/request_handlers/transfers.rb +11 -5
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +15 -1
- data/lib/stripe_mock/server.rb +14 -1
- data/lib/stripe_mock/test_strategies/base.rb +10 -5
- data/lib/stripe_mock/test_strategies/live.rb +5 -0
- data/lib/stripe_mock/test_strategies/mock.rb +8 -0
- data/lib/stripe_mock/util.rb +8 -2
- data/lib/stripe_mock/version.rb +1 -1
- data/lib/stripe_mock/webhook_fixtures/account.external_account.created.json +27 -0
- data/lib/stripe_mock/webhook_fixtures/account.external_account.deleted.json +27 -0
- data/lib/stripe_mock/webhook_fixtures/account.external_account.updated.json +27 -0
- data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_reinstated.json +88 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_withdrawn.json +88 -0
- data/lib/stripe_mock/webhook_fixtures/charge.updated.json +58 -0
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +40 -10
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +39 -10
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +39 -10
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +40 -11
- data/lib/stripe_mock/webhook_fixtures/invoice.created.json +3 -2
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +92 -85
- data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +3 -2
- data/lib/stripe_mock/webhook_fixtures/plan.created.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/plan.updated.json +1 -1
- data/lib/stripe_mock.rb +15 -0
- data/spec/api/instance_spec.rb +30 -0
- data/spec/instance_spec.rb +54 -4
- data/spec/integration_examples/prepare_error_examples.rb +6 -6
- data/spec/list_spec.rb +27 -10
- data/spec/readme_spec.rb +2 -0
- data/spec/server_spec.rb +7 -3
- data/spec/shared_stripe_examples/account_examples.rb +46 -0
- data/spec/shared_stripe_examples/balance_examples.rb +11 -0
- data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
- data/spec/shared_stripe_examples/bank_examples.rb +28 -1
- data/spec/shared_stripe_examples/card_examples.rb +23 -5
- data/spec/shared_stripe_examples/card_token_examples.rb +1 -0
- data/spec/shared_stripe_examples/charge_examples.rb +131 -26
- data/spec/shared_stripe_examples/country_specs_examples.rb +18 -0
- data/spec/shared_stripe_examples/coupon_examples.rb +8 -2
- data/spec/shared_stripe_examples/customer_examples.rb +90 -0
- data/spec/shared_stripe_examples/dispute_examples.rb +19 -8
- data/spec/shared_stripe_examples/ephemeral_key_examples.rb +17 -0
- data/spec/shared_stripe_examples/error_mock_examples.rb +15 -5
- data/spec/shared_stripe_examples/external_account_examples.rb +170 -0
- data/spec/shared_stripe_examples/extra_features_examples.rb +2 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +314 -51
- data/spec/shared_stripe_examples/payout_examples.rb +68 -0
- data/spec/shared_stripe_examples/plan_examples.rb +47 -4
- data/spec/shared_stripe_examples/product_example.rb +65 -0
- data/spec/shared_stripe_examples/recipient_examples.rb +13 -7
- data/spec/shared_stripe_examples/refund_examples.rb +453 -84
- data/spec/shared_stripe_examples/subscription_examples.rb +477 -32
- data/spec/shared_stripe_examples/subscription_items_examples.rb +75 -0
- data/spec/shared_stripe_examples/tax_rate_examples.rb +42 -0
- data/spec/shared_stripe_examples/transfer_examples.rb +72 -23
- data/spec/shared_stripe_examples/webhook_event_examples.rb +74 -5
- data/spec/spec_helper.rb +7 -6
- data/spec/stripe_mock_spec.rb +16 -3
- data/spec/support/stripe_examples.rb +8 -1
- data/spec/util_spec.rb +35 -1
- data/stripe-ruby-mock.gemspec +1 -1
- metadata +44 -8
- data/ChangeLog.rdoc +0 -4
@@ -52,7 +52,7 @@ shared_examples 'Invoice API' do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it "stores all invoices in memory" do
|
55
|
-
expect(Stripe::Invoice.all.map(&:id)).to eq([@invoice.id, @invoice2.id])
|
55
|
+
expect(Stripe::Invoice.all.map(&:id).sort).to eq([@invoice.id, @invoice2.id].sort)
|
56
56
|
end
|
57
57
|
|
58
58
|
it "defaults count to 10 invoices" do
|
@@ -76,57 +76,111 @@ shared_examples 'Invoice API' do
|
|
76
76
|
context "paying an invoice" do
|
77
77
|
before do
|
78
78
|
@invoice = Stripe::Invoice.create
|
79
|
-
@invoice.pay
|
80
79
|
end
|
81
80
|
|
82
81
|
it 'updates attempted and paid flags' do
|
82
|
+
@invoice = @invoice.pay
|
83
83
|
expect(@invoice.attempted).to eq(true)
|
84
84
|
expect(@invoice.paid).to eq(true)
|
85
85
|
end
|
86
86
|
|
87
|
+
it 'creates a new charge object' do
|
88
|
+
expect{ @invoice.pay }.to change { Stripe::Charge.list.data.count }.by 1
|
89
|
+
end
|
90
|
+
|
87
91
|
it 'sets the charge attribute' do
|
92
|
+
@invoice = @invoice.pay
|
88
93
|
expect(@invoice.charge).to be_a String
|
89
94
|
expect(@invoice.charge.length).to be > 0
|
90
95
|
end
|
96
|
+
|
97
|
+
it 'charges the invoice customers default card' do
|
98
|
+
customer = Stripe::Customer.create({
|
99
|
+
source: stripe_helper.generate_card_token
|
100
|
+
})
|
101
|
+
customer_invoice = Stripe::Invoice.create({customer: customer})
|
102
|
+
|
103
|
+
customer_invoice.pay
|
104
|
+
|
105
|
+
expect(Stripe::Charge.list.data.first.customer).to eq customer.id
|
106
|
+
end
|
91
107
|
end
|
92
108
|
|
93
109
|
context "retrieving upcoming invoice" do
|
94
|
-
|
95
|
-
|
96
|
-
|
110
|
+
let(:customer) { Stripe::Customer.create(source: stripe_helper.generate_card_token) }
|
111
|
+
let(:coupon_amtoff) { stripe_helper.create_coupon(id: '100OFF', currency: 'usd', amount_off: 100_00, duration: 'repeating', duration_in_months: 6) }
|
112
|
+
let(:coupon_pctoff) { stripe_helper.create_coupon(id: '50%OFF', currency: 'usd', percent_off: 50, amount_off: nil, duration: 'repeating', duration_in_months: 6) }
|
113
|
+
let(:plan) { stripe_helper.create_plan(id: '50m', amount: 50_00, interval: 'month', name: '50m', currency: 'usd') }
|
114
|
+
let(:quantity) { 3 }
|
115
|
+
let(:subscription) { Stripe::Subscription.create(plan: plan.id, customer: customer.id, quantity: quantity) }
|
116
|
+
|
117
|
+
before(with_customer: true) { customer }
|
118
|
+
before(with_coupon_amtoff: true) { coupon_amtoff }
|
119
|
+
before(with_coupon_pctoff: true) { coupon_pctoff }
|
120
|
+
before(with_discount_amtoff: true) { customer.coupon = coupon_amtoff.id; customer.save }
|
121
|
+
before(with_discount_pctoff: true) { customer.coupon = coupon_pctoff.id; customer.save }
|
122
|
+
before(with_plan: true) { plan }
|
123
|
+
before(with_subscription: true) { subscription }
|
124
|
+
|
125
|
+
# after { subscription.delete rescue nil if @teardown_subscription }
|
126
|
+
# after { plan.delete rescue nil if @teardown_plan }
|
127
|
+
# after { coupon_pctoff.delete rescue nil if @teardown_coupon_pctoff }
|
128
|
+
# after { coupon_amtoff.delete rescue nil if @teardown_coupon_amtoff }
|
129
|
+
# after { customer.delete rescue nil if @teardown_customer }
|
130
|
+
|
131
|
+
describe 'parameter validation' do
|
132
|
+
it 'fails without parameters' do
|
133
|
+
expect { Stripe::Invoice.upcoming() }.to raise_error {|e|
|
134
|
+
expect(e).to be_a(ArgumentError) }
|
135
|
+
end
|
97
136
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
137
|
+
it 'fails without a valid customer' do
|
138
|
+
expect { Stripe::Invoice.upcoming(customer: 'whatever') }.to raise_error {|e|
|
139
|
+
expect(e).to be_a(Stripe::InvalidRequestError)
|
140
|
+
expect(e.message).to eq('No such customer: whatever') }
|
141
|
+
end
|
102
142
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
143
|
+
it 'fails without a customer parameter' do
|
144
|
+
expect { Stripe::Invoice.upcoming(gazebo: 'raindance') }.to raise_error {|e|
|
145
|
+
expect(e).to be_a(Stripe::InvalidRequestError)
|
146
|
+
expect(e.http_status).to eq(400)
|
147
|
+
expect(e.message).to eq('Missing required param: customer') }
|
148
|
+
end
|
108
149
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
150
|
+
it 'fails without a subscription' do
|
151
|
+
expect { Stripe::Invoice.upcoming(customer: customer.id) }.to raise_error {|e|
|
152
|
+
expect(e).to be_a(Stripe::InvalidRequestError)
|
153
|
+
expect(e.http_status).to eq(404)
|
154
|
+
expect(e.message).to eq("No upcoming invoices for customer: #{customer.id}") }
|
155
|
+
end
|
114
156
|
end
|
115
157
|
|
116
|
-
|
117
|
-
|
118
|
-
expect(
|
119
|
-
|
120
|
-
|
158
|
+
describe 'parameter validation' do
|
159
|
+
it 'fails without a subscription or subscription plan if subscription proration date is specified', live: true do
|
160
|
+
expect { Stripe::Invoice.upcoming(customer: customer.id, subscription_proration_date: Time.now.to_i) }.to raise_error do |e|
|
161
|
+
expect(e).to be_a Stripe::InvalidRequestError
|
162
|
+
expect(e.http_status).to eq 400
|
163
|
+
expect(e.message).to eq 'When previewing changes to a subscription, you must specify either `subscription` or `subscription_items`'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'fails without a subscription if proration date is specified', live: true, with_subscription: true do
|
168
|
+
expect { Stripe::Invoice.upcoming(customer: customer.id, subscription_plan: plan.id, subscription_proration_date: Time.now.to_i) }.to raise_error do |e|
|
169
|
+
expect(e).to be_a Stripe::InvalidRequestError
|
170
|
+
expect(e.http_status).to eq 400
|
171
|
+
expect(e.message).to eq 'Cannot specify proration date without specifying a subscription'
|
172
|
+
end
|
173
|
+
end
|
121
174
|
end
|
122
175
|
|
123
|
-
it '
|
124
|
-
|
125
|
-
|
126
|
-
upcoming = Stripe::Invoice.upcoming(customer: @customer.id)
|
176
|
+
it 'considers current subscription', live: true, with_subscription: true do
|
177
|
+
# When
|
178
|
+
upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
127
179
|
|
180
|
+
# Then
|
128
181
|
expect(upcoming).to be_a Stripe::Invoice
|
129
|
-
expect(upcoming.customer).to eq(
|
182
|
+
expect(upcoming.customer).to eq(customer.id)
|
183
|
+
expect(upcoming.amount_due).to eq plan.amount * quantity
|
130
184
|
expect(upcoming.total).to eq(upcoming.lines.data[0].amount)
|
131
185
|
expect(upcoming.period_end).to eq(upcoming.lines.data[0].period.start)
|
132
186
|
expect(Time.at(upcoming.period_start).to_datetime >> 1).to eq(Time.at(upcoming.period_end).to_datetime) # +1 month
|
@@ -135,10 +189,213 @@ shared_examples 'Invoice API' do
|
|
135
189
|
expect(upcoming.subscription).to eq(subscription.id)
|
136
190
|
end
|
137
191
|
|
192
|
+
describe 'discounts' do
|
193
|
+
it 'considers a $ off discount', live: true, with_discount_amtoff: true, with_subscription: true do
|
194
|
+
# When
|
195
|
+
upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
196
|
+
|
197
|
+
# Then
|
198
|
+
expect(upcoming.discount).not_to be_nil
|
199
|
+
expect(upcoming.discount.coupon.id).to eq '100OFF'
|
200
|
+
expect(upcoming.discount.customer).to eq customer.id
|
201
|
+
expect(upcoming.discount.start).to be_within(5).of Time.now.to_i
|
202
|
+
expect(upcoming.discount.end).to be_within(5).of (Time.now.to_datetime >> 6).to_time.to_i
|
203
|
+
expect(upcoming.amount_due).to eq plan.amount * quantity - 100_00
|
204
|
+
expect(upcoming.subtotal).to eq(upcoming.lines.data[0].amount)
|
205
|
+
expect(upcoming.total).to eq upcoming.subtotal - 100_00
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'considers a % off discount', live: true, with_discount_pctoff: true, with_subscription: true do
|
209
|
+
# When
|
210
|
+
upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
211
|
+
|
212
|
+
# Then
|
213
|
+
expect(upcoming.discount).not_to be_nil
|
214
|
+
expect(upcoming.discount.coupon.id).to eq '50%OFF'
|
215
|
+
expect(upcoming.discount.customer).to eq customer.id
|
216
|
+
expect(upcoming.discount.start).to be_within(5).of Time.now.to_i
|
217
|
+
expect(upcoming.discount.end).to be_within(5).of (Time.now.to_datetime >> 6).to_time.to_i
|
218
|
+
expect(upcoming.amount_due).to eq (plan.amount * quantity) * 0.5
|
219
|
+
expect(upcoming.subtotal).to eq(upcoming.lines.data[0].amount)
|
220
|
+
expect(upcoming.total).to eq upcoming.subtotal * 0.5
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe 'proration' do
|
225
|
+
shared_examples 'failing when proration date is outside of the subscription current period' do
|
226
|
+
it 'fails', live: true do
|
227
|
+
expect { Stripe::Invoice.upcoming(
|
228
|
+
customer: customer.id,
|
229
|
+
subscription: subscription.id,
|
230
|
+
subscription_plan: plan.id,
|
231
|
+
subscription_quantity: quantity,
|
232
|
+
subscription_proration_date: proration_date.to_i,
|
233
|
+
subscription_trial_end: nil
|
234
|
+
) }.to raise_error {|e|
|
235
|
+
expect(e).to be_a(Stripe::InvalidRequestError)
|
236
|
+
expect(e.http_status).to eq(400)
|
237
|
+
expect(e.message).to eq('Cannot specify proration date outside of current subscription period') }
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
it_behaves_like 'failing when proration date is outside of the subscription current period' do
|
242
|
+
let(:proration_date) { subscription.current_period_start - 1 }
|
243
|
+
end
|
244
|
+
|
245
|
+
it_behaves_like 'failing when proration date is outside of the subscription current period' do
|
246
|
+
let(:proration_date) { subscription.current_period_end + 1 }
|
247
|
+
end
|
248
|
+
|
249
|
+
[false, true].each do |with_trial|
|
250
|
+
describe "prorating a subscription with a new plan, with_trial: #{with_trial}" do
|
251
|
+
let(:new_monthly_plan) { stripe_helper.create_plan(id: '100m', amount: 100_00, interval: 'month', name: '100m', currency: 'usd') }
|
252
|
+
let(:new_yearly_plan) { stripe_helper.create_plan(id: '100y', amount: 100_00, interval: 'year', name: '100y', currency: 'usd') }
|
253
|
+
let(:plan) { stripe_helper.create_plan(id: '50m', amount: 50_00, interval: 'month', name: '50m', currency: 'usd') }
|
254
|
+
|
255
|
+
it 'prorates while maintaining billing interval', live: true do
|
256
|
+
# Given
|
257
|
+
proration_date = Time.now + 5 * 24 * 3600 # 5 days later
|
258
|
+
new_quantity = 2
|
259
|
+
unused_amount = plan.amount * quantity * (subscription.current_period_end - proration_date.to_i) / (subscription.current_period_end - subscription.current_period_start)
|
260
|
+
remaining_amount = new_monthly_plan.amount * new_quantity * (subscription.current_period_end - proration_date.to_i) / (subscription.current_period_end - subscription.current_period_start)
|
261
|
+
prorated_amount_due = new_monthly_plan.amount * new_quantity - unused_amount + remaining_amount
|
262
|
+
credit_balance = 1000
|
263
|
+
customer.account_balance = -credit_balance
|
264
|
+
customer.save
|
265
|
+
query = { customer: customer.id, subscription: subscription.id, subscription_plan: new_monthly_plan.id, subscription_proration_date: proration_date.to_i, subscription_quantity: new_quantity }
|
266
|
+
query[:subscription_trial_end] = (DateTime.now >> 1).to_time.to_i if with_trial
|
267
|
+
|
268
|
+
# When
|
269
|
+
upcoming = Stripe::Invoice.upcoming(query)
|
270
|
+
|
271
|
+
# Then
|
272
|
+
expect(upcoming).to be_a Stripe::Invoice
|
273
|
+
expect(upcoming.customer).to eq(customer.id)
|
274
|
+
if with_trial
|
275
|
+
expect(upcoming.amount_due).to be_within(1).of 0
|
276
|
+
else
|
277
|
+
expect(upcoming.amount_due).to be_within(1).of prorated_amount_due - credit_balance
|
278
|
+
end
|
279
|
+
expect(upcoming.starting_balance).to eq -credit_balance
|
280
|
+
expect(upcoming.ending_balance).to be_nil
|
281
|
+
expect(upcoming.subscription).to eq(subscription.id)
|
282
|
+
|
283
|
+
if with_trial
|
284
|
+
expect(upcoming.lines.data.length).to eq(2)
|
285
|
+
else
|
286
|
+
expect(upcoming.lines.data.length).to eq(3)
|
287
|
+
end
|
288
|
+
|
289
|
+
expect(upcoming.lines.data[0].proration).to be_truthy
|
290
|
+
expect(upcoming.lines.data[0].plan.id).to eq '50m'
|
291
|
+
expect(upcoming.lines.data[0].amount).to be_within(1).of -unused_amount
|
292
|
+
expect(upcoming.lines.data[0].quantity).to eq quantity
|
293
|
+
|
294
|
+
unless with_trial
|
295
|
+
expect(upcoming.lines.data[1].proration).to be_truthy
|
296
|
+
expect(upcoming.lines.data[1].plan.id).to eq '100m'
|
297
|
+
expect(upcoming.lines.data[1].amount).to be_within(1).of remaining_amount
|
298
|
+
expect(upcoming.lines.data[1].quantity).to eq new_quantity
|
299
|
+
end
|
300
|
+
|
301
|
+
expect(upcoming.lines.data.last.proration).to be_falsey
|
302
|
+
expect(upcoming.lines.data.last.plan.id).to eq '100m'
|
303
|
+
expect(upcoming.lines.data.last.amount).to eq with_trial ? 0 : 20000
|
304
|
+
expect(upcoming.lines.data.last.quantity).to eq new_quantity
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'prorates while changing billing intervals', live: true do
|
308
|
+
# Given
|
309
|
+
proration_date = Time.now + 5 * 24 * 3600 # 5 days later
|
310
|
+
new_quantity = 2
|
311
|
+
unused_amount = plan.amount * quantity * (subscription.current_period_end - proration_date.to_i) / (subscription.current_period_end - subscription.current_period_start)
|
312
|
+
prorated_amount_due = new_yearly_plan.amount * new_quantity - unused_amount
|
313
|
+
credit_balance = 1000
|
314
|
+
customer.account_balance = -credit_balance
|
315
|
+
customer.save
|
316
|
+
query = { customer: customer.id, subscription: subscription.id, subscription_plan: new_yearly_plan.id, subscription_proration_date: proration_date.to_i, subscription_quantity: new_quantity }
|
317
|
+
query[:subscription_trial_end] = (DateTime.now >> 1).to_time.to_i if with_trial
|
318
|
+
|
319
|
+
# When
|
320
|
+
upcoming = Stripe::Invoice.upcoming(query)
|
321
|
+
|
322
|
+
# Then
|
323
|
+
expect(upcoming).to be_a Stripe::Invoice
|
324
|
+
expect(upcoming.customer).to eq(customer.id)
|
325
|
+
if with_trial
|
326
|
+
expect(upcoming.amount_due).to eq 0
|
327
|
+
else
|
328
|
+
expect(upcoming.amount_due).to be_within(1).of prorated_amount_due - credit_balance
|
329
|
+
end
|
330
|
+
expect(upcoming.starting_balance).to eq -credit_balance
|
331
|
+
expect(upcoming.ending_balance).to be_nil
|
332
|
+
expect(upcoming.subscription).to eq(subscription.id)
|
333
|
+
|
334
|
+
expect(upcoming.lines.data[0].proration).to be_truthy
|
335
|
+
expect(upcoming.lines.data[0].plan.id).to eq '50m'
|
336
|
+
expect(upcoming.lines.data[0].amount).to be_within(1).of -unused_amount
|
337
|
+
expect(upcoming.lines.data[0].quantity).to eq quantity
|
338
|
+
|
339
|
+
expect(upcoming.lines.data[1].proration).to be_falsey
|
340
|
+
expect(upcoming.lines.data[1].plan.id).to eq '100y'
|
341
|
+
expect(upcoming.lines.data[1].amount).to eq with_trial ? 0 : 20000
|
342
|
+
expect(upcoming.lines.data[1].quantity).to eq new_quantity
|
343
|
+
end
|
344
|
+
|
345
|
+
# after { new_monthly_plan.delete rescue nil if @teardown_monthly_plan }
|
346
|
+
# after { new_yearly_plan.delete rescue nil if @teardown_yearly_plan }
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
shared_examples 'no proration is done' do
|
351
|
+
it 'generates a preview without performing an actual proration', live: true do
|
352
|
+
expect(preview.subtotal).to eq 150_00
|
353
|
+
# this is a future invoice (generted at the end of the current subscription cycle), rather than a proration invoice
|
354
|
+
expect(preview.created).to be_within(1).of subscription.current_period_end
|
355
|
+
expect(preview.period_start).to eq subscription.current_period_start
|
356
|
+
expect(preview.period_end).to eq subscription.current_period_end
|
357
|
+
expect(preview.lines.count).to eq 1
|
358
|
+
line = preview.lines.first
|
359
|
+
expect(line.type).to eq 'subscription'
|
360
|
+
expect(line.amount).to eq 150_00
|
361
|
+
# line period is for the NEXT subscription cycle
|
362
|
+
expect(line.period.start).to be_within(1).of subscription.current_period_end
|
363
|
+
expect(Time.at(line.period.end).month).to be_within(1).of (Time.at(subscription.current_period_end).to_datetime >> 1).month # +1 month
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
describe 'upcoming invoice with no proration parameters specified' do
|
368
|
+
let(:preview) do
|
369
|
+
Stripe::Invoice.upcoming(
|
370
|
+
customer: customer.id,
|
371
|
+
subscription: subscription.id
|
372
|
+
)
|
373
|
+
end
|
374
|
+
|
375
|
+
it_behaves_like 'no proration is done'
|
376
|
+
end
|
377
|
+
|
378
|
+
describe 'upcoming invoice with same subscription plan and quantity specified' do
|
379
|
+
let(:preview) do
|
380
|
+
proration_date = Time.now + 60
|
381
|
+
Stripe::Invoice.upcoming(
|
382
|
+
customer: customer.id,
|
383
|
+
subscription: subscription.id,
|
384
|
+
subscription_plan: plan.id,
|
385
|
+
subscription_quantity: quantity,
|
386
|
+
subscription_proration_date: proration_date.to_i,
|
387
|
+
subscription_trial_end: nil
|
388
|
+
)
|
389
|
+
end
|
390
|
+
|
391
|
+
it_behaves_like 'no proration is done'
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
138
395
|
it 'sets the start and end of billing periods correctly when plan has an interval_count' do
|
139
396
|
@oddplan = stripe_helper.create_plan(interval: "week", interval_count: 11)
|
140
|
-
@subscription = Stripe::Subscription.create(plan: @oddplan.id, customer:
|
141
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
397
|
+
@subscription = Stripe::Subscription.create(plan: @oddplan.id, customer: customer.id)
|
398
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
142
399
|
|
143
400
|
expect(@upcoming.period_start + 6652800).to eq(@upcoming.period_end) # 6652800 = +11 weeks
|
144
401
|
expect(@upcoming.period_end).to eq(@upcoming.lines.data[0].period.start)
|
@@ -151,20 +408,26 @@ shared_examples 'Invoice API' do
|
|
151
408
|
@plainplan = stripe_helper.create_plan(id: 'b') # 1 month sub
|
152
409
|
@longplan = stripe_helper.create_plan(id: 'c', interval: "year") # 1 year sub
|
153
410
|
|
154
|
-
@plainsub = Stripe::Subscription.create(plan: @plainplan.id, customer:
|
155
|
-
@shortsub = Stripe::Subscription.create(plan: @shortplan.id, customer:
|
156
|
-
@longsub = Stripe::Subscription.create(plan: @longplan.id, customer:
|
411
|
+
@plainsub = Stripe::Subscription.create(plan: @plainplan.id, customer: customer.id)
|
412
|
+
@shortsub = Stripe::Subscription.create(plan: @shortplan.id, customer: customer.id)
|
413
|
+
@longsub = Stripe::Subscription.create(plan: @longplan.id, customer: customer.id)
|
157
414
|
|
158
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
415
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
159
416
|
|
160
417
|
expect(@upcoming.period_start + 604800).to eq(@upcoming.period_end) # 604800 = 1 week
|
161
418
|
expect(@upcoming.period_end + 604800).to eq(@upcoming.lines.data[0].period.end) # 604800 = 1 week
|
162
419
|
expect(@upcoming.subscription).to eq(@shortsub.id)
|
163
420
|
end
|
164
421
|
|
422
|
+
it 'does not store the stripe invoice in memory since its only a preview', with_subscription: true do
|
423
|
+
invoice = Stripe::Invoice.upcoming(customer: customer.id)
|
424
|
+
data = test_data_source(:invoices)
|
425
|
+
expect(data[invoice.id]).to be_nil
|
426
|
+
end
|
427
|
+
|
165
428
|
context 'retrieving invoice line items' do
|
166
429
|
it 'returns all line items for created invoice' do
|
167
|
-
invoice = Stripe::Invoice.create(customer:
|
430
|
+
invoice = Stripe::Invoice.create(customer: customer.id)
|
168
431
|
line_items = invoice.lines.all
|
169
432
|
|
170
433
|
expect(invoice).to be_a Stripe::Invoice
|
@@ -176,9 +439,9 @@ shared_examples 'Invoice API' do
|
|
176
439
|
|
177
440
|
it 'returns all line items for upcoming invoice' do
|
178
441
|
plan = stripe_helper.create_plan()
|
179
|
-
subscription = Stripe::Subscription.create(plan: plan.id, customer:
|
180
|
-
upcoming = Stripe::Invoice.upcoming(customer:
|
181
|
-
line_items = upcoming.lines
|
442
|
+
subscription = Stripe::Subscription.create(plan: plan.id, customer: customer.id)
|
443
|
+
upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
444
|
+
line_items = upcoming.lines
|
182
445
|
|
183
446
|
expect(upcoming).to be_a Stripe::Invoice
|
184
447
|
expect(line_items.count).to eq(1)
|
@@ -192,8 +455,8 @@ shared_examples 'Invoice API' do
|
|
192
455
|
|
193
456
|
it 'for one month plan on the 1st' do
|
194
457
|
@plan = stripe_helper.create_plan()
|
195
|
-
@sub = Stripe::Subscription.create(plan: @plan.id, customer:
|
196
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
458
|
+
@sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2014,1,1,12).to_i)
|
459
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
197
460
|
|
198
461
|
expect(Time.at(@upcoming.period_start)).to eq(Time.utc(2014,1,1,12))
|
199
462
|
expect(Time.at(@upcoming.period_end)).to eq(Time.utc(2014,2,1,12))
|
@@ -203,8 +466,8 @@ shared_examples 'Invoice API' do
|
|
203
466
|
|
204
467
|
it 'for one year plan on the 1st' do
|
205
468
|
@plan = stripe_helper.create_plan(interval: "year")
|
206
|
-
@sub = Stripe::Subscription.create(plan: @plan.id, customer:
|
207
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
469
|
+
@sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2012,1,1,12).to_i)
|
470
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
208
471
|
|
209
472
|
expect(Time.at(@upcoming.period_start)).to eq(Time.utc(2012,1,1,12))
|
210
473
|
expect(Time.at(@upcoming.period_end)).to eq(Time.utc(2013,1,1,12))
|
@@ -214,8 +477,8 @@ shared_examples 'Invoice API' do
|
|
214
477
|
|
215
478
|
it 'for one month plan on the 31st' do
|
216
479
|
@plan = stripe_helper.create_plan()
|
217
|
-
@sub = Stripe::Subscription.create(plan: @plan.id, customer:
|
218
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
480
|
+
@sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2014,1,31,12).to_i)
|
481
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
219
482
|
|
220
483
|
expect(Time.at(@upcoming.period_start)).to eq(Time.utc(2014,1,31,12))
|
221
484
|
expect(Time.at(@upcoming.period_end)).to eq(Time.utc(2014,2,28,12))
|
@@ -225,8 +488,8 @@ shared_examples 'Invoice API' do
|
|
225
488
|
|
226
489
|
it 'for one year plan on feb. 29th' do
|
227
490
|
@plan = stripe_helper.create_plan(interval: "year")
|
228
|
-
@sub = Stripe::Subscription.create(plan: @plan.id, customer:
|
229
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
491
|
+
@sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2012,2,29,12).to_i)
|
492
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
230
493
|
|
231
494
|
expect(Time.at(@upcoming.period_start)).to eq(Time.utc(2012,2,29,12))
|
232
495
|
expect(Time.at(@upcoming.period_end)).to eq(Time.utc(2013,2,28,12))
|
@@ -236,8 +499,8 @@ shared_examples 'Invoice API' do
|
|
236
499
|
|
237
500
|
it 'for two month plan on dec. 31st' do
|
238
501
|
@plan = stripe_helper.create_plan(interval_count: 2)
|
239
|
-
@sub = Stripe::Subscription.create(plan: @plan.id, customer:
|
240
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
502
|
+
@sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2013,12,31,12).to_i)
|
503
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
241
504
|
|
242
505
|
expect(Time.at(@upcoming.period_start)).to eq(Time.utc(2013,12,31,12))
|
243
506
|
expect(Time.at(@upcoming.period_end)).to eq(Time.utc(2014, 2,28,12))
|
@@ -247,8 +510,8 @@ shared_examples 'Invoice API' do
|
|
247
510
|
|
248
511
|
it 'for three month plan on nov. 30th' do
|
249
512
|
@plan = stripe_helper.create_plan(interval_count: 3)
|
250
|
-
@sub = Stripe::Subscription.create(plan: @plan.id, customer:
|
251
|
-
@upcoming = Stripe::Invoice.upcoming(customer:
|
513
|
+
@sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2013,11,30,12).to_i)
|
514
|
+
@upcoming = Stripe::Invoice.upcoming(customer: customer.id)
|
252
515
|
|
253
516
|
expect(Time.at(@upcoming.period_start)).to eq(Time.utc(2013,11,30,12))
|
254
517
|
expect(Time.at(@upcoming.period_end)).to eq(Time.utc(2014, 2,28,12))
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples 'Payout API' do
|
4
|
+
|
5
|
+
it "creates a stripe payout" do
|
6
|
+
payout = Stripe::Payout.create(amount: "100", currency: "usd")
|
7
|
+
|
8
|
+
expect(payout.id).to match(/^test_po/)
|
9
|
+
expect(payout.amount).to eq('100')
|
10
|
+
expect(payout.currency).to eq('usd')
|
11
|
+
expect(payout.metadata.to_hash).to eq({})
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "listing payouts" do
|
15
|
+
before do
|
16
|
+
3.times do
|
17
|
+
Stripe::Payout.create(amount: "100", currency: "usd")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "without params retrieves all tripe payouts" do
|
22
|
+
expect(Stripe::Payout.all.count).to eq(3)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "accepts a limit param" do
|
26
|
+
expect(Stripe::Payout.all(limit: 2).count).to eq(2)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "retrieves a stripe payout" do
|
31
|
+
original = Stripe::Payout.create(amount: "100", currency: "usd")
|
32
|
+
payout = Stripe::Payout.retrieve(original.id)
|
33
|
+
|
34
|
+
expect(payout.id).to eq(original.id)
|
35
|
+
expect(payout.amount).to eq(original.amount)
|
36
|
+
expect(payout.currency).to eq(original.currency)
|
37
|
+
expect(payout.metadata.to_hash).to eq(original.metadata.to_hash)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "cannot retrieve a payout that doesn't exist" do
|
41
|
+
expect { Stripe::Payout.retrieve('nope') }.to raise_error {|e|
|
42
|
+
expect(e).to be_a Stripe::InvalidRequestError
|
43
|
+
expect(e.param).to eq('payout')
|
44
|
+
expect(e.http_status).to eq(404)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'when amount is not integer', live: true do
|
49
|
+
expect { Stripe::Payout.create(amount: '400.2',
|
50
|
+
currency: 'usd',
|
51
|
+
description: 'Payout for test@example.com') }.to raise_error { |e|
|
52
|
+
expect(e).to be_a Stripe::InvalidRequestError
|
53
|
+
expect(e.param).to eq('amount')
|
54
|
+
expect(e.http_status).to eq(400)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'when amount is negative', live: true do
|
59
|
+
expect { Stripe::Payout.create(amount: '-400',
|
60
|
+
currency: 'usd',
|
61
|
+
description: 'Payout for test@example.com') }.to raise_error { |e|
|
62
|
+
expect(e).to be_a Stripe::InvalidRequestError
|
63
|
+
expect(e.param).to eq('amount')
|
64
|
+
expect(e.message).to match(/^Invalid.*integer/)
|
65
|
+
expect(e.http_status).to eq(400)
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
@@ -9,6 +9,9 @@ shared_examples 'Plan API' do
|
|
9
9
|
:amount => 9900,
|
10
10
|
:currency => 'USD',
|
11
11
|
:interval => 1,
|
12
|
+
:product => {
|
13
|
+
:name => 'A product'
|
14
|
+
},
|
12
15
|
:metadata => {
|
13
16
|
:description => "desc text",
|
14
17
|
:info => "info text"
|
@@ -30,20 +33,40 @@ shared_examples 'Plan API' do
|
|
30
33
|
end
|
31
34
|
|
32
35
|
|
36
|
+
it "creates a stripe plan without specifying ID" do
|
37
|
+
plan = Stripe::Plan.create(
|
38
|
+
:name => 'The Mock Plan',
|
39
|
+
:amount => 9900,
|
40
|
+
:currency => 'USD',
|
41
|
+
:interval => 1,
|
42
|
+
:product => {
|
43
|
+
:name => 'A product'
|
44
|
+
}
|
45
|
+
)
|
46
|
+
|
47
|
+
expect(plan.id).to match(/^test_plan/)
|
48
|
+
end
|
49
|
+
|
33
50
|
it "stores a created stripe plan in memory" do
|
34
51
|
plan = Stripe::Plan.create(
|
35
52
|
:id => 'pid_2',
|
36
53
|
:name => 'The Memory Plan',
|
37
54
|
:amount => 1100,
|
38
55
|
:currency => 'USD',
|
39
|
-
:interval => 1
|
56
|
+
:interval => 1,
|
57
|
+
:product => {
|
58
|
+
:name => 'A product'
|
59
|
+
}
|
40
60
|
)
|
41
61
|
plan2 = Stripe::Plan.create(
|
42
62
|
:id => 'pid_3',
|
43
63
|
:name => 'The Bonk Plan',
|
44
64
|
:amount => 7777,
|
45
65
|
:currency => 'USD',
|
46
|
-
:interval => 1
|
66
|
+
:interval => 1,
|
67
|
+
:product => {
|
68
|
+
:name => 'A product'
|
69
|
+
}
|
47
70
|
)
|
48
71
|
data = test_data_source(:plans)
|
49
72
|
expect(data[plan.id]).to_not be_nil
|
@@ -118,6 +141,20 @@ shared_examples 'Plan API' do
|
|
118
141
|
expect(all.count).to eq(100)
|
119
142
|
end
|
120
143
|
|
144
|
+
it 'validates the amount' do
|
145
|
+
expect {
|
146
|
+
Stripe::Plan.create(
|
147
|
+
:id => 'pid_1',
|
148
|
+
:name => 'The Mock Plan',
|
149
|
+
:amount => 99.99,
|
150
|
+
:currency => 'USD',
|
151
|
+
:interval => 'month',
|
152
|
+
:product => {
|
153
|
+
:name => 'A product'
|
154
|
+
}
|
155
|
+
)
|
156
|
+
}.to raise_error(Stripe::InvalidRequestError, "Invalid integer: 99.99")
|
157
|
+
end
|
121
158
|
|
122
159
|
describe "Validation", :live => true do
|
123
160
|
let(:params) { stripe_helper.create_plan_params }
|
@@ -126,10 +163,16 @@ shared_examples 'Plan API' do
|
|
126
163
|
describe "Required Parameters" do
|
127
164
|
after do
|
128
165
|
params.delete(@name)
|
129
|
-
|
166
|
+
message =
|
167
|
+
if @name == :amount
|
168
|
+
"Plans require an `#{@name}` parameter to be set."
|
169
|
+
else
|
170
|
+
"Missing required param: #{@name}."
|
171
|
+
end
|
172
|
+
expect { subject }.to raise_error(Stripe::InvalidRequestError, message)
|
130
173
|
end
|
131
174
|
|
132
|
-
it("requires a
|
175
|
+
it("requires a product") { @name = :product }
|
133
176
|
it("requires an amount") { @name = :amount }
|
134
177
|
it("requires a currency") { @name = :currency }
|
135
178
|
it("requires an interval") { @name = :interval }
|