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
@@ -6,13 +6,14 @@ def expect_card_error(code, param)
6
6
  expect(e.http_status).to eq(402)
7
7
  expect(e.code).to eq(code)
8
8
  expect(e.param).to eq(param)
9
+ expect(e.http_body).to eq(e.json_body.to_json)
9
10
  }
10
11
  end
11
12
 
12
13
  shared_examples 'Stripe Error Mocking' do
13
14
 
14
15
  it "mocks a manually given stripe card error" do
15
- error = Stripe::CardError.new('Test Msg', 'param_name', 'bad_code', http_status: 444, http_body: 'body', json_body: 'json body')
16
+ error = Stripe::CardError.new('Test Msg', 'param_name', code: 'bad_code', http_status: 444, http_body: 'body', json_body: {})
16
17
  StripeMock.prepare_error(error)
17
18
 
18
19
  expect { Stripe::Customer.create() }.to raise_error {|e|
@@ -23,14 +24,14 @@ shared_examples 'Stripe Error Mocking' do
23
24
 
24
25
  expect(e.http_status).to eq(444)
25
26
  expect(e.http_body).to eq('body')
26
- expect(e.json_body).to eq('json body')
27
+ expect(e.json_body).to eq({})
27
28
  }
28
29
  end
29
30
 
30
31
 
31
32
  it "mocks a manually gives stripe invalid request error" do
32
33
 
33
- error = Stripe::InvalidRequestError.new('Test Invalid', 'param', http_status: 987, http_body: 'ibody', json_body: 'json ibody')
34
+ error = Stripe::InvalidRequestError.new('Test Invalid', 'param', http_status: 987, http_body: 'ibody', json_body: {})
34
35
  StripeMock.prepare_error(error)
35
36
 
36
37
  expect { Stripe::Charge.create(amount: 1, currency: 'usd') }.to raise_error {|e|
@@ -40,22 +41,22 @@ shared_examples 'Stripe Error Mocking' do
40
41
 
41
42
  expect(e.http_status).to eq(987)
42
43
  expect(e.http_body).to eq('ibody')
43
- expect(e.json_body).to eq('json ibody')
44
+ expect(e.json_body).to eq({})
44
45
  }
45
46
  end
46
47
 
47
48
 
48
49
  it "mocks a manually gives stripe invalid auth error" do
49
- error = Stripe::AuthenticationError.new('Bad Auth', http_status: 499, http_body: 'abody', json_body: 'json abody')
50
+ error = Stripe::AuthenticationError.new('Bad Auth', http_status: 499, http_body: 'abody', json_body: {})
50
51
  StripeMock.prepare_error(error)
51
52
 
