stripe-ruby-mock 4.0.0 → 5.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec_tests.yml +16 -16
  3. data/Appraisals +7 -0
  4. data/CHANGELOG.md +20 -0
  5. data/Gemfile +2 -0
  6. data/README.md +9 -3
  7. data/bin/stripe-mock-server +1 -0
  8. data/gemfiles/.bundle/config +2 -0
  9. data/gemfiles/stripe_12.gemfile +13 -0
  10. data/gemfiles/stripe_12.gemfile.lock +60 -0
  11. data/gemfiles/stripe_13.gemfile +13 -0
  12. data/gemfiles/stripe_13.gemfile.lock +60 -0
  13. data/lib/stripe_mock/api/client.rb +12 -4
  14. data/lib/stripe_mock/api/instance.rb +5 -3
  15. data/lib/stripe_mock/client.rb +2 -3
  16. data/lib/stripe_mock/compat.rb +29 -0
  17. data/lib/stripe_mock/data.rb +61 -9
  18. data/lib/stripe_mock/instance.rb +47 -4
  19. data/lib/stripe_mock/request_handlers/checkout_session.rb +12 -11
  20. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +1 -0
  21. data/lib/stripe_mock/request_handlers/invoices.rb +8 -2
  22. data/lib/stripe_mock/request_handlers/payment_intents.rb +1 -1
  23. data/lib/stripe_mock/request_handlers/payment_methods.rb +5 -1
  24. data/lib/stripe_mock/request_handlers/payouts.rb +10 -3
  25. data/lib/stripe_mock/request_handlers/subscriptions.rb +1 -1
  26. data/lib/stripe_mock/request_handlers/tax_ids.rb +66 -0
  27. data/lib/stripe_mock/server.rb +9 -4
  28. data/lib/stripe_mock/test_strategies/base.rb +0 -1
  29. data/lib/stripe_mock/util.rb +6 -0
  30. data/lib/stripe_mock/version.rb +1 -1
  31. data/lib/stripe_mock.rb +2 -1
  32. data/spec/instance_spec.rb +7 -2
  33. data/spec/list_spec.rb +1 -1
  34. data/spec/server_spec.rb +12 -3
  35. data/spec/shared_stripe_examples/account_examples.rb +1 -1
  36. data/spec/shared_stripe_examples/checkout_session_examples.rb +0 -5
  37. data/spec/shared_stripe_examples/customer_examples.rb +1 -1
  38. data/spec/shared_stripe_examples/payment_intent_examples.rb +13 -13
  39. data/spec/shared_stripe_examples/payment_method_examples.rb +10 -0
  40. data/spec/shared_stripe_examples/payout_examples.rb +26 -6
  41. data/spec/shared_stripe_examples/product_examples.rb +3 -0
  42. data/spec/shared_stripe_examples/setup_intent_examples.rb +5 -1
  43. data/spec/shared_stripe_examples/subscription_examples.rb +1 -1
  44. data/spec/shared_stripe_examples/transfer_examples.rb +10 -3
  45. data/spec/spec_helper.rb +1 -0
  46. data/spec/stripe_mock_spec.rb +35 -13
  47. data/stripe-ruby-mock.gemspec +2 -1
  48. metadata +33 -8
@@ -12,16 +12,17 @@ module StripeMock
12
12
  def new_session(route, method_url, params, headers)
13
13
  id = params[:id] || new_id('cs')
14
14
 
15
- [:cancel_url, :success_url].each do |p|
16
- require_param(p) if params[p].nil? || params[p].empty?
17
- end
15
+ require_param(:success_url) if params[:success_url].nil? || params[:success_url].empty?
18
16
 
19
17
  line_items = nil
20
18
  if params[:line_items]
21
19
  line_items = params[:line_items].each_with_index.map do |line_item, i|
22
- throw Stripe::InvalidRequestError("Quantity is required. Add `quantity` to `line_items[#{i}]`") unless line_item[:quantity]
20
+ unless line_item[:quantity]
21
+ raise Stripe::InvalidRequestError.new("Quantity is required. Add `quantity` to `line_items[#{i}]`", :line_items)
22
+ end
23
+
23
24
  unless line_item[:price] || line_item[:price_data] || (line_item[:amount] && line_item[:currency] && line_item[:name])
