stripe-ruby-mock 2.5.8 → 4.0.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 (159) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rspec_tests.yml +38 -0
  3. data/.gitignore +1 -1
  4. data/.rspec +2 -1
  5. data/CHANGELOG.md +77 -0
  6. data/Gemfile +1 -5
  7. data/README.md +19 -11
  8. data/lib/stripe_mock/api/client.rb +2 -2
  9. data/lib/stripe_mock/api/errors.rb +34 -28
  10. data/lib/stripe_mock/api/instance.rb +1 -1
  11. data/lib/stripe_mock/api/webhooks.rb +68 -24
  12. data/lib/stripe_mock/client.rb +2 -1
  13. data/lib/stripe_mock/data/list.rb +42 -9
  14. data/lib/stripe_mock/data.rb +359 -21
  15. data/lib/stripe_mock/instance.rb +23 -5
  16. data/lib/stripe_mock/request_handlers/account_links.rb +15 -0
  17. data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
  18. data/lib/stripe_mock/request_handlers/balance_transactions.rb +2 -2
  19. data/lib/stripe_mock/request_handlers/charges.rb +31 -5
  20. data/lib/stripe_mock/request_handlers/checkout_session.rb +179 -0
  21. data/lib/stripe_mock/request_handlers/customers.rb +47 -19
  22. data/lib/stripe_mock/request_handlers/ephemeral_key.rb +1 -1
  23. data/lib/stripe_mock/request_handlers/events.rb +30 -3
  24. data/lib/stripe_mock/request_handlers/express_login_links.rb +15 -0
  25. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +6 -0
  26. data/lib/stripe_mock/request_handlers/helpers/search_helpers.rb +67 -0
  27. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +36 -12
  28. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +1 -1
  29. data/lib/stripe_mock/request_handlers/invoices.rb +26 -6
  30. data/lib/stripe_mock/request_handlers/payment_intents.rb +202 -0
  31. data/lib/stripe_mock/request_handlers/payment_methods.rb +124 -0
  32. data/lib/stripe_mock/request_handlers/plans.rb +1 -1
  33. data/lib/stripe_mock/request_handlers/prices.rb +71 -0
  34. data/lib/stripe_mock/request_handlers/products.rb +15 -5
  35. data/lib/stripe_mock/request_handlers/promotion_codes.rb +43 -0
  36. data/lib/stripe_mock/request_handlers/refunds.rb +13 -2
  37. data/lib/stripe_mock/request_handlers/setup_intents.rb +100 -0
  38. data/lib/stripe_mock/request_handlers/sources.rb +12 -6
  39. data/lib/stripe_mock/request_handlers/subscriptions.rb +146 -25
  40. data/lib/stripe_mock/request_handlers/tokens.rb +6 -4
  41. data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
  42. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +124 -9
  43. data/lib/stripe_mock/server.rb +2 -2
  44. data/lib/stripe_mock/test_strategies/base.rb +98 -12
  45. data/lib/stripe_mock/test_strategies/live.rb +23 -12
  46. data/lib/stripe_mock/test_strategies/mock.rb +6 -2
  47. data/lib/stripe_mock/version.rb +1 -1
  48. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  49. data/lib/stripe_mock/webhook_fixtures/balance.available.json +27 -15
  50. data/lib/stripe_mock/webhook_fixtures/charge.captured.json +143 -0
  51. data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +63 -16
  52. data/lib/stripe_mock/webhook_fixtures/charge.failed.json +101 -44
  53. data/lib/stripe_mock/webhook_fixtures/charge.refund.updated.json +35 -0
  54. data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +145 -50
  55. data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +114 -43
  56. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.json +79 -0
  57. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.payment_mode.json +53 -0
  58. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.setup_mode.json +45 -0
  59. data/lib/stripe_mock/webhook_fixtures/customer.created.json +37 -45
  60. data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +36 -32
  61. data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +31 -22
  62. data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -25
  63. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +135 -47
  64. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +134 -45
  65. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +135 -56
  66. data/lib/stripe_mock/webhook_fixtures/customer.updated.json +38 -46
  67. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +176 -49
  68. data/lib/stripe_mock/webhook_fixtures/invoice.finalized.json +171 -0
  69. data/lib/stripe_mock/webhook_fixtures/invoice.paid.json +171 -0
  70. data/lib/stripe_mock/webhook_fixtures/invoice.payment_action_required.json +171 -0
  71. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +149 -83
  72. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +149 -90
  73. data/lib/stripe_mock/webhook_fixtures/invoice.upcoming.json +70 -0
  74. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +178 -50
  75. data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +87 -13
  76. data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +88 -14
  77. data/lib/stripe_mock/webhook_fixtures/mandate.updated.json +34 -0
  78. data/lib/stripe_mock/webhook_fixtures/payment_intent.amount_capturable_updated.json +170 -0
  79. data/lib/stripe_mock/webhook_fixtures/payment_intent.canceled.json +73 -0
  80. data/lib/stripe_mock/webhook_fixtures/payment_intent.created.json +86 -0
  81. data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +225 -0
  82. data/lib/stripe_mock/webhook_fixtures/payment_intent.processing.json +162 -0
  83. data/lib/stripe_mock/webhook_fixtures/payment_intent.requires_action.json +191 -0
  84. data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +196 -0
  85. data/lib/stripe_mock/webhook_fixtures/payment_link.created.json +47 -0
  86. data/lib/stripe_mock/webhook_fixtures/payment_link.updated.json +50 -0
  87. data/lib/stripe_mock/webhook_fixtures/payment_method.attached.json +63 -0
  88. data/lib/stripe_mock/webhook_fixtures/payment_method.detached.json +62 -0
  89. data/lib/stripe_mock/webhook_fixtures/payout.created.json +40 -0
  90. data/lib/stripe_mock/webhook_fixtures/payout.paid.json +40 -0
  91. data/lib/stripe_mock/webhook_fixtures/payout.updated.json +46 -0
  92. data/lib/stripe_mock/webhook_fixtures/plan.created.json +30 -13
  93. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +30 -13
  94. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +34 -14
  95. data/lib/stripe_mock/webhook_fixtures/price.created.json +42 -0
  96. data/lib/stripe_mock/webhook_fixtures/price.deleted.json +42 -0
  97. data/lib/stripe_mock/webhook_fixtures/price.updated.json +48 -0
  98. data/lib/stripe_mock/webhook_fixtures/product.created.json +40 -0
  99. data/lib/stripe_mock/webhook_fixtures/product.deleted.json +40 -0
  100. data/lib/stripe_mock/webhook_fixtures/product.updated.json +47 -0
  101. data/lib/stripe_mock/webhook_fixtures/quote.accepted.json +92 -0
  102. data/lib/stripe_mock/webhook_fixtures/quote.canceled.json +92 -0
  103. data/lib/stripe_mock/webhook_fixtures/quote.created.json +92 -0
  104. data/lib/stripe_mock/webhook_fixtures/quote.finalized.json +92 -0
  105. data/lib/stripe_mock/webhook_fixtures/setup_intent.canceled.json +46 -0
  106. data/lib/stripe_mock/webhook_fixtures/setup_intent.created.json +51 -0
  107. data/lib/stripe_mock/webhook_fixtures/setup_intent.setup_failed.json +100 -0
  108. data/lib/stripe_mock/webhook_fixtures/setup_intent.succeeded.json +46 -0
  109. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.canceled.json +119 -0
  110. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.created.json +114 -0
  111. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.released.json +111 -0
  112. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.updated.json +125 -0
  113. data/lib/stripe_mock/webhook_fixtures/tax_rate.created.json +32 -0
  114. data/lib/stripe_mock/webhook_fixtures/tax_rate.updated.json +37 -0
  115. data/lib/stripe_mock.rb +11 -0
  116. data/spec/instance_spec.rb +13 -13
  117. data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
  118. data/spec/list_spec.rb +38 -0
  119. data/spec/readme_spec.rb +1 -1
  120. data/spec/server_spec.rb +6 -3
  121. data/spec/shared_stripe_examples/account_examples.rb +10 -2
  122. data/spec/shared_stripe_examples/account_link_examples.rb +16 -0
  123. data/spec/shared_stripe_examples/balance_examples.rb +6 -0
  124. data/spec/shared_stripe_examples/balance_transaction_examples.rb +3 -3
  125. data/spec/shared_stripe_examples/bank_examples.rb +3 -3
  126. data/spec/shared_stripe_examples/bank_token_examples.rb +5 -7
  127. data/spec/shared_stripe_examples/card_examples.rb +4 -4
  128. data/spec/shared_stripe_examples/card_token_examples.rb +17 -21
  129. data/spec/shared_stripe_examples/charge_examples.rb +106 -22
  130. data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
  131. data/spec/shared_stripe_examples/coupon_examples.rb +1 -1
  132. data/spec/shared_stripe_examples/customer_examples.rb +149 -53
  133. data/spec/shared_stripe_examples/dispute_examples.rb +2 -2
  134. data/spec/shared_stripe_examples/error_mock_examples.rb +8 -7
  135. data/spec/shared_stripe_examples/express_login_link_examples.rb +12 -0
  136. data/spec/shared_stripe_examples/external_account_examples.rb +3 -3
  137. data/spec/shared_stripe_examples/invoice_examples.rb +148 -40
  138. data/spec/shared_stripe_examples/invoice_item_examples.rb +1 -1
  139. data/spec/shared_stripe_examples/payment_intent_examples.rb +283 -0
  140. data/spec/shared_stripe_examples/payment_method_examples.rb +454 -0
  141. data/spec/shared_stripe_examples/payout_examples.rb +2 -2
  142. data/spec/shared_stripe_examples/plan_examples.rb +135 -92
  143. data/spec/shared_stripe_examples/price_examples.rb +292 -0
  144. data/spec/shared_stripe_examples/product_examples.rb +215 -0
  145. data/spec/shared_stripe_examples/promotion_code_examples.rb +68 -0
  146. data/spec/shared_stripe_examples/refund_examples.rb +38 -21
  147. data/spec/shared_stripe_examples/setup_intent_examples.rb +85 -0
  148. data/spec/shared_stripe_examples/subscription_examples.rb +706 -324
  149. data/spec/shared_stripe_examples/subscription_items_examples.rb +3 -2
  150. data/spec/shared_stripe_examples/transfer_examples.rb +16 -7
  151. data/spec/shared_stripe_examples/webhook_event_examples.rb +62 -16
  152. data/spec/spec_helper.rb +8 -5
  153. data/spec/stripe_mock_spec.rb +4 -4
  154. data/spec/support/shared_contexts/stripe_validator_spec.rb +8 -0
  155. data/spec/support/stripe_examples.rb +11 -1
  156. data/stripe-ruby-mock.gemspec +9 -5
  157. metadata +115 -47
  158. data/.travis.yml +0 -28
  159. data/spec/shared_stripe_examples/product_example.rb +0 -65