52
- expect { stripe_helper.create_plan() }.to raise_error {|e|
53
+ expect { stripe_helper.create_plan(id: "test_plan") }.to raise_error {|e|
53
54
  expect(e).to be_a(Stripe::AuthenticationError)
54
55
  expect(e.message).to eq('Bad Auth')
55
56
 
56
57
  expect(e.http_status).to eq(499)
57
58
  expect(e.http_body).to eq('abody')
58
- expect(e.json_body).to eq('json abody')
59
+ expect(e.json_body).to eq({})
59
60
  }
60
61
  end
61
62
 
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples 'Express Login Link API' do
4
+ describe 'create an Express Login Link' do
5
+ it 'creates a login link' do
6
+ account_link = Stripe::Account.create_login_link('acct_103ED82ePvKYlo2C')
7
+
8
+ expect(account_link).to be_a Stripe::LoginLink
9
+ expect(account_link.url).to start_with('https://connect.stripe.com/express/')
10
+ end
11
+ end
12
+ end
@@ -63,7 +63,7 @@ shared_examples 'External Account API' do
63
63
  let!(:bank) { account.external_accounts.create(external_account: bank_token) }
64
64
 
65
65
  it "can retrieve all account's banks" do
66
- retrieved = account.external_accounts.all
66
+ retrieved = account.external_accounts.list
67
67
  expect(retrieved.count).to eq(1)
68
68
  end
69
69
 
@@ -142,7 +142,7 @@ shared_examples 'External Account API' do
142
142
 
143
143
  account = Stripe::Account.retrieve('test_account')
144
144
 
145
- list = account.external_accounts.all
145
+ list = account.external_accounts.list
146
146
 
147
147
  expect(list.object).to eq("list")
148
148
  expect(list.count).to eq(2)
@@ -159,7 +159,7 @@ shared_examples 'External Account API' do
159
159
  Stripe::Account.create(id: 'no_banks', type: 'custom', country: "US")
160
160
  account = Stripe::Account.retrieve('no_banks')
161
161
 
162
- list = account.external_accounts.all
162
+ list = account.external_accounts.list
163
163
 
164
164
  expect(list.object).to eq("list")
165
165
  expect(list.count).to eq(0)
@@ -14,6 +14,11 @@ shared_examples 'Invoice API' do
14
14
  expect(data[invoice.id]).to_not be_nil
15
15
  expect(data[invoice.id][:id]).to eq(invoice.id)
16
16
  end
17
+
18
+ it "supports invoice number" do
19
+ original = Stripe::Invoice.create
20
+ expect(original.number).to be
21
+ end
17
22
  end
18
23
 
19
24
  context "retrieving an invoice" do
@@ -48,31 +53,114 @@ shared_examples 'Invoice API' do
48
53
  end
49
54
 
50
55
  it "stores invoices for a customer in memory" do
51
- expect(@customer.invoices.map(&:id)).to eq([@invoice.id])
56
+ invoices = Stripe::Invoice.list(customer: @customer.id)
57
+ expect(invoices.map(&:id)).to eq([@invoice.id])
52
58
  end
53
59
 
54
60
  it "stores all invoices in memory" do
55
- expect(Stripe::Invoice.all.map(&:id).sort).to eq([@invoice.id, @invoice2.id].sort)
61
+ expect(Stripe::Invoice.list.map(&:id)).to match_array([@invoice.id, @invoice2.id])
56
62
  end
57
63
 
58
64
  it "defaults count to 10 invoices" do
59
65
  11.times { Stripe::Invoice.create }
60
- expect(Stripe::Invoice.all.count).to eq(10)
66
+ expect(Stripe::Invoice.list.count).to eq(10)
61
67
  end
62
68
 
63
69
  it "is marked as having more when more objects exist" do
64
70
  11.times { Stripe::Invoice.create }
65
71
 
66
- expect(Stripe::Invoice.all.has_more).to eq(true)
72
+ expect(Stripe::Invoice.list.has_more).to eq(true)
67
73
  end
68
74
 
69
75
  context "when passing limit" do
70
76
  it "gets that many invoices" do
71
- expect(Stripe::Invoice.all(limit: 1).count).to eq(1)
77
+ expect(Stripe::Invoice.list(limit: 1).count).to eq(1)
72
78
  end
73
79
  end
74
80
  end
75
81
 
82
+ context "searching invoices" do
83
+ # the Search API requires about a minute between writes and reads, so add sleeps accordingly when running live
84
+ it "searches invoices for exact matches", :aggregate_failures do
85
+ response = Stripe::Invoice.search({query: 'currency:"usd"'}, stripe_version: '2020-08-27')
86
+ expect(response.data.size).to eq(0)
87
+
88
+ product = stripe_helper.create_product
89
+ stripe_helper.create_plan(
90
+ amount: 500,
91
+ interval: 'month',
92
+ product: product.id,
93
+ currency: 'usd',
94
+ id: 'Sample5',
95
+ )
96
+ customer = Stripe::Customer.create(email: 'johnny@appleseed.com', source: stripe_helper.generate_card_token)
97
+ subscription = Stripe::Subscription.create(customer: customer.id, items: [{plan: 'Sample5'}])
98
+ one = Stripe::Invoice.create(
99
+ customer: customer.id,
100
+ currency: 'usd',
101
+ subscription: subscription.id,
102
+ metadata: {key: 'uno'},
103
+ number: 'one-1',
104
+ receipt_number: '111',
105
+ )
106
+ two = Stripe::Invoice.create(
107
+ customer: customer.id,
108
+ currency: 'gbp',
109
+ subscription: subscription.id,
110
+ metadata: {key: 'dos'},
111
+ number: 'two-2',
112
+ receipt_number: '222',
113
+ )
114
+
115
+ response = Stripe::Invoice.search({query: 'currency:"gbp"'}, stripe_version: '2020-08-27')
116
+ expect(response.data.map(&:id)).to match_array([two.id])
117
+
118
+ response = Stripe::Invoice.search({query: %(customer:"#{customer.id}")}, stripe_version: '2020-08-27')
119
+ expect(response.data.map(&:id)).to match_array([one.id, two.id])
120
+
121
+ response = Stripe::Invoice.search({query: 'number:"one-1"'}, stripe_version: '2020-08-27')
122
+ expect(response.data.map(&:id)).to match_array([one.id])
123
+
124
+ response = Stripe::Invoice.search({query: 'receipt_number:"222"'}, stripe_version: '2020-08-27')
125
+ expect(response.data.map(&:id)).to match_array([two.id])
126
+
127
+ response = Stripe::Invoice.search({query: %(subscription:"#{subscription.id}")}, stripe_version: '2020-08-27')
128
+ expect(response.data.map(&:id)).to match_array([one.id, two.id])
129
+
130
+ response = Stripe::Invoice.search({query: 'total:1000'}, stripe_version: '2020-08-27')
131
+ expect(response.data.map(&:id)).to match_array([one.id, two.id])
132
+
133
+ response = Stripe::Invoice.search({query: 'metadata["key"]:"uno"'}, stripe_version: '2020-08-27')
134
+ expect(response.data.map(&:id)).to match_array([one.id])
135
+ end
136
+
137
+ it "respects limit", :aggregate_failures do
138
+ customer = Stripe::Customer.create(email: 'one@one.com', name: 'one', phone: '1111111111', metadata: {key: 'uno'})
139
+ 11.times do
140
+ Stripe::Invoice.create(customer: customer.id, currency: 'usd')
141
+ end
142
+
143
+ response = Stripe::Invoice.search({query: %(customer:"#{customer.id}")}, stripe_version: '2020-08-27')
144
+ expect(response.data.size).to eq(10)
145
+ response = Stripe::Invoice.search({query: %(customer:"#{customer.id}"), limit: 1}, stripe_version: '2020-08-27')
146
+ expect(response.data.size).to eq(1)
147
+ end
148
+
149
+ it "reports search errors", :aggregate_failures do
150
+ expect {
151
+ Stripe::Invoice.search({limit: 1}, stripe_version: '2020-08-27')
152
+ }.to raise_error(Stripe::InvalidRequestError, /Missing required param: query./)
153
+
154
+ expect {
155
+ Stripe::Invoice.search({query: 'asdf'}, stripe_version: '2020-08-27')
156
+ }.to raise_error(Stripe::InvalidRequestError, /We were unable to parse your search query./)
157
+
158
+ expect {
159
+ Stripe::Invoice.search({query: 'foo:"bar"'}, stripe_version: '2020-08-27')
160
+ }.to raise_error(Stripe::InvalidRequestError, /Field `foo` is an unsupported search field for resource `invoices`./)
161
+ end
162
+ end
163
+
76
164
  context "paying an invoice" do
77
165
  before do
78
166
  @invoice = Stripe::Invoice.create
@@ -82,12 +170,28 @@ shared_examples 'Invoice API' do
82
170
  @invoice = @invoice.pay
83
171
  expect(@invoice.attempted).to eq(true)
84
172
  expect(@invoice.paid).to eq(true)
173
+ expect(@invoice.status).to eq("paid")
85
174
  end
86
175
 
87
176
  it 'creates a new charge object' do
88
177
  expect{ @invoice.pay }.to change { Stripe::Charge.list.data.count }.by 1
89
178
  end
90
179
 
180
+ it 'should work with Stripe::Invoice.pay(invoice_id)' do
181
+ expect(@invoice.paid).to_not eq(true)
182
+
183
+ expect {
184
+ Stripe::Invoice.pay(@invoice.id)
185
+ }.to change { Stripe::Charge.list.data.count }.by 1
186
+
187
+ @invoice = Stripe::Invoice.retrieve(id: @invoice.id)
188
+ expect(@invoice).to_not be_nil
189
+
190
+ expect(@invoice.attempted).to eq(true)
191
+ expect(@invoice.paid).to eq(true)
192
+ expect(@invoice.status).to eq("paid")
193
+ end
194
+
91
195
  it 'sets the charge attribute' do
92
196
  @invoice = @invoice.pay
93
197
  expect(@invoice.charge).to be_a String
@@ -109,8 +213,9 @@ shared_examples 'Invoice API' do
109
213
  context "retrieving upcoming invoice" do
110
214
  let(:customer) { Stripe::Customer.create(source: stripe_helper.generate_card_token) }
111
215
  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') }
216
+ let(:coupon_pctoff) { stripe_helper.create_coupon(id: '50OFF', currency: 'usd', percent_off: 50, amount_off: nil, duration: 'repeating', duration_in_months: 6) }
217
+ let(:product) { stripe_helper.create_product(id: "prod_123") }
218
+ let(:plan) { stripe_helper.create_plan(id: '50m', product: product.id, amount: 50_00, interval: 'month', nickname: '50m', currency: 'usd') }
114
219
  let(:quantity) { 3 }
115
220
  let(:subscription) { Stripe::Subscription.create(plan: plan.id, customer: customer.id, quantity: quantity) }
116
221
 
@@ -131,7 +236,10 @@ shared_examples 'Invoice API' do
131
236
  describe 'parameter validation' do
132
237
  it 'fails without parameters' do
133
238
  expect { Stripe::Invoice.upcoming() }.to raise_error {|e|
134
- expect(e).to be_a(ArgumentError) }
239
+ expect(e).to be_a(Stripe::InvalidRequestError)
240
+ expect(e.http_status).to eq(400)
241
+ expect(e.message).to eq('Missing required param: customer if subscription is not provided')
242
+ }
135
243
  end