24
- throw Stripe::InvalidRequestError("Price or amount and currency is required. Add `price`, `price_data`, or `amount`, `currency` and `name` to `line_items[#{i}]`")
25
+ raise Stripe::InvalidRequestError.new("Price or amount and currency is required. Add `price`, `price_data`, or `amount`, `currency` and `name` to `line_items[#{i}]`", :line_items)
25
26
  end
26
27
  {
27
28
  id: new_id("li"),
@@ -48,11 +49,11 @@ module StripeMock
48
49
  if line_items
49
50
  amount = 0
50
51
 
51
- line_items.each do |line_item|
52
+ line_items.each do |line_item|
52
53
  price = prices[line_item[:price]]
53
54
 
54
55
  if price.nil?
55
- raise StripeMock::StripeMockError.new("Price not found for ID: #{line_item[:price]}")
56
+ raise StripeMock::StripeMockError.new("Price not found for ID: #{line_item[:price]}", :line_items)
56
57
  end
57
58
 
58
59
  amount += (price[:unit_amount] * line_item[:quantity])
@@ -78,7 +79,7 @@ module StripeMock
78
79
  checkout_session_line_items[id] = line_items
79
80
  when "setup"
80
81
  if !params[:line_items].nil? && !params[:line_items].empty?
81
- throw Stripe::InvalidRequestError.new("You cannot pass `line_items` in `setup` mode", :line_items, http_status: 400)
82
+ raise Stripe::InvalidRequestError.new("You cannot pass `line_items` in `setup` mode", :line_items, http_status: 400)
82
83
  end
83
84
  setup_intent = new_setup_intent(nil, nil, {
84
85
  customer: params[:customer],
@@ -91,7 +92,7 @@ module StripeMock
91
92
  require_param(:line_items) if params[:line_items].nil? || params[:line_items].empty?
92
93
  checkout_session_line_items[id] = line_items
93
94
  else
94
- throw Stripe::InvalidRequestError.new("Invalid mode: must be one of payment, setup, or subscription", :mode, http_status: 400)
95
+ raise Stripe::InvalidRequestError.new("Invalid mode: must be one of payment, setup, or subscription", :mode, http_status: 400)
95
96
  end
96
97
 
97
98
  checkout_sessions[id] = {
@@ -156,7 +157,7 @@ module StripeMock
156
157
  price = prices[line_item[:price]].clone
157
158
 
158
159
  if price.nil?
159
- raise StripeMock::StripeMockError.new("Price not found for ID: #{line_item[:price]}")
160
+ raise StripeMock::StripeMockError.new("Price not found for ID: #{line_item[:price]}", :line_items)
160
161
  end
161
162
 
162
163
  {
@@ -170,7 +171,7 @@ module StripeMock
170
171
  }
171
172
  end
172
173
  else
173
- throw Stripe::InvalidRequestError("Only payment and subscription sessions have line items")
174
+ raise Stripe::InvalidRequestError.new("Only payment and subscription sessions have line items", :line_items)
174
175
  end
175
176
  end
176
177
  end
@@ -3,6 +3,7 @@ module StripeMock
3
3
  module Helpers
4
4
  def add_coupon_to_object(object, coupon)
5
5
  discount_attrs = {}.tap do |attrs|
6
+ attrs[:object] = "discount"
6
7
  attrs[object[:object]] = object[:id]
7
8
  attrs[:coupon] = coupon
8
9
  attrs[:start] = Time.now.to_i
@@ -77,6 +77,9 @@ module StripeMock
77
77
  raise Stripe::InvalidRequestError.new('When previewing changes to a subscription, you must specify either `subscription` or `subscription_items`', nil, http_status: 400) if !params[:subscription_proration_date].nil? && params[:subscription].nil? && params[:subscription_plan].nil?
78
78
  raise Stripe::InvalidRequestError.new('Cannot specify proration date without specifying a subscription', nil, http_status: 400) if !params[:subscription_proration_date].nil? && params[:subscription].nil?
79
79
 
80
+ if params[:subscription] && params[:customer].nil?
81
+ params[:customer] = subscriptions[params[:subscription]][:customer]
82
+ end
80
83
  customer = customers[stripe_account][params[:customer]]
81
84
  assert_existence :customer, params[:customer], customer
82
85
 
@@ -114,8 +117,9 @@ module StripeMock
114
117
  invoice_lines = []
115
118
 
116
119
  if prorating
120
+ plan_amount = subscription[:plan][:amount] || subscription[:plan][:unit_amount]
117
121
  unused_amount = (
118
- subscription[:plan][:amount].to_f *
122
+ plan_amount.to_f *
119
123
  subscription[:quantity] *
120
124
  (subscription[:current_period_end] - subscription_proration_date.to_i) / (subscription[:current_period_end] - subscription[:current_period_start])
121
125
  ).ceil
@@ -169,11 +173,13 @@ module StripeMock
169
173
  private
170
174
 
171
175
  def get_mock_subscription_line_item(subscription)
176
+ plan_amount = subscription[:plan][:amount] || subscription[:plan][:unit_amount]
177
+
172
178
  Data.mock_line_item(
173
179
  id: subscription[:id],
174
180
  type: "subscription",
175
181
  plan: subscription[:plan],
176
- amount: subscription[:status] == 'trialing' ? 0 : subscription[:plan][:amount] * subscription[:quantity],
182
+ amount: subscription[:status] == 'trialing' ? 0 : plan_amount * subscription[:quantity],
177
183
  discountable: true,
178
184
  quantity: subscription[:quantity],
179
185
  period: {
@@ -193,7 +193,7 @@ module StripeMock
193
193
  payment_method: payment_intent[:payment_method]
194
194
  )
195
195
 
196
- payment_intent[:charges][:data] << charges[charge_id].clone
196
+ payment_intent[:latest_charge] = charge_id
197
197
 
198
198
  payment_intent
199
199
  end
@@ -116,8 +116,12 @@ module StripeMock
116
116
  end
117
117
  end
118
118
 
119
+ def valid_types
120
+ %w(card ideal sepa_debit us_bank_account)
121
+ end
122
+
119
123
  def invalid_type?(type)
120
- !%w(card ideal sepa_debit).include?(type)
124
+ !valid_types.include?(type)
121
125
  end
122
126
  end
123
127
  end
@@ -4,18 +4,25 @@ module StripeMock
4
4
 
5
5
  def Payouts.included(klass)
6
6
  klass.add_handler 'post /v1/payouts', :new_payout
7
+ klass.add_handler 'post /v1/payouts/(.*)', :update_payout
7
8
  klass.add_handler 'get /v1/payouts', :list_payouts
8
9
  klass.add_handler 'get /v1/payouts/(.*)', :get_payout
9
10
  end
10
11
 
11
12
  def new_payout(route, method_url, params, headers)
12
- id = new_id('po')
13
+ params[:id] ||= new_id("po")
13
14
 
14
- unless params[:amount].is_a?(Integer) || (params[:amount].is_a?(String) && /^\d+$/.match(params[:amount]))
15
+ unless (params[:amount].is_a?(Integer) && params[:amount].positive?) || (params[:amount].is_a?(String) && /^\d+$/.match(params[:amount]))
15
16
  raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', http_status: 400)
16
17
  end
17
18
 
18
- payouts[id] = Data.mock_payout(params.merge :id => id)
19
+ payouts[params[:id]] = Data.mock_payout(params.merge :id => params[:id])
20
+ end
21
+
22
+ def update_payout(route, method_url, params, headers)
23
+ route =~ method_url
24
+ assert_existence :payout, $1, payouts[$1]
25
+ payouts[$1].merge!(params)
19
26
  end
20
27
 
21
28
  def list_payouts(route, method_url, params, headers)
@@ -167,7 +167,7 @@ module StripeMock
167
167
  end
168
168
 
169
169
  if params[:transfer_data] && !params[:transfer_data].empty?
170
- throw Stripe::InvalidRequestError.new(missing_param_message("transfer_data[destination]")) unless params[:transfer_data][:destination]
170
+ raise Stripe::InvalidRequestError.new(missing_param_message("transfer_data[destination]")) unless params[:transfer_data][:destination]
171
171
  subscription[:transfer_data] = params[:transfer_data].dup
172
172
  subscription[:transfer_data][:amount_percent] ||= 100
173
173
  end
@@ -0,0 +1,66 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module TaxIds
4
+ def TaxIds.included(klass)
5
+ klass.add_handler 'post /v1/tax_ids', :new_tax_id
6
+ klass.add_handler 'post /v1/customers/(.*)/tax_ids', :new_customer_tax_id
7
+ klass.add_handler 'get /v1/tax_ids/([^/]*)', :get_tax_id
8
+ klass.add_handler 'get /v1/customers/(.*)/tax_ids/([^/]*)', :get_customer_tax_id
9
+ klass.add_handler 'get /v1/tax_ids', :list_tax_ids
10
+ klass.add_handler 'get /v1/customers/(.*)/tax_ids', :list_customer_tax_ids
11
+ klass.add_handler 'delete /v1/tax_ids/([^/]*)', :delete_tax_id
12
+ klass.add_handler 'delete /v1/customers/(.*)/tax_ids/([^/]*)', :delete_customer_tax_id
13
+ end
14
+
15
+ def new_tax_id(route, method_url, params, headers)
16
+ params[:id] ||= new_id('txi')
17
+ tax_ids[ params[:id] ] = Data.mock_tax_id(params)
18
+ tax_ids[ params[:id] ]
19
+ end
20
+ def new_customer_tax_id(route, method_url, params, headers)
21
+ new_tax_id(route, method_url, params.merge(customer: $1))
22
+ end
23
+
24
+ def get_tax_id(route, method_url, params, headers)
25
+ route =~ method_url
26
+ tax_id = assert_existence :tax_id, $1, tax_ids[$1]
27
+ tax_id.clone
28
+ end
29
+ def get_customer_tax_id(route, method_url, params, headers)
30
+ route =~ method_url
31
+ tax_id = tax_ids[$2]
32
+ tax_id = nil if tax_id[:customer] != $1
33
+ tax_id = assert_existence :tax_id, $2, tax_id
34
+ tax_id.clone
35
+ end
36
+
37
+ def list_tax_ids(route, method_url, params, headers)
38
+ Data.mock_list_object(tax_ids.values, params)
39
+ end
40
+ def list_customer_tax_ids(route, method_url, params, headers)
41
+ Data.mock_list_object(tax_ids.values.select { |t| t[:customer] == $1 }, params)
42
+ end
43
+
44
+ def delete_tax_id(route, method_url, params, headers)
45
+ route =~ method_url
46
+ assert_existence :tax_id, $1, tax_ids[$1]
47
+
48
+ tax_ids[$1] = {
49
+ id: tax_ids[$1][:id],
50
+ deleted: true
51
+ }
52
+ end
53
+ def delete_customer_tax_id(route, method_url, params, headers)
54
+ route =~ method_url
55
+ tax_id = tax_ids[$2]
56
+ tax_id = nil if tax_id[:customer] != $1
57
+ tax_id = assert_existence :tax_id, $2, tax_id
58
+
59
+ tax_ids[$2] = {
60
+ id: tax_ids[$2][:id],
61
+ deleted: true
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -3,10 +3,16 @@ require 'drb/drb'
3
3
  module StripeMock
4
4
  class Server
5
5
  def self.start_new(opts)
6
- puts "Starting StripeMock server on port #{opts[:port] || 4999}"
6
+ host = opts.fetch(:host, "0.0.0.0")
7
+ port = opts.fetch(:port, 4999)
8
+ extra_requires = opts.fetch(:require, [])
7
9
 
8
- host = opts.fetch :host,'0.0.0.0'
9
- port = opts.fetch :port, 4999
10
+ extra_requires.each do |path|
11
+ puts "Requiring additional path: #{path}"
12
+ require(path)
13
+ end
14
+
15
+ puts "Starting StripeMock server on port #{port}"
10
16
 
11
17
  DRb.start_service "druby://#{host}:#{port}", Server.new
12
18
  DRb.thread.join
@@ -88,6 +94,5 @@ module StripeMock
88
94
  def upsert_stripe_object(object, attributes)
89
95
  @instance.upsert_stripe_object(object, attributes)
90
96
  end
91
-
92
97
  end
93
98
  end
@@ -121,7 +121,6 @@ module StripeMock
121
121
  amount: 500,
122
122
  currency: 'usd',
123
123
  }],
124
- cancel_url: "https://example.com/cancel",
125
124
  success_url: "https://example.com/success",
126
125
  }.merge(params)
127
126
  end
@@ -40,5 +40,11 @@ module StripeMock
40
40
  old_param.merge(new_param)
41
41
  end
42
42
 
43
+ def self.snake_case(str)
44
+ str.gsub(/([a-z])([A-Z])/, '\1_\2') # Convert camelCase to snake_case
45
+ .gsub(/[-]/, '_') # Convert kebab-case to snake_case
46
+ .downcase # Ensure all characters are lowercase
47
+ end
48
+
43
49
  end
44
50
  end
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "4.0.0"
3
+ VERSION = "5.0.0"
4
4
  end
data/lib/stripe_mock.rb CHANGED
@@ -8,7 +8,7 @@ require 'stripe'
8
8
  require 'stripe_mock/version'
9
9
  require 'stripe_mock/util'
10
10
  require 'stripe_mock/error_queue'
11
-
11
+ require 'stripe_mock/compat'
12
12
  require 'stripe_mock/data'
13
13
  require 'stripe_mock/data/list'
14
14
 
@@ -80,6 +80,7 @@ require 'stripe_mock/request_handlers/tokens.rb'
80
80
  require 'stripe_mock/request_handlers/country_spec.rb'
81
81
  require 'stripe_mock/request_handlers/ephemeral_key.rb'
82
82
  require 'stripe_mock/request_handlers/products.rb'
83
+ require 'stripe_mock/request_handlers/tax_ids.rb'
83
84
  require 'stripe_mock/request_handlers/tax_rates.rb'
84
85
  require 'stripe_mock/request_handlers/checkout_session.rb'
85
86
  require 'stripe_mock/instance'
@@ -20,8 +20,13 @@ describe StripeMock::Instance do
20
20
  "type" => "service"
21
21
  )
22
22
  res, api_key = StripeMock.instance.mock_request('post', '/v1/products', api_key: 'api_key', params: symbol_params)
23
- expect(res.data[:name]).to eq('Symbol Product')
24
- expect(res.data[:type]).to eq('service')
23
+ if StripeMock::Compat.stripe_gte_13?
24
+ expect(JSON.parse(res.body)["name"]).to eq('Symbol Product')
25
+ expect(JSON.parse(res.body)["type"]).to eq('service')
26
+ else
27
+ expect(res.data[:name]).to eq('Symbol Product')
28
+ expect(res.data[:type]).to eq('service')
29
+ end
25
30
  end
26
31
 
27
32
  it "exits gracefully on an unrecognized handler url" do
data/spec/list_spec.rb CHANGED
@@ -149,7 +149,7 @@ describe StripeMock::Data::List do
149
149
  255.times { data << Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token) }
150
150
  list = StripeMock::Data::List.new(data, starting_after: "test_ch_unknown")
151
151
 
152
- expect { list.to_h }.to raise_error
152
+ expect { list.to_h }.to raise_error(RuntimeError, "No such object id: test_ch_unknown")
153
153
  end
154
154
  end
155
155
 
data/spec/server_spec.rb CHANGED
@@ -54,11 +54,20 @@ describe 'StripeMock Server', :mock_server => true do
54
54
 
55
55
 
56
56
  it "returns a response with symbolized hash keys" do
57
- stripe_helper.create_plan(id: 'x', product: product.id)
58
- response, api_key = StripeMock.redirect_to_mock_server('get', '/v1/plans/x', api_key: 'xxx')
59
- response.data.keys.each {|k| expect(k).to be_a(Symbol) }
57
+ unless StripeMock::Compat.stripe_gte_13?
58
+ stripe_helper.create_plan(id: 'x', product: product.id)
59
+ response, api_key = StripeMock.redirect_to_mock_server('get', '/v1/plans/x', api_key: 'xxx')
60
+ response.data.keys.each {|k| expect(k).to be_a(Symbol) }
61
+ end
60
62
  end
61
63
 
64
+ it "returns a Net::HttpResponse" do
65
+ if StripeMock::Compat.stripe_gte_13?
66
+ stripe_helper.create_plan(id: 'x', product: product.id)
67
+ response, api_key = StripeMock.redirect_to_mock_server('get', '/v1/plans/x', 'https://api.stripe.com', {}, {}, 'normal')
68
+ expect(response).to be_a(Net::HTTPResponse)
69
+ end
70
+ end
62
71
 
63
72
  it "can toggle debug" do
64
73
  StripeMock.toggle_debug(true)
@@ -55,7 +55,7 @@ shared_examples 'Account API' do
55
55
  account.tos_acceptance.date = nil
56
56
  expect {
57
57
  account.save
58
- }.to raise_error
58
+ }.to raise_error(Stripe::InvalidRequestError, /Invalid integer/)
59
59
  end