@@ -278,20 +278,6 @@ shared_examples 'Charge API' do
278
278
  }.not_to raise_error
279
279
  end
280
280
 
281
- it "marks a charge as safe" do
282
- original = Stripe::Charge.create({
283
- amount: 777,
284
- currency: 'USD',
285
- source: stripe_helper.generate_card_token
286
- })
287
- charge = Stripe::Charge.retrieve(original.id)
288
-
289
- charge.mark_as_safe
290
-
291
- updated = Stripe::Charge.retrieve(original.id)
292
- expect(updated.fraud_details[:user_report]).to eq "safe"
293
- end
294
-
295
281
  it "does not lose data when updating a charge" do
296
282
  original = Stripe::Charge.create({
297
283
  amount: 777,
@@ -357,28 +343,29 @@ shared_examples 'Charge API' do
357
343
  end
358
344
 
359
345
  it "stores charges for a customer in memory" do
360
- expect(@customer.charges.data.map(&:id)).to eq([@charge.id])
346
+ charges = Stripe::Charge.list(customer: @customer.id)
347
+ expect(charges.map(&:id)).to eq([@charge.id])
361
348
  end
362
349
 
363
350
  it "stores all charges in memory" do
364
- expect(Stripe::Charge.all.data.map(&:id).reverse).to eq([@charge.id, @charge2.id])
351
+ expect(Stripe::Charge.list.data.map(&:id).reverse).to eq([@charge.id, @charge2.id])
365
352
  end
366
353
 
367
354
  it "defaults count to 10 charges" do
368
355
  11.times { Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token) }
369
356
 
370
- expect(Stripe::Charge.all.data.count).to eq(10)
357
+ expect(Stripe::Charge.list.data.count).to eq(10)
371
358
  end
372
359
 
373
360
  it "is marked as having more when more objects exist" do
374
361
  11.times { Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token) }