136
244
 
137
245
  it 'fails without a valid customer' do
@@ -144,7 +252,7 @@ shared_examples 'Invoice API' do
144
252
  expect { Stripe::Invoice.upcoming(gazebo: 'raindance') }.to raise_error {|e|
145
253
  expect(e).to be_a(Stripe::InvalidRequestError)
146
254
  expect(e.http_status).to eq(400)
147
- expect(e.message).to eq('Missing required param: customer') }
255
+ expect(e.message).to eq('Missing required param: customer if subscription is not provided') }
148
256
  end
149
257
 
150
258
  it 'fails without a subscription' do
@@ -198,8 +306,8 @@ shared_examples 'Invoice API' do
198
306
  expect(upcoming.discount).not_to be_nil
199
307
  expect(upcoming.discount.coupon.id).to eq '100OFF'
200
308
  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
309
+ expect(upcoming.discount.start).to be_within(60).of Time.now.to_i
310
+ expect(upcoming.discount.end).to be_within(60).of (Time.now.to_datetime >> 6).to_time.to_i
203
311
  expect(upcoming.amount_due).to eq plan.amount * quantity - 100_00
204
312
  expect(upcoming.subtotal).to eq(upcoming.lines.data[0].amount)
205
313
  expect(upcoming.total).to eq upcoming.subtotal - 100_00