60
60
 
61
61
  context 'with tos acceptance date' do
@@ -11,7 +11,6 @@ shared_examples "Checkout Session API" do
11
11
  session = Stripe::Checkout::Session.create(
12
12
  payment_method_types: ["card"],
13
13
  line_items: line_items,
14
- cancel_url: "https://example.com/cancel",
15
14
  success_url: "https://example.com/success"
16
15
  )
17
16
 
@@ -28,7 +27,6 @@ shared_examples "Checkout Session API" do
28
27
  session = Stripe::Checkout::Session.create(
29
28
  customer: "customer_id",
30
29
  success_url: "localhost/nada",
31
- cancel_url: "localhost/nada",
32
30
  payment_method_types: ["card"],
33
31
  )
34
32
  end.to raise_error(Stripe::InvalidRequestError, /line_items/i)
@@ -40,7 +38,6 @@ shared_examples "Checkout Session API" do
40
38
  session = Stripe::Checkout::Session.create(
41
39
  mode: "setup",
42
40
  payment_method_types: ["card"],
43
- cancel_url: "https://example.com/cancel",
44
41
  success_url: "https://example.com/success"
45
42
  )
46
43
 
@@ -55,7 +52,6 @@ shared_examples "Checkout Session API" do
55
52
  session = Stripe::Checkout::Session.create(
56
53
  customer: "customer_id",
57
54
  success_url: "localhost/nada",
58
- cancel_url: "localhost/nada",
59
55
  payment_method_types: ["card"],
60
56
  mode: "subscription",
61
57
  )
