Skip to content

Commit 6ec882b

Browse files
Merge branch 'master' into f/add-missing-decline-codes
2 parents 4c1aa49 + d12621d commit 6ec882b

38 files changed

+466
-264
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
# REQUEST: Looking for More Core Contributors
88

9-
This gem has unexpectedly grown in popularity and I've gotten pretty busy, so I'm currently looking for more core contributors to help me out. If you're interested, there is only one requirement: submit a significant enough pull request and have it merged into master (many of you have already done this). Afterwards, ping me in [chat](https://gitter.im/rebelidealist/stripe-ruby-mock) and I will add you as a collaborator.
9+
This gem has unexpectedly grown in popularity and I've gotten pretty busy, so I'm currently looking for more core contributors to help me out. If you're interested, there is only one requirement: submit a significant enough pull request and have it merged into master (many of you have already done this). Afterwards, ping [@gilbert](https://gitter.im/gilbert) in [chat](https://gitter.im/rebelidealist/stripe-ruby-mock) and I will add you as a collaborator.
1010

1111
## Install
1212

1313
In your gemfile:
1414

15-
gem 'stripe-ruby-mock', '~> 2.5.8', :require => 'stripe_mock'
15+
gem 'stripe-ruby-mock', '~> 3.0.0', :require => 'stripe_mock'
1616

1717
## Features
1818

@@ -23,12 +23,12 @@ In your gemfile:
2323

2424
### Requirements
2525

26-
* ruby >= 2.0.0
27-
* stripe >= 2.0.3
26+
* ruby >= 2.4.0
27+
* stripe >= 5.0.0
2828

2929
### Specifications
3030

31-
**STRIPE API TARGET VERSION:** 2017-06-05 (master)
31+
**STRIPE API TARGET VERSION:** 2019-08-20 (master) - we try, but some features are not implemented yet.
3232

3333
Older API version branches:
3434

@@ -141,7 +141,7 @@ end
141141
```
142142

143143
## Mocking Card Errors
144-
144+
** Ensure you start StripeMock in a before filter `StripeMock.start`
145145
Tired of manually inputting fake credit card numbers to test against errors? Tire no more!
146146

147147
```ruby
@@ -176,7 +176,7 @@ StripeMock.prepare_card_error(:incorrect_zip)
176176
You can see the details of each error in [lib/stripe_mock/api/errors.rb](lib/stripe_mock/api/errors.rb)
177177

178178
### Specifying Card Errors
179-
179+
** Ensure you start StripeMock in a before filter `StripeMock.start`
180180
By default, `prepare_card_error` only triggers for `:new_charge`, the event that happens when you run `Charge.create`. More explicitly, this is what happens by default:
181181