@@ -211,10 +319,10 @@ shared_examples 'Invoice API' do
211
319
 
212
320
  # Then
213
321
  expect(upcoming.discount).not_to be_nil
214
- expect(upcoming.discount.coupon.id).to eq '50%OFF'
322
+ expect(upcoming.discount.coupon.id).to eq '50OFF'
215
323
  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
324
+ expect(upcoming.discount.start).to be_within(60).of Time.now.to_i
325
+ expect(upcoming.discount.end).to be_within(60).of (Time.now.to_datetime >> 6).to_time.to_i
218
326
  expect(upcoming.amount_due).to eq (plan.amount * quantity) * 0.5
219
327
  expect(upcoming.subtotal).to eq(upcoming.lines.data[0].amount)
220
328
  expect(upcoming.total).to eq upcoming.subtotal * 0.5
@@ -223,7 +331,7 @@ shared_examples 'Invoice API' do
223
331
 
224
332
  describe 'proration' do
225
333
  shared_examples 'failing when proration date is outside of the subscription current period' do
226
- it 'fails', live: true do
334
+ it 'fails', live: true, skip: 'Stripe does not raise error anymore' do
227
335
  expect { Stripe::Invoice.upcoming(
228
336
  customer: customer.id,
229
337
  subscription: subscription.id,
@@ -248,9 +356,9 @@ shared_examples 'Invoice API' do
248
356
 
249
357
  [false, true].each do |with_trial|
250
358
  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') }
359
+ let(:new_monthly_plan) { stripe_helper.create_plan(id: '100m', product: product.id, amount: 100_00, interval: 'month') }
360
+ let(:new_yearly_plan) { stripe_helper.create_plan(id: '100y', product: product.id, amount: 100_00, interval: 'year') }
361
+ let(:plan) { stripe_helper.create_plan(id: '50m', product: product.id, amount: 50_00, interval: 'month') }
254
362
 
255
363
  it 'prorates while maintaining billing interval', live: true do
256
364
  # Given
@@ -271,19 +379,17 @@ shared_examples 'Invoice API' do
271
379
  # Then
272
380
  expect(upcoming).to be_a Stripe::Invoice
273
381
  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
382
  expect(upcoming.starting_balance).to eq -credit_balance
280
- expect(upcoming.ending_balance).to be_nil
281
383
  expect(upcoming.subscription).to eq(subscription.id)
282
384
 
283
385
  if with_trial
386
+ expect(upcoming.amount_due).to be_within(1).of 0
284
387
  expect(upcoming.lines.data.length).to eq(2)
388
+ # expect(upcoming.ending_balance).to be_within(50).of -13540 # -13322
285
389
  else
390
+ expect(upcoming.amount_due).to be_within(1).of prorated_amount_due - credit_balance
286
391
  expect(upcoming.lines.data.length).to eq(3)
392
+ expect(upcoming.ending_balance).to eq 0
287
393
  end
288
394
 
289
395
  expect(upcoming.lines.data[0].proration).to be_truthy
@@ -308,9 +414,10 @@ shared_examples 'Invoice API' do
308
414
  # Given
309
415
  proration_date = Time.now + 5 * 24 * 3600 # 5 days later
310
416
  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)
417
+ unused_amount = (plan.amount.to_f * quantity * (subscription.current_period_end - proration_date.to_i) / (subscription.current_period_end - subscription.current_period_start)).round
312
418
  prorated_amount_due = new_yearly_plan.amount * new_quantity - unused_amount
313
419
  credit_balance = 1000
420
+ amount_due = prorated_amount_due - credit_balance
314
421
  customer.account_balance = -credit_balance
315
422
  customer.save
316
423
  query = { customer: customer.id, subscription: subscription.id, subscription_plan: new_yearly_plan.id, subscription_proration_date: proration_date.to_i, subscription_quantity: new_quantity }
@@ -323,12 +430,13 @@ shared_examples 'Invoice API' do
323
430
  expect(upcoming).to be_a Stripe::Invoice
324
431
  expect(upcoming.customer).to eq(customer.id)
325
432
  if with_trial
433
+ # expect(upcoming.ending_balance).to be_within(50).of -13540 # -13322
326
434
  expect(upcoming.amount_due).to eq 0
327
435
  else
328
- expect(upcoming.amount_due).to be_within(1).of prorated_amount_due - credit_balance
436
+ expect(upcoming.ending_balance).to eq 0
437
+ expect(upcoming.amount_due).to be_within(1).of amount_due
329
438
  end
330
439
  expect(upcoming.starting_balance).to eq -credit_balance
331
- expect(upcoming.ending_balance).to be_nil
332
440
  expect(upcoming.subscription).to eq(subscription.id)
333
441
 
334
442
  expect(upcoming.lines.data[0].proration).to be_truthy
@@ -351,7 +459,7 @@ shared_examples 'Invoice API' do
351
459
  it 'generates a preview without performing an actual proration', live: true do
352
460
  expect(preview.subtotal).to eq 150_00
353
461
  # 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
462
+ expect(preview.due_date).to be_nil
355
463
  expect(preview.period_start).to eq subscription.current_period_start
356
464
  expect(preview.period_end).to eq subscription.current_period_end
357
465
  expect(preview.lines.count).to eq 1
@@ -393,7 +501,7 @@ shared_examples 'Invoice API' do
393
501
  end
394
502
 
395
503
  it 'sets the start and end of billing periods correctly when plan has an interval_count' do
396
- @oddplan = stripe_helper.create_plan(interval: "week", interval_count: 11)
504
+ @oddplan = stripe_helper.create_plan(product: product.id, interval: "week", interval_count: 11, id: "weekly_pl")
397
505
  @subscription = Stripe::Subscription.create(plan: @oddplan.id, customer: customer.id)
398
506
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
399
507
 
@@ -404,9 +512,9 @@ shared_examples 'Invoice API' do
404
512
  end
405
513
 
406
514
  it 'chooses the most recent of multiple subscriptions' do
407
- @shortplan = stripe_helper.create_plan(id: 'a', interval: "week") # 1 week sub
408
- @plainplan = stripe_helper.create_plan(id: 'b') # 1 month sub
409
- @longplan = stripe_helper.create_plan(id: 'c', interval: "year") # 1 year sub
515
+ @shortplan = stripe_helper.create_plan(id: 'a', product: product.id, interval: "week") # 1 week sub
516
+ @plainplan = stripe_helper.create_plan(id: 'b', product: product.id, interval: "month") # 1 month sub
517
+ @longplan = stripe_helper.create_plan(id: 'c', product: product.id, interval: "year") # 1 year sub
410
518
 
411
519
  @plainsub = Stripe::Subscription.create(plan: @plainplan.id, customer: customer.id)
412
520
  @shortsub = Stripe::Subscription.create(plan: @shortplan.id, customer: customer.id)
@@ -428,7 +536,7 @@ shared_examples 'Invoice API' do
428
536
  context 'retrieving invoice line items' do
429
537
  it 'returns all line items for created invoice' do
430
538
  invoice = Stripe::Invoice.create(customer: customer.id)
431
- line_items = invoice.lines.all
539
+ line_items = invoice.lines.list
432
540
 
433
541
  expect(invoice).to be_a Stripe::Invoice
434
542
  expect(line_items.count).to eq(1)
@@ -438,7 +546,7 @@ shared_examples 'Invoice API' do
438
546
  end
439
547
 
440
548
  it 'returns all line items for upcoming invoice' do
441
- plan = stripe_helper.create_plan()
549
+ plan = stripe_helper.create_plan(product: product.id, id: "silver_pl")
442
550
  subscription = Stripe::Subscription.create(plan: plan.id, customer: customer.id)
443
551
  upcoming = Stripe::Invoice.upcoming(customer: customer.id)
444
552
  line_items = upcoming.lines
@@ -454,7 +562,7 @@ shared_examples 'Invoice API' do
454
562
  context 'calculates month and year offsets correctly' do
455
563
 
456
564
  it 'for one month plan on the 1st' do
457
- @plan = stripe_helper.create_plan()
565
+ @plan = stripe_helper.create_plan(product: product.id, id: "one_mo_plan")
458
566
  @sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2014,1,1,12).to_i)