@@ -86,7 +82,6 @@ shared_examples "Checkout Session API" do
86
82
  it "can expand setup_intent" do
87
83
  initial_session = Stripe::Checkout::Session.create(
88
84
  mode: "setup",
89
- cancel_url: "https://example.com",
90
85
  success_url: "https://example.com",
91
86
  payment_method_types: ["card"]
92
87
  )
@@ -24,7 +24,7 @@ shared_examples 'Customer API' do
24
24
  expect(customer.default_source).to_not be_nil
25
25
  expect(customer.default_source).to eq customer.sources.data.first.id
26
26
 
27
- expect { customer.source }.to raise_error
27
+ expect { customer.source }.to raise_error(NoMethodError)
28
28
  end
29
29
 
30
30
  it "creates a stripe customer with a default payment method" do
@@ -90,9 +90,9 @@ shared_examples 'PaymentIntent API' do
90
90
  amount: 100, currency: 'usd', confirm: true
91
91
  )
92
92
  expect(payment_intent.status).to eq('succeeded')
93
- expect(payment_intent.charges.data.size).to eq(1)
94
- expect(payment_intent.charges.data.first.object).to eq('charge')
95
- balance_txn = payment_intent.charges.data.first.balance_transaction
93
+ charge = Stripe::Charge.retrieve(payment_intent.latest_charge)
94
+ expect(charge.object).to eq('charge')
95
+ balance_txn = charge.balance_transaction
96
96
  expect(balance_txn).to match(/^test_txn/)