375
362
 
376
- expect(Stripe::Charge.all.has_more).to eq(true)
363
+ expect(Stripe::Charge.list.has_more).to eq(true)
377
364
  end
378
365
 
379
366
  context "when passing limit" do
380
367
  it "gets that many charges" do
381
- expect(Stripe::Charge.all(limit: 1).count).to eq(1)
368
+ expect(Stripe::Charge.list(limit: 1).count).to eq(1)
382
369
  end
383
370
  end
384
371
  end
@@ -398,13 +385,13 @@ shared_examples 'Charge API' do
398
385
  Stripe::Charge.create(customer: cus.id, amount: 100, currency: "usd")
399
386
  end
400
387
 
401
- all = Stripe::Charge.all
388
+ all_charges = Stripe::Charge.list
402
389
  default_limit = 10
403
- half = Stripe::Charge.all(starting_after: all.data.at(1).id)
390
+ half = Stripe::Charge.list(starting_after: all_charges.data.at(1).id)
404
391
 
405
392
  expect(half).to be_a(Stripe::ListObject)
406
393
  expect(half.data.count).to eq(default_limit)
407
- expect(half.data.first.id).to eq(all.data.at(2).id)
394
+ expect(half.data.first.id).to eq(all_charges.data.at(2).id)
408
395
  end
409
396
 
410
397
 
@@ -507,4 +494,101 @@ shared_examples 'Charge API' do
507
494
  end
508
495
  end
509
496
 
497
+ context "search" do
498
+ # the Search API requires about a minute between writes and reads, so add sleeps accordingly when running live
499
+ it "searches charges for exact matches", :aggregate_failures do
500
+ response = Stripe::Charge.search({query: 'amount:100'}, stripe_version: '2020-08-27')
501
+ expect(response.data.size).to eq(0)
502
+
503
+ customer = Stripe::Customer.create(email: 'johnny@appleseed.com')
504
+ one = Stripe::Charge.create(
505
+ customer: customer.id,
506
+ amount: 100,
507
+ currency: "usd",
508
+ payment_method_details: {
509
+ card: StripeMock::Data.mock_charge[:payment_method_details][:card].merge(
510
+ brand: "mastercard",
511
+ exp_month: 1,
512
+ exp_year: 2111,
513
+ fingerprint: "un",
514
+ last4: "1111",
515
+ ),
516
+ },
517
+ status: "succeeded",
518
+ metadata: {key: 'uno'},
519
+ )
520
+ two = Stripe::Charge.create(
521
+ customer: customer.id,
522
+ amount: 200,
523
+ currency: "gbp",
524
+ payment_method_details: {
525
+ card: StripeMock::Data.mock_charge[:payment_method_details][:card].merge(
526
+ brand: "visa",
527
+ exp_month: 2,
528
+ exp_year: 2222,
529
+ fingerprint: "deux",
530
+ last4: "2222",
531
+ ),
532
+ },
533
+ status: "pending",
534
+ metadata: {key: 'dos'},
535
+ )
536
+
537
+ response = Stripe::Charge.search({query: 'amount:100'}, stripe_version: '2020-08-27')
538
+ expect(response.data.map(&:id)).to match_array([one.id])
539
+
540
+ response = Stripe::Charge.search({query: 'currency:"gbp"'}, stripe_version: '2020-08-27')
541
+ expect(response.data.map(&:id)).to match_array([two.id])
542
+
543
+ response = Stripe::Charge.search({query: %(customer:"#{customer.id}")}, stripe_version: '2020-08-27')
544
+ expect(response.data.map(&:id)).to match_array([one.id, two.id])
545
+
546
+ response = Stripe::Charge.search({query: 'payment_method_details.card.brand:mastercard'}, stripe_version: '2020-08-27')
547
+ expect(response.data.map(&:id)).to match_array([one.id])
548
+
549
+ response = Stripe::Charge.search({query: 'payment_method_details.card.exp_month:2'}, stripe_version: '2020-08-27')
550
+ expect(response.data.map(&:id)).to match_array([two.id])
551
+
552
+ response = Stripe::Charge.search({query: 'payment_method_details.card.exp_year:2111'}, stripe_version: '2020-08-27')
553
+ expect(response.data.map(&:id)).to match_array([one.id])
554
+
555
+ response = Stripe::Charge.search({query: 'payment_method_details.card.fingerprint:un'}, stripe_version: '2020-08-27')
556
+ expect(response.data.map(&:id)).to match_array([one.id])
557
+
558
+ response = Stripe::Charge.search({query: 'payment_method_details.card.last4:2222'}, stripe_version: '2020-08-27')
559
+ expect(response.data.map(&:id)).to match_array([two.id])
560
+
561
+ response = Stripe::Charge.search({query: 'status:"succeeded"'}, stripe_version: '2020-08-27')
562
+ expect(response.data.map(&:id)).to match_array([one.id])
563
+
564
+ response = Stripe::Charge.search({query: 'metadata["key"]:"uno"'}, stripe_version: '2020-08-27')
565
+ expect(response.data.map(&:id)).to match_array([one.id])
566
+ end
567
+
568
+ it "respects limit", :aggregate_failures do
569
+ customer = Stripe::Customer.create(email: 'johnny@appleseed.com')
570
+ 11.times do
571
+ Stripe::Charge.create(customer: customer.id, amount: 100, currency: "usd")
572
+ end
573
+
574
+ response = Stripe::Charge.search({query: %(customer:"#{customer.id}")}, stripe_version: '2020-08-27')
575
+ expect(response.data.size).to eq(10)
576
+ response = Stripe::Charge.search({query: %(customer:"#{customer.id}"), limit: 1}, stripe_version: '2020-08-27')
577
+ expect(response.data.size).to eq(1)
578
+ end
579
+
580
+ it "reports search errors", :aggregate_failures do
581
+ expect {
582
+ Stripe::Charge.search({limit: 1}, stripe_version: '2020-08-27')
583
+ }.to raise_error(Stripe::InvalidRequestError, /Missing required param: query./)
584
+
585
+ expect {
586
+ Stripe::Charge.search({query: 'asdf'}, stripe_version: '2020-08-27')
587
+ }.to raise_error(Stripe::InvalidRequestError, /We were unable to parse your search query./)
588
+
589
+ expect {
590
+ Stripe::Charge.search({query: 'foo:"bar"'}, stripe_version: '2020-08-27')
591
+ }.to raise_error(Stripe::InvalidRequestError, /Field `foo` is an unsupported search field for resource `charges`./)
592
+ end
593
+ end
510
594
  end