459
567
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
460
568
 
@@ -465,7 +573,7 @@ shared_examples 'Invoice API' do
465
573
  end
466
574
 
467
575
  it 'for one year plan on the 1st' do
468
- @plan = stripe_helper.create_plan(interval: "year")
576
+ @plan = stripe_helper.create_plan(interval: "year", product: product.id, id: "year_plan")
469
577
  @sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2012,1,1,12).to_i)
470
578
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
471
579
 
@@ -476,7 +584,7 @@ shared_examples 'Invoice API' do
476
584
  end
477
585
 
478
586
  it 'for one month plan on the 31st' do
479
- @plan = stripe_helper.create_plan()
587
+ @plan = stripe_helper.create_plan(product: product.id, id: "one_mo_plan")
480
588
  @sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2014,1,31,12).to_i)
481
589
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
482
590
 
@@ -487,7 +595,7 @@ shared_examples 'Invoice API' do
487
595
  end
488
596
 
489
597
  it 'for one year plan on feb. 29th' do
490
- @plan = stripe_helper.create_plan(interval: "year")
598
+ @plan = stripe_helper.create_plan(product: product.id, interval: "year", id: "year_plan")
491
599
  @sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2012,2,29,12).to_i)
492
600
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
493
601
 
@@ -498,7 +606,7 @@ shared_examples 'Invoice API' do
498
606
  end
