stripe-ruby-mock 3.1.0.rc3 → 3.1.0

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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec_tests.yml +38 -0
  3. data/.rspec +2 -1
  4. data/CHANGELOG.md +28 -0
  5. data/README.md +5 -3
  6. data/lib/stripe_mock/api/webhooks.rb +65 -26
  7. data/lib/stripe_mock/data.rb +80 -11
  8. data/lib/stripe_mock/instance.rb +6 -2
  9. data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
  10. data/lib/stripe_mock/request_handlers/charges.rb +5 -0
  11. data/lib/stripe_mock/request_handlers/checkout_session.rb +158 -1
  12. data/lib/stripe_mock/request_handlers/events.rb +30 -3
  13. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +1 -0
  14. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +28 -9
  15. data/lib/stripe_mock/request_handlers/invoices.rb +6 -1
  16. data/lib/stripe_mock/request_handlers/payment_intents.rb +13 -2
  17. data/lib/stripe_mock/request_handlers/payment_methods.rb +5 -1
  18. data/lib/stripe_mock/request_handlers/prices.rb +18 -0
  19. data/lib/stripe_mock/request_handlers/promotion_codes.rb +43 -0
  20. data/lib/stripe_mock/request_handlers/refunds.rb +13 -2
  21. data/lib/stripe_mock/request_handlers/setup_intents.rb +16 -9
  22. data/lib/stripe_mock/request_handlers/subscriptions.rb +93 -4
  23. data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
  24. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +5 -4
  25. data/lib/stripe_mock/test_strategies/base.rb +51 -24
  26. data/lib/stripe_mock/version.rb +1 -1
  27. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  28. data/lib/stripe_mock/webhook_fixtures/balance.available.json +26 -20
  29. data/lib/stripe_mock/webhook_fixtures/charge.captured.json +143 -0
  30. data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +63 -16
  31. data/lib/stripe_mock/webhook_fixtures/charge.failed.json +49 -120
  32. data/lib/stripe_mock/webhook_fixtures/charge.refund.updated.json +35 -0
  33. data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +145 -50
  34. data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +114 -43
  35. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.json +79 -0
  36. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.payment_mode.json +53 -0
  37. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.setup_mode.json +45 -0
  38. data/lib/stripe_mock/webhook_fixtures/customer.created.json +37 -46
  39. data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +36 -32
  40. data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +31 -22
  41. data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -25
  42. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +135 -47
  43. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +134 -45
  44. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +135 -56
  45. data/lib/stripe_mock/webhook_fixtures/customer.updated.json +38 -47
  46. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +176 -49
  47. data/lib/stripe_mock/webhook_fixtures/invoice.finalized.json +171 -0
  48. data/lib/stripe_mock/webhook_fixtures/invoice.paid.json +171 -0
  49. data/lib/stripe_mock/webhook_fixtures/invoice.payment_action_required.json +171 -0
  50. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +149 -83
  51. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +149 -90
  52. data/lib/stripe_mock/webhook_fixtures/invoice.upcoming.json +70 -0
  53. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +178 -50
  54. data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +87 -13
  55. data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +88 -14
  56. data/lib/stripe_mock/webhook_fixtures/mandate.updated.json +34 -0
  57. data/lib/stripe_mock/webhook_fixtures/payment_intent.amount_capturable_updated.json +170 -0
  58. data/lib/stripe_mock/webhook_fixtures/payment_intent.canceled.json +73 -0
  59. data/lib/stripe_mock/webhook_fixtures/payment_intent.created.json +86 -0
  60. data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +118 -79
  61. data/lib/stripe_mock/webhook_fixtures/payment_intent.processing.json +162 -0
  62. data/lib/stripe_mock/webhook_fixtures/payment_intent.requires_action.json +191 -0
  63. data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +85 -53
  64. data/lib/stripe_mock/webhook_fixtures/payment_link.created.json +47 -0
  65. data/lib/stripe_mock/webhook_fixtures/payment_link.updated.json +50 -0
  66. data/lib/stripe_mock/webhook_fixtures/payment_method.attached.json +63 -0
  67. data/lib/stripe_mock/webhook_fixtures/payment_method.detached.json +62 -0
  68. data/lib/stripe_mock/webhook_fixtures/payout.created.json +40 -0
  69. data/lib/stripe_mock/webhook_fixtures/payout.paid.json +40 -0
  70. data/lib/stripe_mock/webhook_fixtures/payout.updated.json +46 -0
  71. data/lib/stripe_mock/webhook_fixtures/plan.created.json +30 -13
  72. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +30 -13
  73. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +34 -14
  74. data/lib/stripe_mock/webhook_fixtures/price.created.json +42 -0
  75. data/lib/stripe_mock/webhook_fixtures/price.deleted.json +42 -0
  76. data/lib/stripe_mock/webhook_fixtures/price.updated.json +48 -0
  77. data/lib/stripe_mock/webhook_fixtures/product.created.json +19 -13
  78. data/lib/stripe_mock/webhook_fixtures/product.deleted.json +20 -14
  79. data/lib/stripe_mock/webhook_fixtures/product.updated.json +24 -15
  80. data/lib/stripe_mock/webhook_fixtures/quote.accepted.json +92 -0
  81. data/lib/stripe_mock/webhook_fixtures/quote.canceled.json +92 -0
  82. data/lib/stripe_mock/webhook_fixtures/quote.created.json +92 -0
  83. data/lib/stripe_mock/webhook_fixtures/quote.finalized.json +92 -0
  84. data/lib/stripe_mock/webhook_fixtures/setup_intent.canceled.json +46 -0
  85. data/lib/stripe_mock/webhook_fixtures/setup_intent.created.json +51 -0
  86. data/lib/stripe_mock/webhook_fixtures/setup_intent.setup_failed.json +100 -0
  87. data/lib/stripe_mock/webhook_fixtures/setup_intent.succeeded.json +46 -0
  88. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.canceled.json +119 -0
  89. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.created.json +114 -0
  90. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.released.json +111 -0
  91. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.updated.json +125 -0
  92. data/lib/stripe_mock/webhook_fixtures/tax_rate.created.json +32 -0
  93. data/lib/stripe_mock/webhook_fixtures/tax_rate.updated.json +37 -0
  94. data/lib/stripe_mock.rb +3 -1
  95. data/spec/instance_spec.rb +3 -1
  96. data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
  97. data/spec/readme_spec.rb +1 -1
  98. data/spec/shared_stripe_examples/account_examples.rb +9 -1
  99. data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
  100. data/spec/shared_stripe_examples/invoice_examples.rb +21 -0
  101. data/spec/shared_stripe_examples/payment_intent_examples.rb +74 -0
  102. data/spec/shared_stripe_examples/payment_method_examples.rb +32 -27
  103. data/spec/shared_stripe_examples/price_examples.rb +42 -2
  104. data/spec/shared_stripe_examples/promotion_code_examples.rb +68 -0
  105. data/spec/shared_stripe_examples/refund_examples.rb +13 -0
  106. data/spec/shared_stripe_examples/setup_intent_examples.rb +17 -0
  107. data/spec/shared_stripe_examples/subscription_examples.rb +213 -2
  108. data/spec/shared_stripe_examples/transfer_examples.rb +10 -1
  109. data/spec/shared_stripe_examples/webhook_event_examples.rb +51 -5
  110. data/spec/support/stripe_examples.rb +3 -1
  111. data/stripe-ruby-mock.gemspec +1 -1
  112. metadata +54 -11
  113. data/.travis.yml +0 -25
  114. data/lib/stripe_mock/request_handlers/checkout.rb +0 -15
  115. data/spec/shared_stripe_examples/checkout_examples.rb +0 -47