@@ -0,0 +1,99 @@
1
+ require "spec_helper"
2
+
3
+ shared_examples "Checkout Session API" do
4
+ it "creates PaymentIntent with payment mode" do
5
+ line_items = [{
6
+ name: "T-shirt",
7
+ quantity: 2,
8
+ amount: 500,
9
+ currency: "usd",
10
+ }]
11
+ session = Stripe::Checkout::Session.create(
12
+ payment_method_types: ["card"],
13
+ line_items: line_items,
14
+ cancel_url: "https://example.com/cancel",
15
+ success_url: "https://example.com/success"
16
+ )
17
+
18
+ expect(session.payment_intent).to_not be_empty
19
+ payment_intent = Stripe::PaymentIntent.retrieve(session.payment_intent)
20
+ expect(payment_intent.amount).to eq(1000)
21
+ expect(payment_intent.currency).to eq("usd")
22
+ expect(payment_intent.customer).to eq(session.customer)
23
+ end
24
+
25
+ context "when creating a payment" do
26
+ it "requires line_items" do
27
+ expect do
28
+ session = Stripe::Checkout::Session.create(
29
+ customer: "customer_id",
30
+ success_url: "localhost/nada",
31
+ cancel_url: "localhost/nada",
32
+ payment_method_types: ["card"],
33
+ )
34
+ end.to raise_error(Stripe::InvalidRequestError, /line_items/i)
35
+
36
+ end
37
+ end
38
+
39
+ it "creates SetupIntent with setup mode" do
40
+ session = Stripe::Checkout::Session.create(
41
+ mode: "setup",
42
+ payment_method_types: ["card"],
43
+ cancel_url: "https://example.com/cancel",
44
+ success_url: "https://example.com/success"
45
+ )
46
+
47
+ expect(session.setup_intent).to_not be_empty
48
+ setup_intent = Stripe::SetupIntent.retrieve(session.setup_intent)
49
+ expect(setup_intent.payment_method_types).to eq(["card"])
50
+ end
51
+
52
+ context "when creating a subscription" do
53
+ it "requires line_items" do
54
+ expect do
55
+ session = Stripe::Checkout::Session.create(
56
+ customer: "customer_id",
57
+ success_url: "localhost/nada",
58
+ cancel_url: "localhost/nada",
59
+ payment_method_types: ["card"],
60
+ mode: "subscription",
61
+ )
62
+ end.to raise_error(Stripe::InvalidRequestError, /line_items/i)
63
+
64
+ end
65
+ end
66
+
67
+ context "retrieve a checkout session" do
68
+ let(:checkout_session1) { stripe_helper.create_checkout_session }
69
+
70
+ it "can be retrieved by id" do
71
+ checkout_session1
72
+
73
+ checkout_session = Stripe::Checkout::Session.retrieve(checkout_session1.id)
74
+
75
+ expect(checkout_session.id).to eq(checkout_session1.id)
76
+ end
77
+
78
+ it "cannot retrieve a checkout session that doesn't exist" do
79
+ expect { Stripe::Checkout::Session.retrieve("nope") }.to raise_error { |e|
80
+ expect(e).to be_a Stripe::InvalidRequestError
81
+ expect(e.param).to eq("checkout_session")
82
+ expect(e.http_status).to eq(404)
83
+ }
84
+ end
85
+
86
+ it "can expand setup_intent" do
87
+ initial_session = Stripe::Checkout::Session.create(
88
+ mode: "setup",
89
+ cancel_url: "https://example.com",
90
+ success_url: "https://example.com",
91
+ payment_method_types: ["card"]
92
+ )
93
+
94
+ checkout_session = Stripe::Checkout::Session.retrieve(id: initial_session.id, expand: ["setup_intent"])
95
+
96
+ expect(checkout_session.setup_intent).to be_a_kind_of(Stripe::SetupIntent)
97
+ end
98
+ end
99
+ end
@@ -53,7 +53,7 @@ shared_examples 'Coupon API' do
53
53
  coupon1