499
607
 
500
608
  it 'for two month plan on dec. 31st' do
501
- @plan = stripe_helper.create_plan(interval_count: 2)
609
+ @plan = stripe_helper.create_plan(product: product.id, interval_count: 2, id: 'two_mo_plan')
502
610
  @sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2013,12,31,12).to_i)
503
611
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
504
612
 
@@ -509,7 +617,7 @@ shared_examples 'Invoice API' do
509
617
  end
510
618
 
511
619
  it 'for three month plan on nov. 30th' do
512
- @plan = stripe_helper.create_plan(interval_count: 3)
620
+ @plan = stripe_helper.create_plan(product: product.id, interval_count: 3)
513
621
  @sub = Stripe::Subscription.create(plan: @plan.id, customer: customer.id, current_period_start: Time.utc(2013,11,30,12).to_i)
514
622
  @upcoming = Stripe::Invoice.upcoming(customer: customer.id)
515
623
 
@@ -39,7 +39,7 @@ shared_examples 'Invoice Item API' do
39
39
  end
40
40
 
41
41
  it "retrieves all invoice items" do
42
- all = Stripe::InvoiceItem.all
42
+ all = Stripe::InvoiceItem.list
43
43
  expect(all.count).to eq(2)
44
44
  expect(all.map &:amount).to include(1075, 1540)
45
45
  end