97
97
  expect(Stripe::BalanceTransaction.retrieve(balance_txn).id).to eq(balance_txn)
98
98
  end
@@ -104,7 +104,7 @@ shared_examples 'PaymentIntent API' do
104
104
  customer: customer,
105
105
  payment_method: customer.sources.first
106
106
 
107
- charge = payment_intent.charges.data.first
107
+ charge = Stripe::Charge.retrieve(payment_intent.latest_charge)
108
108
  expect(charge.amount).to eq(payment_intent.amount)
109
109
  expect(charge.payment_intent).to eq(payment_intent.id)
110
110
  expect(charge.description).to be_nil
@@ -121,17 +121,17 @@ shared_examples 'PaymentIntent API' do
121
121
  amount: 100, currency: "usd", confirm: true, payment_method: "test_pm_1"
122
122
  )
123
123
  expect(payment_intent.status).to eq("succeeded")
124
- expect(payment_intent.charges.data.size).to eq(1)
125
- expect(payment_intent.charges.data.first.object).to eq("charge")
126
- expect(payment_intent.charges.data.first.payment_method).to eq("test_pm_1")
124
+ charge = Stripe::Charge.retrieve(payment_intent.latest_charge)
125
+ expect(charge.object).to eq("charge")
126
+ expect(charge.payment_method).to eq("test_pm_1")
127
127
  end