54
54
  coupon2
55
55
 
56
- all = Stripe::Coupon.all
56
+ all = Stripe::Coupon.list
57
57
 
58
58
  expect(all.count).to eq(2)
59
59
  expect(all.map &:id).to include('10BUCKS', '11BUCKS')
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  shared_examples 'Customer API' do
4
+ let(:product_params) { {id: "prod_CCC", name: "My Product", type: "service"} }
5
+ let(:product) { stripe_helper.create_product(product_params) }
4
6
 
5
7
  def gen_card_tk
6
8
  stripe_helper.generate_card_token
@@ -15,6 +17,7 @@ shared_examples 'Customer API' do
15
17
  expect(customer.id).to match(/^test_cus/)
16
18
  expect(customer.email).to eq('johnny@appleseed.com')
17
19
  expect(customer.description).to eq('a description')
20
+ expect(customer.preferred_locales).to eq([])
18
21
 
19
22
  expect(customer.sources.count).to eq(1)
20
23
  expect(customer.sources.data.length).to eq(1)
@@ -24,6 +27,17 @@ shared_examples 'Customer API' do
24
27
  expect { customer.source }.to raise_error
25
28
  end
26
29
 
30
+ it "creates a stripe customer with a default payment method" do
31
+ customer = Stripe::Customer.create({
32
+ email: 'johnny@appleseed.com',
33
+ invoice_settings: {
34
+ default_payment_method: "pm_1ExEuFL2DI6wht39WNJgbybl"
35
+ },
36
+ description: "a description"
37
+ })
38
+ expect(customer.invoice_settings.default_payment_method).to eq("pm_1ExEuFL2DI6wht39WNJgbybl")
39
+ end
40
+
27
41
  it "creates a stripe customer with multiple cards and updates the default card" do
28
42
  card_a = gen_card_tk
29
43
  card_b = gen_card_tk
@@ -88,7 +102,7 @@ shared_examples 'Customer API' do
88
102
  end
89
103
 
90
104
  it 'creates a customer with a plan' do
91
- plan = stripe_helper.create_plan(id: 'silver')
105
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id)
92
106
  customer = Stripe::Customer.create(id: 'test_cus_plan', source: gen_card_tk, :plan => 'silver')
93
107
 
94
108
  customer = Stripe::Customer.retrieve('test_cus_plan')
@@ -100,24 +114,29 @@ shared_examples 'Customer API' do
100
114
  expect(customer.subscriptions.first.customer).to eq(customer.id)
101
115
  end
102
116
 
103
- it "creates a customer with a plan (string/symbol agnostic)" do
104
- plan = stripe_helper.create_plan(id: 'string_id')
105
- customer = Stripe::Customer.create(id: 'test_cus_plan', source: gen_card_tk, :plan => :string_id)
106
-
107
- customer = Stripe::Customer.retrieve('test_cus_plan')
108
- expect(customer.subscriptions.first.plan.id).to eq('string_id')
117
+ it 'creates a customer with a plan (string/symbol agnostic)' do
118
+ stripe_helper.create_plan(id: 'silver', product: product.id)
109
119
 
110
- plan = stripe_helper.create_plan(:id => :sym_id)
111
- customer = Stripe::Customer.create(id: 'test_cus_plan', source: gen_card_tk, :plan => 'sym_id')
120
+ Stripe::Customer.create(id: 'cust_SLV1', source: gen_card_tk, :plan => 'silver')
121
+ customer = Stripe::Customer.retrieve('cust_SLV1')
122
+ expect(customer.subscriptions.count).to eq(1)
123
+ expect(customer.subscriptions.data.length).to eq(1)
124
+ expect(customer.subscriptions).to_not be_nil
125
+ expect(customer.subscriptions.first.plan.id).to eq('silver')
126
+ expect(customer.subscriptions.first.customer).to eq(customer.id)
112
127
 
113
- customer = Stripe::Customer.retrieve('test_cus_plan')
114
- expect(customer.subscriptions.first.plan.id).to eq('sym_id')
128
+ Stripe::Customer.create(id: 'cust_SLV2', source: gen_card_tk, :plan => :silver)
129
+ customer = Stripe::Customer.retrieve('cust_SLV2')
130
+ expect(customer.subscriptions.count).to eq(1)
131
+ expect(customer.subscriptions.data.length).to eq(1)
132
+ expect(customer.subscriptions).to_not be_nil
133
+ expect(customer.subscriptions.first.plan.id).to eq('silver')
134
+ expect(customer.subscriptions.first.customer).to eq(customer.id)
115
135
  end
116
136
 
117
137
  context "create customer" do
118
-
119
138
  it "with a trial when trial_end is set" do
120
- plan = stripe_helper.create_plan(id: 'no_trial', amount: 999)
139
+ plan = stripe_helper.create_plan(id: 'no_trial', product: product.id, amount: 999)
121
140
  trial_end = Time.now.utc.to_i + 3600
122
141
  customer = Stripe::Customer.create(id: 'test_cus_trial_end', source: gen_card_tk, plan: 'no_trial', trial_end: trial_end)
123
142
 
@@ -133,7 +152,7 @@ shared_examples 'Customer API' do
133
152
  end
134
153
 
135
154
  it 'overrides trial period length when trial_end is set' do
136
- plan = stripe_helper.create_plan(id: 'silver', amount: 999, trial_period_days: 14)
155
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id, amount: 999, trial_period_days: 14)
137
156
  trial_end = Time.now.utc.to_i + 3600