182182
```ruby
@@ -195,7 +195,7 @@ customer.cards.create
195195
`:new_charge` and `:create_card` are names of methods in the [StripeMock request handlers](lib/stripe_mock/request_handlers). You can also set `StripeMock.toggle_debug(true)` to see the event name for each Stripe request made in your tests.
196196

197197
### Custom Errors
198-
198+
** Ensure you start StripeMock in a before filter `StripeMock.start`
199199
To raise an error on a specific type of request, take a look at the [request handlers folder](lib/stripe_mock/request_handlers/) and pass a method name to `StripeMock.prepare_error`.
200200

201201
If you wanted to raise an error for creating a new customer, for instance, you would do the following:

lib/stripe_mock.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
require 'stripe_mock/request_handlers/ephemeral_key.rb'
7777
require 'stripe_mock/request_handlers/products.rb'
7878
require 'stripe_mock/request_handlers/tax_rates.rb'
79+
require 'stripe_mock/request_handlers/checkout.rb'
7980
require 'stripe_mock/instance'
8081

8182
require 'stripe_mock/test_strategies/base.rb'

lib/stripe_mock/api/errors.rb

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
module StripeMock
2-
32
def self.prepare_error(stripe_error, *handler_names)
43
handler_names.push(:all) if handler_names.count == 0
54

@@ -15,31 +14,33 @@ def self.prepare_error(stripe_error, *handler_names)
1514
def self.prepare_card_error(code, *handler_names)
1615
handler_names.push(:new_charge) if handler_names.count == 0
1716

18-
args = CardErrors.argument_map[code]
19-
raise StripeMockError.new("Unrecognized stripe card error code: #{code}") if args.nil?
20-
self.prepare_error Stripe::CardError.new(*args), *handler_names
17+
error = CardErrors.build_error_for(code)
18+
if error.nil?
19+
raise StripeMockError, "Unrecognized stripe card error code: #{code}"
20+
end
21+
22+
prepare_error error, *handler_names
2123
end
2224

2325
module CardErrors
24-
25-
def self.argument_map
26-
@__map ||= {
27-
incorrect_number: add_json_body(["The card number is incorrect", 'number', 'incorrect_number', http_status: 402]),
28-
invalid_number: add_json_body(["The card number is not a valid credit card number", 'number', 'invalid_number', http_status: 402]),
29-
invalid_expiry_month: add_json_body(["The card's expiration month is invalid", 'exp_month', 'invalid_expiry_month', http_status: 402]),
30-
invalid_expiry_year: add_json_body(["The card's expiration year is invalid", 'exp_year', 'invalid_expiry_year', http_status: 402]),
31-
invalid_cvc: add_json_body(["The card's security code is invalid", 'cvc', 'invalid_cvc', http_status: 402]),
32-
expired_card: add_json_body(["The card has expired", 'exp_month', 'expired_card', http_status: 402]),
33-
incorrect_cvc: add_json_body(["The card's security code is incorrect", 'cvc', 'incorrect_cvc', http_status: 402]),
34-
card_declined: add_json_body(["The card was declined", nil, 'card_declined', http_status: 402]),
35-
missing: add_json_body(["There is no card on a customer that is being charged.", nil, 'missing', http_status: 402]),
36-
processing_error: add_json_body(["An error occurred while processing the card", nil, 'processing_error', http_status: 402]),
37-
card_error: add_json_body(['The card number is not a valid credit card number.', 'number', 'invalid_number', http_status: 402]),
38-
incorrect_zip: add_json_body(['The zip code you supplied failed validation.', 'address_zip', 'incorrect_zip', http_status: 402]),
39-
insufficient_funds: add_json_body(["The card has insufficient funds to complete the purchase.", nil, 'insufficient_funds', http_status: 402]),
40-
lost_card: add_json_body(["The payment has been declined because the card is reported lost.", nil, 'lost_card', http_status: 402]),
41-
stolen_card: add_json_body(["The payment has been declined because the card is reported stolen.", nil, 'stolen_card', http_status: 402])
42-
}
26+
def self.build_error_for(code)
27+
case code
28+
when :incorrect_number then build_card_error('The card number is incorrect', 'number', code: 'incorrect_number', http_status: 402)
29+
when :invalid_number then build_card_error('The card number is not a valid credit card number', 'number', code: 'invalid_number', http_status: 402)
30+
when :invalid_expiry_month then build_card_error("The card's expiration month is invalid", 'exp_month', code: 'invalid_expiry_month', http_status: 402)
31+
when :invalid_expiry_year then build_card_error("The card's expiration year is invalid", 'exp_year', code: 'invalid_expiry_year', http_status: 402)
32+
when :invalid_cvc then build_card_error("The card's security code is invalid", 'cvc', code: 'invalid_cvc', http_status: 402)
33+
when :expired_card then build_card_error('The card has expired', 'exp_month', code: 'expired_card', http_status: 402)
34+
when :incorrect_cvc then build_card_error("The card's security code is incorrect", 'cvc', code: 'incorrect_cvc', http_status: 402)
35+
when :card_declined then build_card_error('The card was declined', nil, code: 'card_declined', http_status: 402)
36+
when :missing then build_card_error('There is no card on a customer that is being charged.', nil, code: 'missing', http_status: 402)
37+
when :processing_error then build_card_error('An error occurred while processing the card', nil, code: 'processing_error', http_status: 402)
38+
when :card_error then build_card_error('The card number is not a valid credit card number.', 'number', code: 'invalid_number', http_status: 402)
39+
when :incorrect_zip then build_card_error('The zip code you supplied failed validation.', 'address_zip', code: 'incorrect_zip', http_status: 402)
40+
when :insufficient_funds then build_card_error('The card has insufficient funds to complete the purchase.', nil, code: 'insufficient_funds', http_status: 402)
41+
when :lost_card then build_card_error('The payment has been declined because the card is reported lost.', nil, code: 'lost_card', http_status: 402)
42+
when :stolen_card then build_card_error('The payment has been declined because the card is reported stolen.', nil, code: 'stolen_card', http_status: 402)
43+
end
4344
end
4445

4546
def self.get_decline_code(code)
@@ -53,16 +54,18 @@ def self.get_decline_code(code)
5354
decline_code_map[code_key]
5455
end
5556

56-
def self.add_json_body(error_values)
57-
error_keys = [:message, :param, :code]
58-
59-
json_hash = Hash[error_keys.zip error_values]
60-
json_hash[:type] = 'card_error'
61-
json_hash[:decline_code] = get_decline_code(json_hash[:code])
57+
def self.build_card_error(message, param, **kwargs)
58+
json_hash = {
59+
message: message,
60+
param: param,
61+
code: kwargs[:code],
62+
type: 'card_error',
63+
decline_code: get_decline_code(kwargs[:code])
64+
}
6265

63-
error_values.last.merge!(json_body: { error: json_hash }, http_body: { error: json_hash })
66+
error_keyword_args = kwargs.merge(json_body: { error: json_hash }, http_body: { error: json_hash }.to_json)
6467

65-
error_values
68+
Stripe::CardError.new(message, param, **error_keyword_args)
6669
end
6770
end
6871
end

lib/stripe_mock/data.rb

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def self.mock_charge(params={})
205205
data: []
206206
},
207207
transfer: nil,
208-
balance_transaction: "txn_2dyYXXP90MN26R",
208+
balance_transaction: params[:balance_transaction] || "txn_2dyYXXP90MN26R",
209209
failure_message: nil,
210210
failure_code: nil,
211211
amount_refunded: 0,
@@ -1215,5 +1215,43 @@ def self.mock_setup_intent(params = {})
12151215
:usage => "off_session"
12161216
}.merge(params)
12171217
end
1218+
1219+
def self.mock_checkout_session(params = {})
1220+
cs_id = params[:id] || "test_cs_default"
1221+
currency = params[:currency] || StripeMock.default_currency
1222+
{
1223+
id: cs_id,
1224+
object: 'checkout.session',
1225+
billing_address_collection: nil,
1226+
cancel_url: 'https://example.com/cancel',
1227+
client_reference_id: nil,
1228+
customer: nil,
1229+
customer_email: nil,
1230+
display_items: [
1231+
{
1232+
amount: 1500,
1233+
currency: currency,
1234+
custom: {
1235+
description: 'Comfortable cotton t-shirt',
1236+
images: nil,
1237+
name: 'T-shirt'
1238+
},
1239+
quantity: 2,
1240+
type: 'custom'
1241+
}
1242+
],
1243+
livemode: false,
1244+
locale: nil,
1245+
mode: nil,
1246+
payment_intent: mock_payment_intent[:id],
1247+
payment_method_types: [
1248+
'card'
1249+
],
1250+
setup_intent: nil,
1251+
submit_type: nil,
1252+
subscription: nil,
1253+
success_url: 'https://example.com/success'
1254+
}.merge(params)
1255+
end
12181256
end
12191257
end

lib/stripe_mock/instance.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ def self.handler_for_method_url(method_url)
4949
include StripeMock::RequestHandlers::Payouts
5050
include StripeMock::RequestHandlers::EphemeralKey
5151
include StripeMock::RequestHandlers::TaxRates
52+
include StripeMock::RequestHandlers::Checkout
5253

5354
attr_reader :accounts, :balance, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
5455
:disputes, :events, :invoices, :invoice_items, :orders, :payment_intents, :payment_methods,
5556
:setup_intents, :plans, :recipients, :refunds, :transfers, :payouts, :subscriptions, :country_spec,
56-
:subscriptions_items, :products, :tax_rates
57+
:subscriptions_items, :products, :tax_rates, :checkout_sessions
5758

5859
attr_accessor :error_queue, :debug, :conversion_rate, :account_balance
5960

@@ -85,6 +86,7 @@ def initialize
8586
@subscriptions_items = {}
8687
@country_spec = {}
8788
@tax_rates = {}
89+
@checkout_sessions = {}
8890

8991
@debug = false
9092
@error_queue = ErrorQueue.new
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module StripeMock
2+
module RequestHandlers
3+
module Checkout
4+
def Checkout.included(klass)
5+
klass.add_handler 'post /v1/checkout/sessions', :new_session
6+
end
7+
8+
def new_session(route, method_url, params, headers)
9+
params[:id] ||= new_id('cs')
10+
11+
checkout_sessions[params[:id]] = Data.mock_checkout_session(params)
12+
end
13+
end
14+
end
15+
end

lib/stripe_mock/request_handlers/payment_intents.rb

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,9 @@ def new_payment_intent(route, method_url, params, headers)
3131
last_payment_error: last_payment_error
3232
)
3333
)
34-
if params[:confirm]
35-
payment_intents[id] = succeeded_payment_intent(payment_intents[id])
36-
end
37-
38-
bal_trans_params = { amount: params[:amount], source: id, application_fee: params[:application_fee] }
39-
balance_transaction_id = new_balance_transaction('txn', bal_trans_params)
4034

41-
if payment_intents[id][:charges][:data].length > 0
42-
payment_intents[id][:charges][:data][0][:balance_transaction] = balance_transaction_id
35+
if params[:confirm] && status == 'succeeded'
36+
payment_intents[id] = succeeded_payment_intent(payment_intents[id])
4337
end
4438

4539
payment_intents[id].clone
@@ -172,8 +166,8 @@ def last_payment_error_generator(code: nil, message: nil, decline_code: nil)
172166

173167
def succeeded_payment_intent(payment_intent)
174168
payment_intent[:status] = 'succeeded'
175-
payment_intent[:charges][:data] << Data.mock_charge
176-
169+
btxn = new_balance_transaction('txn', { source: payment_intent[:id] })
170+
payment_intent[:charges][:data] << Data.mock_charge(balance_transaction: btxn)
177171
payment_intent
178172
end
179173
end

lib/stripe_mock/request_handlers/subscriptions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def create_subscription(route, method_url, params, headers)
102102
customer[:default_source] = new_card[:id]
103103
end
104104

105-
allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start created prorate billing_cycle_anchor billing days_until_due idempotency_key enable_incomplete_payments cancel_at_period_end default_tax_rates)
105+
allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start created prorate billing_cycle_anchor billing days_until_due idempotency_key enable_incomplete_payments cancel_at_period_end default_tax_rates payment_behavior)
106106
unknown_params = params.keys - allowed_params.map(&:to_sym)
107107
if unknown_params.length > 0
108108
raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)

lib/stripe_mock/request_handlers/validators/param_validators.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def missing_plan_amount_message
4949
SUPPORTED_PLAN_INTERVALS = ["month", "year", "week", "day"]
5050

5151
def invalid_plan_interval_message
52-
"Invalid interval: must be one of month, year, week, or day"
52+
"Invalid interval: must be one of day, month, week, or year"
5353
end
5454

5555
SUPPORTED_CURRENCIES = [

lib/stripe_mock/test_strategies/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def create_coupon(params = {})
102102
end
103103

104104
def delete_all_coupons
105-
coupons = Stripe::Coupon.all
105+
coupons = Stripe::Coupon.list
106106
coupons.data.map(&:delete) if coupons.data.count > 0
107107
end
108108

0 commit comments

Comments
 (0)