128
128
 
129
129
  it "confirms a stripe payment_intent" do
130
130
  payment_intent = Stripe::PaymentIntent.create(amount: 100, currency: "usd")
131
131
  confirmed_payment_intent = payment_intent.confirm()
132
132
  expect(confirmed_payment_intent.status).to eq("succeeded")
133
- expect(confirmed_payment_intent.charges.data.size).to eq(1)
134
- expect(confirmed_payment_intent.charges.data.first.object).to eq('charge')
133
+ charge = Stripe::Charge.retrieve(confirmed_payment_intent.latest_charge)
134
+ expect(charge.object).to eq('charge')
135
135
  end
136
136
 
137
137
  it 'creates a charge for a confirmed stripe payment_intent' do
@@ -141,7 +141,7 @@ shared_examples 'PaymentIntent API' do
141
141
  payment_method: customer.sources.first
142
142
 
143
143
  confirmed_payment_intent = payment_intent.confirm
144
- charge = confirmed_payment_intent.charges.data.first
144
+ charge = Stripe::Charge.retrieve(payment_intent.latest_charge)
145
145
  expect(charge.amount).to eq(confirmed_payment_intent.amount)
146
146
  expect(charge.payment_intent).to eq(confirmed_payment_intent.id)
147
147
  expect(charge.description).to be_nil