@@ -25,6 +25,12 @@ shared_examples 'PaymentMethod API' do
25
25
  cvc: 999
26
26
  }
27
27
  end
28
+ let(:visa_card_details) do
29
+ card_details
30
+ end
31
+ let(:mastercard_card_details) do
32
+ card_details.merge(:number => 5555_5555_5555_4444)
33
+ end
28
34
  let(:sepa_debit_details) do
29
35
  {
30
36
  iban: 'DE89370400440532013000'
@@ -385,6 +391,7 @@ shared_examples 'PaymentMethod API' do
385
391
  .from(original_card_exp_month).to(new_card_exp_month)
386
392
  end
387
393
 
394
+
388
395
  context 'without a customer' do
389
396
  it 'raises invalid requestion exception' do
390
397
  expect do
@@ -394,29 +401,39 @@ shared_examples 'PaymentMethod API' do
394
401
  end
395
402
  end
396
403
 
404
+ context 'with visa card' do
405
+ let(:payment_method) do
406
+ Stripe::PaymentMethod.create(type: 'card', card: visa_card_details)
407
+ end
408
+
409
+ it 'uses correct brand' do
410
+ expect(payment_method.card.brand).to eq('visa')
411
+ end
412
+ end
413
+
414
+ context 'with mastercard card' do
415
+ let(:payment_method) do
416
+ Stripe::PaymentMethod.create(type: 'card', card: mastercard_card_details)
417
+ end
418
+
419
+ it 'uses correct brand' do
420
+ expect(payment_method.card.brand).to eq('mastercard')
421
+ end
422
+ end
423
+
397
424
  context 'with ideal' do
398
425
  let(:payment_method) do
399
426
  Stripe::PaymentMethod.create(type: 'ideal', ideal: ideal_details)
400
427
  end
401
428
 
402
- it 'updates the ideal for the payment method' do
429
+ it 'cannot update' do
403
430
  Stripe::PaymentMethod.attach(payment_method.id, customer: customer.id)
404
431
 
405
- original_ideal_bank = payment_method.ideal.bank
406
432
  new_ideal_bank = 12
407
433
 
408
434
  expect do
409
435
  Stripe::PaymentMethod.update(payment_method.id, ideal: { bank: new_ideal_bank })
410
- end.to change { Stripe::PaymentMethod.retrieve(payment_method.id).ideal.bank }
411
- .from(original_ideal_bank).to(new_ideal_bank)
412
- end
413
-
414
- context 'without a customer' do
415
- it 'raises invalid requestion exception' do
416
- expect do
417
- Stripe::PaymentMethod.update(payment_method.id, ideal: { bank: 12 })
418
- end.to raise_error(Stripe::InvalidRequestError)
419
- end
436
+ end.to raise_error(Stripe::InvalidRequestError)
420
437
  end
421
438
  end
422
439
 
@@ -425,24 +442,12 @@ shared_examples 'PaymentMethod API' do
425
442
  Stripe::PaymentMethod.create(type: 'sepa_debit', sepa_debit: sepa_debit_details)
426
443
  end
427
444
 
428
- it 'updates the sepa_debit for the payment method' do
445
+ it 'cannot update' do
429
446
  Stripe::PaymentMethod.attach(payment_method.id, customer: customer.id)
430
447
 
431
- original_iban = payment_method.sepa_debit.iban
432
- new_iban = 'DE62370400440532013001'
433
-
434
448
  expect do
435
- Stripe::PaymentMethod.update(payment_method.id, sepa_debit: { iban: new_iban })
436
- end.to change { Stripe::PaymentMethod.retrieve(payment_method.id).sepa_debit.iban }
437
- .from(original_iban).to(new_iban)
438
- end
439
-
440
- context 'without a customer' do
441
- it 'raises invalid requestion exception' do
442
- expect do
443
- Stripe::PaymentMethod.update(payment_method.id, sepa_debit: { iban: 'DE62370400440532013001' })
444
- end.to raise_error(Stripe::InvalidRequestError)
445
- end
449
+ Stripe::PaymentMethod.update(payment_method.id, sepa_debit: { iban: 'DE62370400440532013001'})
450
+ end.to raise_error(Stripe::InvalidRequestError)
446
451
  end
447
452
  end
448
453
  end
@@ -1,8 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  shared_examples 'Price API' do
4
- let(:product) { stripe_helper.create_product }
5
- let(:product_id) { product.id }
4
+ let(:product_id) { "product_id_1" }
5
+ let(:product) { stripe_helper.create_product(id: product_id) }
6
+
7
+ let(:other_product_id) { "product_id_2" }
8
+ let(:other_product) { stripe_helper.create_product(id: other_product_id) }
6
9
 
7
10
  let(:price_attributes) { {
8
11
  :id => "price_abc123",
@@ -26,6 +29,7 @@ shared_examples 'Price API' do
26
29
 
27
30
  before(:each) do
28
31
  product
32
+ other_product
29
33
  end
30
34
 
31
35
  it "creates a stripe price" do
@@ -125,6 +129,42 @@ shared_examples 'Price API' do
125
129
  expect(two.map &:amount).to include(98765)
126
130
  end
127
131
 
132
+ it "retrieves prices filtering by currency" do
133
+ 5.times do | i|
134
+ stripe_helper.create_price(id: "usd price #{i}", product: product_id, amount: 11, currency: 'usd')
135
+ stripe_helper.create_price(id: "brl price #{i}", product: product_id, amount: 11, currency: 'brl')
136
+ end
137
+
138
+ all = Stripe::Price.list()
139
+ expect(all.count).to eq(10)
140
+
141
+ usd = Stripe::Price.list({currency: 'usd'})
142
+ expect(usd.count).to eq(5)
143
+ expect(usd.all? {|p| p.currency == 'usd' }).to be_truthy
144
+
145
+ brl = Stripe::Price.list({currency: 'brl'})
146
+ expect(brl.count).to eq(5)
147
+ expect(brl.all? {|p| p.currency == 'brl' }).to be_truthy
148
+ end
149
+
150
+ it "retrieves prices filtering by product" do
151
+ 5.times do | i|
152
+ stripe_helper.create_price(id: "product 1 price #{i}", product: product_id)
153
+ stripe_helper.create_price(id: "product 2 price #{i}", product: other_product_id)
154
+ end
155
+
156
+ all = Stripe::Price.list()
157
+ expect(all.count).to eq(10)
158
+
159
+ product_prices = Stripe::Price.list({product: product.id})
160
+ expect(product_prices.count).to eq(5)
161
+ expect(product_prices.all? {|p| p.product == product.id }).to be_truthy
162
+
163
+ other_product_prices = Stripe::Price.list({product: other_product.id})
164
+ expect(other_product_prices.count).to eq(5)
165
+ expect(other_product_prices.all? {|p| p.product == other_product.id }).to be_truthy
166
+ end
167
+
128
168
  describe "Validations", :live => true do
129
169
  include_context "stripe validator"
130
170
  let(:params) { stripe_helper.create_price_params(product: product_id) }
@@ -0,0 +1,68 @@
1
+ require "spec_helper"
2
+
3
+ shared_examples "PromotionCode API" do
4
+ let(:coupon) { stripe_helper.create_coupon }
5
+
6
+ it "creates a promotion code" do
7
+ promotion_code = Stripe::PromotionCode.create({id: "promo_123", coupon: coupon.id, code: "FREESTUFF"})
8
+
9
+ expect(promotion_code.id).to eq("promo_123")
10
+ expect(promotion_code.code).to eq("FREESTUFF")
11
+ expect(promotion_code.coupon).to eq(coupon.id)
12
+ end
13
+
14
+ it "creates a promotion code without specifying code" do
15
+ promotion_code = Stripe::PromotionCode.create({id: "promo_123", coupon: coupon.id})
16
+
17
+ expect(promotion_code.id).to eq("promo_123")
18
+ expect(promotion_code.code).to eq("TESTCODE")
19
+ expect(promotion_code.coupon).to eq(coupon.id)
20
+ end
21
+
22
+ it "cannot create a promotion code without a coupon" do
23
+ expect {
24
+ Stripe::PromotionCode.create
25
+ }.to raise_error { |e|
26
+ expect(e).to be_a(Stripe::InvalidRequestError)
27
+ expect(e.message).to eq("Missing required param: coupon")
28
+ }
29
+ end
30
+
31
+ it "requires minimum amount currency when minimum amount is provided" do
32
+ expect {
33
+ Stripe::PromotionCode.create(coupon: coupon, restrictions: {minimum_amount: 100})
34
+ }.to raise_error { |e|
35
+ expect(e).to be_a(Stripe::InvalidRequestError)
36
+ expect(e.message).to eq("You must pass minimum_amount_currency when passing minimum_amount")
37
+ }
38
+ end
39
+
40
+ it "updates a promotion code" do
41
+ promotion_code = Stripe::PromotionCode.create({coupon: coupon.id})
42
+ expect(promotion_code.active).to eq(true)
43
+
44
+ updated = Stripe::PromotionCode.update(promotion_code.id, active: false)
45
+
46
+ expect(updated.active).to eq(false)
47
+ end
48
+
49
+ it "retrieves a promotion code" do
50
+ original = Stripe::PromotionCode.create({coupon: coupon.id})
51
+
52
+ promotion_code = Stripe::PromotionCode.retrieve(original.id)
53
+
54
+ expect(promotion_code.id).to eq(original.id)
55
+ expect(promotion_code.code).to eq(original.code)
56
+ expect(promotion_code.coupon).to eq(original.coupon)
57
+ end
58
+
59
+ it "lists all promotion codes" do
60
+ Stripe::PromotionCode.create({coupon: coupon.id, code: "10PERCENT"})
61
+ Stripe::PromotionCode.create({coupon: coupon.id, code: "20PERCENT"})
62
+
63
+ all = Stripe::PromotionCode.list
64
+
65
+ expect(all.count).to eq(2)
66
+ expect(all.map(&:code)).to include("10PERCENT", "20PERCENT")
67
+ end
68
+ end
@@ -22,6 +22,19 @@ shared_examples 'Refund API' do
22
22
  expect(charge.amount_refunded).to eq(999)
23
23
  end
24
24
 
25
+ it "refunds a stripe payment intent" do
26
+ payment_intent = Stripe::PaymentIntent.create(
27
+ amount: 999,
28
+ currency: 'USD'
29
+ )
30
+
31
+ refund = Stripe::Refund.create(
32
+ payment_intent: payment_intent.id
33
+ )
34
+ expect(refund.amount).to eq(999)
35
+ end
36
+
37
+
25
38
  it "creates a stripe refund with a status" do
26
39
  charge = Stripe::Charge.create(
27
40
  amount: 999,
@@ -10,6 +10,14 @@ shared_examples 'SetupIntent API' do
10
10
  expect(setup_intent.status).to eq('requires_payment_method')
11
11
  end
12
12
 
13
+ it 'creates a stripe setup intent with payment method' do
14
+ setup_intent = Stripe::SetupIntent.create(payment_method: 'random')
15
+
16
+ expect(setup_intent.id).to match(/^test_si/)
17
+ expect(setup_intent.metadata.to_hash).to eq({})
18
+ expect(setup_intent.status).to eq('requires_action')
19
+ end
20
+
13
21
  describe "listing setup_intent" do
14
22
  before do
15
23
  3.times do
@@ -42,6 +50,15 @@ shared_examples 'SetupIntent API' do
42
50
  }
43
51
  end
44
52
 
53
+ it "expands payment_method" do
54
+ payment_method = Stripe::PaymentMethod.create(type: "card")
55
+ original = Stripe::SetupIntent.create(payment_method: payment_method.id)
56
+
57
+ setup_intent = Stripe::SetupIntent.retrieve({id: original.id, expand: ["payment_method"]})
58
+
59
+ expect(setup_intent.payment_method).to eq(payment_method)
60
+ end
61
+
45
62
  it "confirms a stripe setup_intent" do
46
63
  setup_intent = Stripe::SetupIntent.create()
47
64
  confirmed_setup_intent = setup_intent.confirm()
@@ -179,6 +179,7 @@ shared_examples 'Customer Subscriptions with plans' do
179
179
  expect(subscriptions.data).to be_a(Array)
180
180
  expect(subscriptions.data.count).to eq(1)
181
181
  expect(subscriptions.data.first.discount).not_to be_nil
182
+ expect(subscriptions.data.first.discount.id).not_to be_nil
182
183
  expect(subscriptions.data.first.discount).to be_a(Stripe::Discount)
183
184
  expect(subscriptions.data.first.discount.coupon.id).to eq(coupon.id)
184
185
  end
@@ -195,6 +196,28 @@ shared_examples 'Customer Subscriptions with plans' do
195
196
  }
196
197
  end
197
198
 
199
+ it "allows promotion code" do
200
+ customer = Stripe::Customer.create(source: gen_card_tk)
201
+ coupon = stripe_helper.create_coupon
202
+ promotion_code = Stripe::PromotionCode.create(coupon: coupon)
203
+
204
+ expect {
205
+ Stripe::Subscription.create(plan: plan.id, customer: customer.id, promotion_code: promotion_code.id)
206
+ }.not_to raise_error(Stripe::InvalidRequestError)
207
+ end
208
+
209
+ it "does not permit both coupon and promotion code" do
210
+ customer = Stripe::Customer.create(source: gen_card_tk)
211
+
212
+ expect {
213
+ Stripe::Subscription.create(plan: plan.id, customer: customer.id, coupon: "test", promotion_code: "test")
214
+ }.to raise_error { |e|
215
+ expect(e).to be_a Stripe::InvalidRequestError
216
+ expect(e.http_status).to eq(400)
217
+ expect(e.message).to eq("You may only specify one of these parameters: coupon, promotion_code")
218
+ }
219
+ end
220
+
198
221
  it "correctly sets quantity, application_fee_percent and tax_percent" do
199
222
  customer = Stripe::Customer.create(id: 'test_customer_sub', source: gen_card_tk)
200
223
 
@@ -290,6 +313,27 @@ shared_examples 'Customer Subscriptions with plans' do
290
313
  expect(customer.subscriptions.count).to eq(0)
291
314
  end
292
315
 
316
+ it "creates a subscription when subscription's payment_behavior is default_incomplete" do
317
+ plan = stripe_helper.create_plan(id: 'enterprise', product: product.id, amount: 499)
318
+ customer = Stripe::Customer.create(id: 'cardless')
319
+
320
+ sub = Stripe::Subscription.create({ plan: plan.id, customer: customer.id, payment_behavior: 'default_incomplete' })
321
+ customer = Stripe::Customer.retrieve('cardless')
322
+
323
+ expect(customer.subscriptions.count).to eq(1)
324
+ expect(customer.subscriptions.data.first.id).to eq(sub.id)
325
+ expect(customer.subscriptions.data.first.status).to eq('incomplete')
326
+ end
327
+
328
+ it "allows setting transfer_data" do
329
+ customer = Stripe::Customer.create(id: 'test_customer_sub', source: gen_card_tk)
330
+
331
+ sub = Stripe::Subscription.create({ customer: customer.id, plan: plan.id, transfer_data: {destination: "acct_0000000000000000", amount_percent: 50} })
332
+
333
+ expect(sub.transfer_data.destination).to eq("acct_0000000000000000")
334
+ expect(sub.transfer_data.amount_percent).to eq(50)
335
+ end
336
+
293
337
  it "throws an error when subscribing a customer with no card" do
294
338
  plan = stripe_helper.create_plan(id: 'enterprise', product: product.id, amount: 499)
295
339
  customer = Stripe::Customer.create(id: 'cardless')
@@ -338,7 +382,7 @@ shared_examples 'Customer Subscriptions with plans' do
338
382
  expect(sub.object).to eq('subscription')
339
383
  expect(sub.plan.to_hash).to eq(plan_with_trial.to_hash)
340
384
  expect(sub.trial_end - sub.trial_start).to eq(14 * 86400)
341
- expect(sub.billing_cycle_anchor).to be_nil
385
+ expect(sub.billing_cycle_anchor).to eq sub.trial_start
342
386
 
343
387
  customer = Stripe::Customer.retrieve(customer.id)
344
388
  subscriptions = Stripe::Subscription.list(customer: customer.id)
@@ -532,6 +576,45 @@ shared_examples 'Customer Subscriptions with plans' do
532
576
  expect(subscription.items.data[1].plan.id).to eq plan2.id
533
577
  end
534
578
 
579
+ it 'sets current_period_end based on price week interval', live: true do
580
+ price = stripe_helper.create_price(recurring: {interval: 'week'})
581
+
582
+ subscription = Stripe::Subscription.create(
583
+ customer: Stripe::Customer.create(source: gen_card_tk).id,
584
+ items: [
585
+ {price: price.id, quantity: 1}
586
+ ]
587
+ )
588
+
589
+ expect(subscription.current_period_end).to eq (Time.now + (7 * 60 * 60 * 24)).to_i
590
+ end
591
+
592
+ it 'sets current_period_end based on price month interval', live: true do
593
+ price = stripe_helper.create_price(recurring: {interval: 'month'})
594
+
595
+ subscription = Stripe::Subscription.create(
596
+ customer: Stripe::Customer.create(source: gen_card_tk).id,
597
+ items: [
598
+ {price: price.id, quantity: 1}
599
+ ]
600
+ )
601
+
602
+ expect(subscription.current_period_end).to eq (DateTime.now >> 1).to_time.to_i
603
+ end
604
+
605
+ it 'sets current_period_end based on price year interval', live: true do
606
+ price = stripe_helper.create_price(recurring: {interval: 'year'})
607
+
608
+ subscription = Stripe::Subscription.create(
609
+ customer: Stripe::Customer.create(source: gen_card_tk).id,
610
+ items: [
611
+ {price: price.id, quantity: 1}
612
+ ]
613
+ )
614
+
615
+ expect(subscription.current_period_end).to eq (DateTime.now >> 12).to_time.to_i
616
+ end
617
+
535
618
  it 'add a new subscription to bill via an invoice' do
536
619
  product = stripe_helper.create_product(id: 'invoice_billing')
537
620
  plan = stripe_helper.create_plan(id: 'silver', product: product.id,
@@ -633,6 +716,35 @@ shared_examples 'Customer Subscriptions with plans' do
633
716
  expect(subscription.default_tax_rates.first.id).to eq(tax_rate.id)
634
717
  end
635
718
  end
719
+
720
+ it 'expands latest_invoice.payment_intent' do
721
+ customer = Stripe::Customer.create(source: gen_card_tk)
722
+ subscription = Stripe::Subscription.create({
723
+ customer: customer.id,
724
+ plan: plan.id,
725
+ expand: ['latest_invoice.payment_intent']
726
+ })
727
+
728
+ expect(subscription.latest_invoice.payment_intent.status).to eq('succeeded')
729
+
730
+ subscription = Stripe::Subscription.create({
731
+ customer: customer.id,
732
+ plan: plan.id,
733
+ expand: ['latest_invoice.payment_intent'],
734
+ payment_behavior: 'default_incomplete'
735
+ })
736
+
737
+ expect(subscription.latest_invoice.payment_intent.status).to eq('requires_payment_method')
738
+
739
+ subscription = Stripe::Subscription.create({
740
+ customer: customer.id,
741
+ plan: plan.id,
742
+ expand: ['latest_invoice.payment_intent'],
743
+ trial_period_days: 14
744
+ })
745
+
746
+ expect(subscription.latest_invoice.payment_intent).to be_nil
747
+ end
636
748
  end
637
749
 
638
750
  context "updating a subscription" do
@@ -858,6 +970,23 @@ shared_examples 'Customer Subscriptions with plans' do
858
970
  expect(subscription.discount).to be_nil
859
971
  end
860
972
 
973
+ it "throws an error when promotion code has an amount restriction" do
974
+ coupon = stripe_helper.create_coupon
975
+ promotion_code = Stripe::PromotionCode.create(
976
+ coupon: coupon, restrictions: {minimum_amount: 100, minimum_amount_currency: "USD"}
977
+ )
978
+ customer = Stripe::Customer.create(source: gen_card_tk, plan: plan.id)
979
+ subscription = Stripe::Subscription.retrieve(customer.subscriptions.data.first.id)
980
+
981
+ subscription.promotion_code = promotion_code.id
982
+
983
+ expect { subscription.save }.to raise_error { |e|
984
+ expect(e).to be_a Stripe::InvalidRequestError
985
+ expect(e.http_status).to eq(400)
986
+ expect(e.message).to_not be_nil
987
+ }
988
+ end
989
+
861
990
  it "throws an error when plan does not exist" do
862
991
  customer = Stripe::Customer.create(id: 'cardless', plan: free_plan.id)
863
992
 
@@ -1030,6 +1159,18 @@ shared_examples 'Customer Subscriptions with plans' do
1030
1159
  expect(e.message).to eq("Invalid timestamp: must be an integer")
1031
1160
  }
1032
1161
  end
1162
+
1163
+ it "converts billing_cycle_anchor=now to a timestamp" do
1164
+ customer = Stripe::Customer.create(id: 'test_billing_anchor', plan: plan.id, source: gen_card_tk)
1165
+
1166
+ sub = Stripe::Subscription.retrieve(customer.subscriptions.data.first.id)
1167
+ sub.billing_cycle_anchor = 'now'
1168
+ sub.save
1169
+
1170
+ expect(sub.billing_cycle_anchor).to be_a(Integer)
1171
+ end
1172
+
1173
+
1033
1174
  end
1034
1175
 
1035
1176
  context "cancelling a subscription" do
@@ -1155,6 +1296,10 @@ shared_examples 'Customer Subscriptions with plans' do
1155
1296
  expect(subscription.items.data.first.plan.currency).to eq('usd')
1156
1297
  expect(subscription.items.data.first.quantity).to eq(2)
1157
1298
  end
1299
+
1300
+ it "has a start_date attribute" do
1301
+ expect(subscription).to respond_to(:start_date)
1302
+ end
1158
1303
  end
1159
1304
 
1160
1305
  context "retrieve multiple subscriptions" do
@@ -1182,6 +1327,50 @@ shared_examples 'Customer Subscriptions with plans' do
1182
1327
  expect(list.count).to eq(0)
1183
1328
  expect(list.data.length).to eq(0)
1184
1329
  end
1330
+
1331
+ it "does not include canceled subscriptions by default" do
1332
+ customer = Stripe::Customer.create(source: gen_card_tk)
1333
+ subscription = Stripe::Subscription.create({ plan: plan.id, customer: customer.id })
1334
+ subscription.delete
1335
+
1336
+ list = Stripe::Subscription.list({customer: customer.id})
1337
+
1338
+ expect(list.object).to eq("list")
1339
+ expect(list.data).to be_empty
1340
+ expect(list.data.length).to eq(0)
1341
+ end
1342
+
1343
+ it "filters out subscriptions based on their current_period", live: true do
1344
+ price = stripe_helper.create_price(recurring: { interval: 'month' })
1345
+ price2 = stripe_helper.create_price(recurring: { interval: 'year' })
1346
+
1347
+ subscription1 = Stripe::Subscription.create(
1348
+ customer: Stripe::Customer.create(source: gen_card_tk).id,
1349
+ items: [{ price: price.id, quantity: 1 }]
1350
+ )
1351
+ subscription2 = Stripe::Subscription.create(
1352
+ customer: Stripe::Customer.create(source: gen_card_tk).id,
1353
+ items: [{ price: price2.id, quantity: 1 }]
1354
+ )
1355
+
1356
+ list = Stripe::Subscription.list({ current_period_end: { gt: subscription1.current_period_end }})
1357
+ expect(list.data).to contain_exactly(subscription2)
1358
+
1359
+ list = Stripe::Subscription.list({ current_period_end: { gte: subscription1.current_period_end }})
1360
+ expect(list.data).to contain_exactly(subscription1, subscription2)
1361
+
1362
+ list = Stripe::Subscription.list({ current_period_end: { lt: subscription1.current_period_end }})
1363
+ expect(list.data).to be_empty
1364
+
1365
+ list = Stripe::Subscription.list({ current_period_end: { lte: subscription1.current_period_end }})
1366
+ expect(list.data).to contain_exactly(subscription1)
1367
+
1368
+ list = Stripe::Subscription.list({ current_period_start: subscription1.current_period_start })
1369
+ expect(list.data).to contain_exactly(subscription1, subscription2)
1370
+
1371
+ list = Stripe::Subscription.list({ current_period_end: subscription2.current_period_end })
1372
+ expect(list.data).to contain_exactly(subscription2)
1373
+ end
1185
1374
  end
1186
1375
 
1187
1376
  describe "metadata" do
@@ -1212,8 +1401,28 @@ shared_examples 'Customer Subscriptions with plans' do
1212
1401
  expect(customer.subscriptions.first.plan.id).to eq('Sample5')
1213
1402
  expect(customer.subscriptions.first.metadata['foo']).to eq('bar')
1214
1403
  end
1215
- end
1216
1404
 
1405
+ it "saves subscription item metadata" do
1406
+ stripe_helper.
1407
+ create_plan(
1408
+ :amount => 500,
1409
+ :interval => 'month',
1410
+ :product => product.id,
1411
+ :currency => 'usd',
1412
+ :id => 'Sample5'
1413
+ )
1414
+ customer = Stripe::Customer.create({
1415
+ email: 'johnny@appleseed.com',
1416
+ source: gen_card_tk
1417
+ })
1418
+
1419
+ subscription = Stripe::Subscription.create(
1420
+ customer: customer.id,
1421
+ items: [{plan: "Sample5", metadata: {foo: 'bar'}}],
1422
+ )
1423
+ expect(subscription.items.data[0].metadata.to_h).to eq(foo: 'bar')
1424
+ end
1425
+ end
1217
1426
  end
1218
1427
 
1219
1428
  shared_examples 'Customer Subscriptions with prices' do
@@ -1237,6 +1446,7 @@ shared_examples 'Customer Subscriptions with prices' do
1237
1446
 
1238
1447
  expect(subscription.object).to eq('subscription')
1239
1448
  expect(subscription.plan.to_hash).to eq(price.to_hash)
1449
+ expect(subscription.items.first.price.to_hash).to eq(price.to_hash)
1240
1450
  expect(subscription.metadata.foo).to eq("bar")
1241
1451
  expect(subscription.metadata.example).to eq("yes")
1242
1452
 
@@ -1252,6 +1462,7 @@ shared_examples 'Customer Subscriptions with prices' do
1252
1462
 
1253
1463
  expect(subscriptions.data.first.id).to eq(subscription.id)
1254
1464
  expect(subscriptions.data.first.plan.to_hash).to eq(price.to_hash)
1465
+ expect(subscriptions.data.first.items.first.price.to_hash).to eq(price.to_hash)
1255
1466
  expect(subscriptions.data.first.customer).to eq(customer.id)
1256
1467
  expect(subscriptions.data.first.metadata.foo).to eq( "bar" )
1257
1468
  expect(subscriptions.data.first.metadata.example).to eq( "yes" )
@@ -9,7 +9,7 @@ shared_examples 'Transfer API' do
9
9
  expect(transfer.id).to match /^test_tr/
10
10
  expect(transfer.amount).to eq(100)
11
11
  expect(transfer.amount_reversed).to eq(0)
12
- expect(transfer.balance_transaction).to eq('txn_2dyYXXP90MN26R')
12
+ expect(transfer.balance_transaction).to eq('test_txn_1')
13
13
  expect(transfer.created).to eq(1304114826)
14
14
  expect(transfer.currency).to eq('usd')
15
15
  expect(transfer.description).to eq('Transfer description')
@@ -30,6 +30,15 @@ shared_examples 'Transfer API' do
30
30
  expect(transfer.transfer_group).to eq("group_ch_164xRv2eZvKYlo2Clu1sIJWB")
31
31
  end
32
32
 
33
+ it "creates a balance transaction" do
34
+ destination = Stripe::Account.create(type: "custom", email: "#{SecureRandom.uuid}@example.com", id: "acct_12345", requested_capabilities: ['card_payments', 'platform_payments'])
35
+ transfer = Stripe::Transfer.create(amount: 100, currency: "usd", destination: destination.id)
36
+
37
+ bal_trans = Stripe::BalanceTransaction.retrieve(transfer.balance_transaction)
38
+ expect(bal_trans.amount).to eq(100)
39
+ expect(bal_trans.source).to eq(transfer.id)
40
+ end
41
+
33
42
  describe "listing transfers" do
34
43
  let(:destination) { Stripe::Account.create(type: "custom", email: "#{SecureRandom.uuid}@example.com", business_name: "MyCo") }
35
44