138
157
  customer = Stripe::Customer.create(id: 'test_cus_trial_end', source: gen_card_tk, plan: 'silver', trial_end: trial_end)
139
158
 
@@ -148,7 +167,7 @@ shared_examples 'Customer API' do
148
167
  end
149
168
 
150
169
  it 'creates a customer when trial_end is set and no source', live: true do
151
- plan = stripe_helper.create_plan(id: 'silver', amount: 999)
170
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id, amount: 999)
152
171
  trial_end = Time.now.utc.to_i + 3600
153
172
  customer = Stripe::Customer.create(plan: 'silver', trial_end: trial_end)
154
173
  expect(customer.subscriptions.count).to eq(1)
@@ -161,7 +180,7 @@ shared_examples 'Customer API' do
161
180
  end
162
181
 
163
182
  it "returns no trial when trial_end is set to 'now'" do
164
- plan = stripe_helper.create_plan(id: 'silver', amount: 999, trial_period_days: 14)
183
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id, amount: 999, trial_period_days: 14)
165
184
  customer = Stripe::Customer.create(id: 'test_cus_trial_end', source: gen_card_tk, plan: 'silver', trial_end: "now")
166
185
 
167
186
  customer = Stripe::Customer.retrieve('test_cus_trial_end')
@@ -175,8 +194,8 @@ shared_examples 'Customer API' do
175
194
  expect(customer.subscriptions.first.trial_end).to be_nil
176
195
  end
177
196
 
178
- it "returns an error if trial_end is set to a past time" do
179
- plan = stripe_helper.create_plan(id: 'silver', amount: 999)
197
+ it 'returns an error if trial_end is set to a past time' do
198
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id, amount: 999)
180
199
  expect {
181
200
  Stripe::Customer.create(id: 'test_cus_trial_end', source: gen_card_tk, plan: 'silver', trial_end: Time.now.utc.to_i - 3600)
182
201
  }.to raise_error {|e|
@@ -185,7 +204,7 @@ shared_examples 'Customer API' do
185
204
  }
186
205
  end
187
206
 