@@ -157,8 +157,8 @@ shared_examples 'PaymentIntent API' do
157
157
  payment_intent = Stripe::PaymentIntent.create(amount: 100, currency: "usd")
158
158
  confirmed_payment_intent = payment_intent.capture()
159
159
  expect(confirmed_payment_intent.status).to eq("succeeded")
160
- expect(confirmed_payment_intent.charges.data.size).to eq(1)
161
- expect(confirmed_payment_intent.charges.data.first.object).to eq('charge')
160
+ charge = Stripe::Charge.retrieve(confirmed_payment_intent.latest_charge)
161
+ expect(charge.object).to eq('charge')
162
162
  end
163
163
 
164
164
  it 'creates a charge for a captured stripe payment_intent' do
@@ -170,7 +170,7 @@ shared_examples 'PaymentIntent API' do
170
170
  capture_method: 'manual'
171
171
 
172
172
  captured_payment_intent = payment_intent.capture
173
- charge = captured_payment_intent.charges.data.first
173
+ charge = Stripe::Charge.retrieve(captured_payment_intent.latest_charge)
174
174
  expect(charge.amount).to eq(captured_payment_intent.amount)
175
175
  expect(charge.payment_intent).to eq(captured_payment_intent.id)
176
176
  expect(charge.description).to be_nil
@@ -450,5 +450,15 @@ shared_examples 'PaymentMethod API' do
450
450
  end.to raise_error(Stripe::InvalidRequestError)
451
451
  end
452
452
  end
453
+
454
+ context 'with us_bank_account' do
455
+ let(:payment_method) do
456
+ Stripe::PaymentMethod.create(type: 'us_bank_account')
457
+ end
458
+
459
+ it 'works' do
460
+ expect(payment_method.type).to eq('us_bank_account')
461
+ end
462
+ end
453
463
  end
454
464
  end
@@ -3,10 +3,10 @@ require 'spec_helper'
3
3
  shared_examples 'Payout API' do
4
4
 
5
5
  it "creates a stripe payout" do
6
- payout = Stripe::Payout.create(amount: "100", currency: "usd")
6
+ payout = Stripe::Payout.create(amount: 100, currency: "usd")
7
7
 
8
8
  expect(payout.id).to match(/^test_po/)
9
- expect(payout.amount).to eq('100')
9
+ expect(payout.amount).to eq(100)
10
10
  expect(payout.currency).to eq('usd')
11
11
  expect(payout.metadata.to_hash).to eq({})
12
12
  end
@@ -14,7 +14,7 @@ shared_examples 'Payout API' do
14
14
  describe "listing payouts" do
15
15
  before do
16
16
  3.times do
17
- Stripe::Payout.create(amount: "100", currency: "usd")
17
+ Stripe::Payout.create(amount: 100, currency: "usd")
18
18
  end
19
19
  end
20
20
 
@@ -28,7 +28,7 @@ shared_examples 'Payout API' do
28
28
  end
29
29
 
30
30
  it "retrieves a stripe payout" do
31
- original = Stripe::Payout.create(amount: "100", currency: "usd")
31
+ original = Stripe::Payout.create(amount: 100, currency: "usd")
32
32
  payout = Stripe::Payout.retrieve(original.id)
33
33
 
34
34
  expect(payout.id).to eq(original.id)
@@ -37,6 +37,25 @@ shared_examples 'Payout API' do
37
37
  expect(payout.metadata.to_hash).to eq(original.metadata.to_hash)
38
38
  end
39
39
 
40
+ it "updates a stripe payout using method" do
41
+ original = Stripe::Payout.create(amount: 100, currency: "usd")
42
+ updated = Stripe::Payout.update(original.id, amount: 1337)
43
+ payout = Stripe::Payout.retrieve(original.id)
44
+ expect(payout.amount).to eq(1337)
45
+ end
46
+
47
+ it "updates a stripe payout object" do
48
+ original = Stripe::Payout.create(amount: 100, currency: "usd")
49
+ payout = Stripe::Payout.retrieve(original.id)
50
+
51
+ expect(payout.id).to eq(original.id)
52
+
53
+ payout.amount = 1337
54
+ payout.save
55
+ payout = Stripe::Payout.retrieve(original.id)
56
+ expect(payout.amount).to eq(1337)
57
+ end
58
+
40
59
  it "cannot retrieve a payout that doesn't exist" do
41
60
  expect { Stripe::Payout.retrieve('nope') }.to raise_error {|e|
42
61
  expect(e).to be_a Stripe::InvalidRequestError
@@ -46,17 +65,18 @@ shared_examples 'Payout API' do
46
65
  end
47
66
 
48
67
  it 'when amount is not integer', live: true do
49
- expect { Stripe::Payout.create(amount: '400.2',
68
+ expect { Stripe::Payout.create(amount: 400.2,
50
69
  currency: 'usd',
51
70
  description: 'Payout for test@example.com') }.to raise_error { |e|
52
71
  expect(e).to be_a Stripe::InvalidRequestError
53
72
  expect(e.param).to eq('amount')
73
+ expect(e.message).to match(/^Invalid.*integer/)
54
74
  expect(e.http_status).to eq(400)
55
75
  }
56
76
  end
57
77
 
58
78
  it 'when amount is negative', live: true do
59
- expect { Stripe::Payout.create(amount: '-400',
79
+ expect { Stripe::Payout.create(amount: -400,
60
80
  currency: 'usd',
61
81
  description: 'Payout for test@example.com') }.to raise_error { |e|
62
82
  expect(e).to be_a Stripe::InvalidRequestError
@@ -192,15 +192,18 @@ shared_examples "Product API" do
192
192
  :attributes,
193
193
  :caption,
194
194
  :created,
195
+ :default_price,
195
196
  :deactivate_on,
196
197
  :description,
197
198
  :images,
199
+ :marketing_features,
198
200
  :livemode,
199
201
  :metadata,
200
202
  :name,
201
203
  :package_dimensions,
202
204
  :shippable,
203
205
  :statement_descriptor,
206
+ :tax_code,
204
207
  :type,
205
208
  :unit_label,
206
209
  :updated,
@@ -80,6 +80,10 @@ shared_examples 'SetupIntent API' do
80
80
 
81
81
  updated = Stripe::SetupIntent.retrieve(original.id)
82
82
 
83
- expect(updated.metadata[:foo]).to eq(:bar)
83
+ if StripeMock::Compat.stripe_gte_13?
84
+ expect(updated.metadata[:foo]).to eq("bar")
85
+ else
86
+ expect(updated.metadata[:foo]).to eq(:bar)
87
+ end
84
88
  end
85
89
  end
@@ -203,7 +203,7 @@ shared_examples 'Customer Subscriptions with plans' do
203
203
 
204
204
  expect {
205
205
  Stripe::Subscription.create(plan: plan.id, customer: customer.id, promotion_code: promotion_code.id)
206
- }.not_to raise_error(Stripe::InvalidRequestError)
206
+ }.not_to raise_error
207
207
  end
208
208
 
209
209
  it "does not permit both coupon and promotion code" do