188
- it "returns an error if trial_end is set without a plan" do
207
+ it 'returns an error if trial_end is set without a plan' do
189
208
  expect {
190
209
  Stripe::Customer.create(id: 'test_cus_trial_end', source: gen_card_tk, trial_end: "now")
191
210
  }.to raise_error {|e|
@@ -198,7 +217,7 @@ shared_examples 'Customer API' do
198
217
 
199
218
  it 'cannot create a customer with a plan that does not exist' do
200
219
  expect {
201
- customer = Stripe::Customer.create(id: 'test_cus_no_plan', source: gen_card_tk, :plan => 'non-existant')
220
+ Stripe::Customer.create(id: 'test_cus_no_plan', source: gen_card_tk, :plan => 'non-existant')
202
221
  }.to raise_error {|e|
203
222
  expect(e).to be_a(Stripe::InvalidRequestError)
204
223
  expect(e.message).to eq('No such plan: non-existant')
@@ -206,9 +225,9 @@ shared_examples 'Customer API' do
206
225
  end
207
226
 
208
227
  it 'cannot create a customer with an existing plan, but no card token' do
209
- plan = stripe_helper.create_plan(id: 'p')
228
+ plan = stripe_helper.create_plan(id: 'p', product: product.id)
210
229
  expect {
211
- customer = Stripe::Customer.create(id: 'test_cus_no_plan', :plan => 'p')
230
+ Stripe::Customer.create(id: 'test_cus_no_plan', :plan => 'p')
212
231
  }.to raise_error {|e|
213
232
  expect(e).to be_a(Stripe::InvalidRequestError)
214
233
  expect(e.message).to eq('You must supply a valid card')
@@ -216,10 +235,9 @@ shared_examples 'Customer API' do
216
235
  end
217
236
 
218
237
  it 'creates a customer with a coupon discount' do
219
- coupon = Stripe::Coupon.create(id: "10PERCENT", duration: 'once')
238
+ coupon = Stripe::Coupon.create(id: '10PERCENT', duration: 'once')
220
239
 
221
- customer =
222
- Stripe::Customer.create(id: 'test_cus_coupon', coupon: '10PERCENT')
240
+ Stripe::Customer.create(id: 'test_cus_coupon', coupon: '10PERCENT')
223
241
 
224
242
  customer = Stripe::Customer.retrieve('test_cus_coupon')
225
243
  expect(customer.discount).to_not be_nil
@@ -231,40 +249,59 @@ shared_examples 'Customer API' do
231
249
  describe 'repeating coupon with duration limit', live: true do
232
250
  let!(:coupon) { stripe_helper.create_coupon(id: '10OFF', amount_off: 1000, currency: 'usd', duration: 'repeating', duration_in_months: 12) }
233
251
  let!(:customer) { Stripe::Customer.create(coupon: coupon.id) }
252
+
234
253
  it 'creates the discount with the end date', live: true do
235
254
  discount = Stripe::Customer.retrieve(customer.id).discount
236
255
  expect(discount).to_not be_nil
237
256
  expect(discount.coupon).to_not be_nil
238
- expect(discount.end).to be_within(1).of (Time.now.to_datetime >> 12).to_time.to_i
257
+ expect(discount.end).to be_within(10).of (DateTime.now >> 12).to_time.to_i
239
258
  end
259
+
240
260
  after { Stripe::Coupon.retrieve(coupon.id).delete }
241
261
  after { Stripe::Customer.retrieve(customer.id).delete }
242
262
  end
243
263
 
244
264
  it 'cannot create a customer with a coupon that does not exist' do
245
265
  expect{
246
- customer = Stripe::Customer.create(id: 'test_cus_no_coupon', coupon: '5OFF')
266
+ Stripe::Customer.create(id: 'test_cus_no_coupon', coupon: '5OFF')
247
267
  }.to raise_error {|e|
248
268
  expect(e).to be_a(Stripe::InvalidRequestError)
249
269
  expect(e.message).to eq('No such coupon: 5OFF')
250
270
  }
251
271
  end
252
272
 
273
+ context 'with coupon on customer' do
274
+ before do
275
+ Stripe::Coupon.create(id: '10PERCENT', duration: 'once')
276
+ Stripe::Customer.create(id: 'test_cus_coupon', coupon: '10PERCENT')
277
+ end
278
+
279
+ it 'remove the coupon from customer' do
280
+ customer = Stripe::Customer.retrieve('test_cus_coupon')
281
+ expect(customer.discount).to_not be_nil
282
+ expect(customer.discount.coupon).to_not be_nil
283
+ expect(customer.discount.customer).to eq customer.id
284
+ expect(customer.discount.start).to be_within(1).of Time.now.to_i
285
+
286
+ Stripe::Customer.update('test_cus_coupon', coupon: '')
287
+ customer = Stripe::Customer.retrieve('test_cus_coupon')
288
+ expect(customer.discount).to be_nil
289
+ end
290
+ end
291
+
253
292
  it "stores a created stripe customer in memory" do
254
- customer = Stripe::Customer.create({
255
- email: 'johnny@appleseed.com',
256
- source: gen_card_tk
257
- })
258
- customer2 = Stripe::Customer.create({
259
- email: 'bob@bobbers.com',
260
- source: gen_card_tk
261
- })
293
+ customer = Stripe::Customer.create(email: 'johnny@appleseed.com')
294
+ customer2 = Stripe::Customer.create(email: 'bob@bobbers.com')
262
295
  data = test_data_source(:customers)
263
- expect(data[customer.id]).to_not be_nil
264
- expect(data[customer.id][:email]).to eq('johnny@appleseed.com')
296
+ list = data[data.keys.first]
265
297
 
266
- expect(data[customer2.id]).to_not be_nil
267
- expect(data[customer2.id][:email]).to eq('bob@bobbers.com')
298
+ customer_hash = list[customer.id.to_sym] || list[customer.id]
299
+ expect(customer_hash).to_not be_nil
300
+ expect(customer_hash[:email]).to eq('johnny@appleseed.com')
301
+
302
+ customer2_hash = list[customer2.id.to_sym] || list[customer2.id]
303
+ expect(customer2_hash).to_not be_nil
304
+ expect(customer2_hash[:email]).to eq('bob@bobbers.com')
268
305
  end
269
306
 
270
307
  it "retrieves a stripe customer" do
@@ -307,9 +344,65 @@ shared_examples 'Customer API' do
307
344
  Stripe::Customer.create({ email: 'one@one.com' })
308
345
  Stripe::Customer.create({ email: 'two@two.com' })
309
346
 
310
- all = Stripe::Customer.all
347
+ all = Stripe::Customer.list
311
348
  expect(all.count).to eq(2)
312
- expect(all.map &:email).to include('one@one.com', 'two@two.com')
349
+ expect(all.data.map &:email).to include('one@one.com', 'two@two.com')
350
+ end
351
+
352
+ context "search" do
353
+ # the Search API requires about a minute between writes and reads, so add sleeps accordingly when running live
354
+ it "searches customers for exact matches", :aggregate_failures do
355
+ response = Stripe::Customer.search({query: 'email:"one@one.com"'}, stripe_version: '2020-08-27')
356
+ expect(response.data.size).to eq(0)
357
+
358
+ one = Stripe::Customer.create(email: 'one@one.com', name: 'one', phone: '1111111111', metadata: {key: 'uno'})
359
+ two = Stripe::Customer.create(email: 'two@two.com', name: 'two', phone: '2222222222', metadata: {key: 'dos'})
360
+
361
+ response = Stripe::Customer.search({query: 'email:"one@one.com"'}, stripe_version: '2020-08-27')
362
+ expect(response.data.map(&:id)).to match_array([one.id])
363
+
364
+ response = Stripe::Customer.search({query: 'name:"two"'}, stripe_version: '2020-08-27')
365
+ expect(response.data.map(&:id)).to match_array([two.id])
366
+
367
+ response = Stripe::Customer.search({query: 'phone:"2222222222"'}, stripe_version: '2020-08-27')
368
+ expect(response.data.map(&:id)).to match_array([two.id])
369
+
370
+ response = Stripe::Customer.search({query: 'metadata["key"]:"uno"'}, stripe_version: '2020-08-27')
371
+ expect(response.data.map(&:id)).to match_array([one.id])
372
+ end
373
+
374
+ it "respects limit", :aggregate_failures do
375
+ one = Stripe::Customer.create(email: 'one@one.com', name: 'one')
376
+ two = Stripe::Customer.create(email: 'two@two.com', name: 'one')
377
+ three = Stripe::Customer.create(email: 'three@three.com', name: 'one')
378
+ four = Stripe::Customer.create(email: 'four@four.com', name: 'one')
379
+ five = Stripe::Customer.create(email: 'five@five.com', name: 'one')
380
+ six = Stripe::Customer.create(email: 'six@six.com', name: 'one')
381
+ seven = Stripe::Customer.create(email: 'seven@seven.com', name: 'one')
382
+ eight = Stripe::Customer.create(email: 'eight@eight.com', name: 'one')
383
+ nine = Stripe::Customer.create(email: 'nine@nine.com', name: 'one')
384
+ ten = Stripe::Customer.create(email: 'ten@ten.com', name: 'one')
385
+ eleven = Stripe::Customer.create(email: 'eleven@eleven.com', name: 'one')
386
+
387
+ response = Stripe::Customer.search({query: 'name:"one"'}, stripe_version: '2020-08-27')
388
+ expect(response.data.size).to eq(10)
389
+ response = Stripe::Customer.search({query: 'name:"one"', limit: 1}, stripe_version: '2020-08-27')
390
+ expect(response.data.size).to eq(1)
391
+ end
392
+
393
+ it "reports search errors", :aggregate_failures do
394
+ expect {
395
+ Stripe::Customer.search({limit: 1}, stripe_version: '2020-08-27')
396
+ }.to raise_error(Stripe::InvalidRequestError, /Missing required param: query./)
397
+
398
+ expect {
399
+ Stripe::Customer.search({query: 'asdf'}, stripe_version: '2020-08-27')
400
+ }.to raise_error(Stripe::InvalidRequestError, /We were unable to parse your search query./)
401
+
402
+ expect {
403
+ Stripe::Customer.search({query: 'foo:"bar"'}, stripe_version: '2020-08-27')
404
+ }.to raise_error(Stripe::InvalidRequestError, /Field `foo` is an unsupported search field for resource `customers`./)
405
+ end
313
406
  end
314
407
 
315
408
  it "updates a stripe customer" do
@@ -317,8 +410,9 @@ shared_examples 'Customer API' do
317
410
  email = original.email
318
411
 
319
412
  coupon = Stripe::Coupon.create(id: "10PERCENT", duration: 'once')
320
- original.description = 'new desc'
321
- original.coupon = coupon.id
413
+ original.description = 'new desc'
414
+ original.preferred_locales = %w(fr en)
415
+ original.coupon = coupon.id
322
416
  original.save
323
417
 
324
418
  expect(original.email).to eq(email)
@@ -328,9 +422,19 @@ shared_examples 'Customer API' do
328
422
  customer = Stripe::Customer.retrieve("test_customer_update")
329
423
  expect(customer.email).to eq(original.email)
330
424
  expect(customer.description).to eq('new desc')
425
+ expect(customer.preferred_locales).to eq(%w(fr en))
331
426
  expect(customer.discount.coupon).to be_a Stripe::Coupon
332
427
  end
333
428
 
429
+ it "preserves stripe customer metadata" do
430
+ metadata = {user_id: "38"}
431
+ customer = Stripe::Customer.create(metadata: metadata)
432
+ expect(customer.metadata.to_h).to eq(metadata)
433
+
434
+ updated = Stripe::Customer.update(customer.id, metadata: {fruit: "apples"})
435
+ expect(updated.metadata.to_h).to eq(metadata.merge(fruit: "apples"))
436
+ end
437
+
334
438
  it "retrieves the customer's default source after it was updated" do
335
439
  customer = Stripe::Customer.create()
336
440
  customer.source = gen_card_tk
@@ -391,7 +495,7 @@ shared_examples 'Customer API' do
391
495
  end
392
496
 
393
497
  it "still has subscriptions after save when subscriptions unchanged" do
394
- plan = stripe_helper.create_plan(id: 'silver')
498
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id)
395
499
  original = Stripe::Customer.create(source: gen_card_tk, plan: 'silver')
396
500
  subscription = original.subscriptions.data.first
397
501
  subscription_id = subscription.id
@@ -404,7 +508,7 @@ shared_examples 'Customer API' do
404
508
  end
405
509
 
406
510
  it "should add a customer to a subscription" do
407
- plan = stripe_helper.create_plan(id: 'silver')
511
+ plan = stripe_helper.create_plan(id: 'silver', product: product.id)
408
512
  customer = Stripe::Customer.create(source: gen_card_tk)
409
513
  customer.subscriptions.create(plan: plan.id)
410
514
 
@@ -417,14 +521,6 @@ shared_examples 'Customer API' do
417
521
  expect(customer.deleted).to eq(true)
418
522
  end
419
523
 
420
- it 'works with the update_subscription method' do
421
- stripe_helper.create_plan(id: 'silver')
422
- cus = Stripe::Customer.create(source: gen_card_tk)
423
- expect {
424
- cus.update_subscription(plan: 'silver')
425
- }.not_to raise_error
426
- end
427
-
428
524
  it "deletes a stripe customer discount" do
429
525
  original = Stripe::Customer.create(id: 'test_customer_update')
430
526
 
@@ -71,14 +71,14 @@ shared_examples 'Dispute API' do
71
71
  describe "listing disputes" do
72
72
 
73
73
  it "retrieves all disputes" do
74
- disputes = Stripe::Dispute.all
74
+ disputes = Stripe::Dispute.list
75
75
 
76
76
  expect(disputes.count).to eq(10)
77
77
  expect(disputes.map &:id).to include('dp_05RsQX2eZvKYlo2C0FRTGSSA','dp_15RsQX2eZvKYlo2C0ERTYUIA', 'dp_25RsQX2eZvKYlo2C0ZXCVBNM', 'dp_35RsQX2eZvKYlo2C0QAZXSWE', 'dp_45RsQX2eZvKYlo2C0EDCVFRT', 'dp_55RsQX2eZvKYlo2C0OIKLJUY', 'dp_65RsQX2eZvKYlo2C0ASDFGHJ', 'dp_75RsQX2eZvKYlo2C0EDCXSWQ', 'dp_85RsQX2eZvKYlo2C0UJMCDET', 'dp_95RsQX2eZvKYlo2C0EDFRYUI')
78
78
  end
79
79
 
80
80
  it "retrieves disputes with a limit(3)" do
81
- disputes = Stripe::Dispute.all(limit: 3)
81
+ disputes = Stripe::Dispute.list(limit: 3)
82
82
 
83
83
  expect(disputes.count).to eq(3)
84
84
  expected = ['dp_95RsQX2eZvKYlo2C0EDFRYUI','dp_85RsQX2eZvKYlo2C0UJMCDET', 'dp_75RsQX2eZvKYlo2C0EDCXSWQ']