stripe-ruby-mock 2.3.1 → 2.4.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/stripe_mock.rb +2 -0
  4. data/lib/stripe_mock/api/errors.rb +2 -1
  5. data/lib/stripe_mock/api/instance.rb +10 -0
  6. data/lib/stripe_mock/api/webhooks.rb +3 -0
  7. data/lib/stripe_mock/data.rb +196 -17
  8. data/lib/stripe_mock/instance.rb +14 -3
  9. data/lib/stripe_mock/request_handlers/accounts.rb +7 -0
  10. data/lib/stripe_mock/request_handlers/charges.rb +24 -21
  11. data/lib/stripe_mock/request_handlers/country_spec.rb +22 -0
  12. data/lib/stripe_mock/request_handlers/customers.rb +3 -3
  13. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +5 -2
  14. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +2 -1
  15. data/lib/stripe_mock/request_handlers/recipients.rb +12 -0
  16. data/lib/stripe_mock/request_handlers/refunds.rb +88 -0
  17. data/lib/stripe_mock/request_handlers/subscriptions.rb +7 -6
  18. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +5 -0
  19. data/lib/stripe_mock/test_strategies/base.rb +7 -4
  20. data/lib/stripe_mock/version.rb +1 -1
  21. data/lib/stripe_mock/webhook_fixtures/account.external_account.created.json +27 -0
  22. data/lib/stripe_mock/webhook_fixtures/account.external_account.deleted.json +27 -0
  23. data/lib/stripe_mock/webhook_fixtures/account.external_account.updated.json +27 -0
  24. data/spec/api/instance_spec.rb +30 -0
  25. data/spec/list_spec.rb +11 -7
  26. data/spec/server_spec.rb +1 -1
  27. data/spec/shared_stripe_examples/account_examples.rb +11 -0
  28. data/spec/shared_stripe_examples/card_examples.rb +13 -2
  29. data/spec/shared_stripe_examples/card_token_examples.rb +1 -0
  30. data/spec/shared_stripe_examples/charge_examples.rb +64 -15
  31. data/spec/shared_stripe_examples/country_specs_examples.rb +18 -0
  32. data/spec/shared_stripe_examples/customer_examples.rb +38 -0
  33. data/spec/shared_stripe_examples/error_mock_examples.rb +12 -2
  34. data/spec/shared_stripe_examples/plan_examples.rb +11 -0
  35. data/spec/shared_stripe_examples/recipient_examples.rb +7 -1
  36. data/spec/shared_stripe_examples/refund_examples.rb +447 -84
  37. data/spec/shared_stripe_examples/subscription_examples.rb +15 -0
  38. data/spec/support/stripe_examples.rb +1 -0
  39. metadata +12 -3
@@ -34,14 +34,16 @@ module StripeMock
34
34
  include StripeMock::RequestHandlers::InvoiceItems
35
35
  include StripeMock::RequestHandlers::Orders
36
36
  include StripeMock::RequestHandlers::Plans
37
+ include StripeMock::RequestHandlers::Refunds
37
38
  include StripeMock::RequestHandlers::Recipients
38
39
  include StripeMock::RequestHandlers::Transfers
39
40
  include StripeMock::RequestHandlers::Tokens
41
+ include StripeMock::RequestHandlers::CountrySpec
40
42
 
41
43
 
42
44
  attr_reader :accounts, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
43
45
  :disputes, :events, :invoices, :invoice_items, :orders, :plans, :recipients,
44
- :transfers, :subscriptions
46
+ :refunds, :transfers, :subscriptions, :country_spec
45
47
 
46
48
  attr_accessor :error_queue, :debug
47
49
 
@@ -60,8 +62,10 @@ module StripeMock
60
62
  @orders = {}
61
63
  @plans = {}
62
64
  @recipients = {}
65
+ @refunds = {}
63
66
  @transfers = {}
64
67
  @subscriptions = {}
68
+ @country_spec = {}
65
69
 
66
70
  @debug = false
67
71
  @error_queue = ErrorQueue.new
@@ -124,9 +128,16 @@ module StripeMock
124
128
  "#{StripeMock.global_id_prefix}#{prefix}_#{@id_counter += 1}"
125
129
  end
126
130
 
127
- def new_balance_transaction(prefix)
131
+ def new_balance_transaction(prefix, params = {})
128
132
  # balance transaction ids must be strings
129
- "#{StripeMock.global_id_prefix}#{prefix}_#{@balance_transaction_counter += 1}"
133
+ id = "#{StripeMock.global_id_prefix}#{prefix}_#{@balance_transaction_counter += 1}"
134
+ amount = params[:amount]
135
+ unless amount.nil?
136
+ # Fee calculation
137
+ params[:fee] ||= (30 + (amount.abs * 0.029).ceil) * (amount > 0 ? 1 : -1)
138
+ end
139
+ @balance_transactions[id] = Data.mock_balance_transaction(params.merge(id: id))
140
+ id
130
141
  end
131
142
 
132
143
  def symbolize_names(hash)
@@ -8,6 +8,7 @@ module StripeMock
8
8
  klass.add_handler 'get /v1/accounts/(.*)', :get_account
9
9
  klass.add_handler 'post /v1/accounts/(.*)', :update_account
10
10
  klass.add_handler 'get /v1/accounts', :list_accounts
11
+ klass.add_handler 'post /oauth/deauthorize',:deauthorize
11
12
  end
12
13
 
13
14
  def new_account(route, method_url, params, headers)
@@ -34,6 +35,12 @@ module StripeMock
34
35
  Data.mock_list_object(accounts.values, params)
35
36
  end
36
37
 
38
+ def deauthorize(route, method_url, params, headers)
39
+ init_account
40
+ route =~ method_url
41
+ Stripe::StripeObject.construct_from(:stripe_user_id => params[:stripe_user_id])
42
+ end
43
+
37
44
  private
38
45
 
39
46
  def init_account
@@ -8,7 +8,7 @@ module StripeMock
8
8
  klass.add_handler 'get /v1/charges/(.*)', :get_charge
9
9
  klass.add_handler 'post /v1/charges/(.*)/capture', :capture_charge
10
10
  klass.add_handler 'post /v1/charges/(.*)/refund', :refund_charge
11
- klass.add_handler 'post /v1/charges/(.*)/refunds', :create_refund
11
+ klass.add_handler 'post /v1/charges/(.*)/refunds', :refund_charge
12
12
  klass.add_handler 'post /v1/charges/(.*)', :update_charge
13
13
  end
14
14
 
@@ -28,7 +28,7 @@ module StripeMock
28
28
  if params[:customer]
29
29
  params[:source] = get_card(customers[params[:customer]], params[:source])
30
30
  else
31
- params[:source] = get_card_by_token(params[:source])
31
+ params[:source] = get_card_or_bank_by_token(params[:source])
32
32
  end
33
33
  elsif params[:source][:id]
34
34
  raise Stripe::InvalidRequestError.new("Invalid token id: #{params[:source]}", 'card', 400)
@@ -41,8 +41,20 @@ module StripeMock
41
41
  end
42
42
 
43
43
  ensure_required_params(params)
44
+ bal_trans_params = { amount: params[:amount], source: params[:source] }
44
45
 
45
- charges[id] = Data.mock_charge(params.merge :id => id, :balance_transaction => new_balance_transaction('txn'))
46
+ balance_transaction_id = new_balance_transaction('txn', bal_trans_params)
47
+
48
+ charges[id] = Data.mock_charge(
49
+ params.merge :id => id,
50
+ :balance_transaction => balance_transaction_id)
51
+
52
+ if params[:expand] == ['balance_transaction']
53
+ charges[id][:balance_transaction] =
54
+ balance_transactions[balance_transaction_id]
55
+ end
56
+
57
+ charges[id]
46
58
  end
47
59
 
48
60
  def update_charge(route, method_url, params, headers)
@@ -74,7 +86,8 @@ module StripeMock
74
86
 
75
87
  def get_charge(route, method_url, params, headers)
76
88
  route =~ method_url
77
- assert_existence :charge, $1, charges[$1]
89
+ charge_id = $1 || params[:charge]
90
+ assert_existence :charge, charge_id, charges[charge_id]
78
91
  end
79
92
 
80
93
  def capture_charge(route, method_url, params, headers)
@@ -101,24 +114,12 @@ module StripeMock
101
114
  def refund_charge(route, method_url, params, headers)
102
115
  charge = get_charge(route, method_url, params, headers)
103
116
 
104
- refund = Data.mock_refund params.merge(
105
- :balance_transaction => new_balance_transaction('txn'),
106
- :id => new_id('re')
107
- )
108
- add_refund_to_charge(refund, charge)
109
- charge
110
- end
111
-
112
- def create_refund(route, method_url, params, headers)
113
- charge = get_charge(route, method_url, params, headers)
114
-
115
- refund = Data.mock_refund params.merge(
116
- :balance_transaction => new_balance_transaction('txn'),
117
- :id => new_id('re'),
118
- :charge => charge[:id]
117
+ new_refund(
118
+ route,
119
+ method_url,
120
+ params.merge(:charge => charge[:id]),
121
+ headers
119
122
  )
120
- add_refund_to_charge(refund, charge)
121
- refund
122
123
  end
123
124
 
124
125
  private
@@ -132,6 +133,8 @@ module StripeMock
132
133
  raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', 400)
133
134
  elsif non_positive_charge_amount?(params)
134
135
  raise Stripe::InvalidRequestError.new('Invalid positive integer', 'amount', 400)
136
+ elsif params[:source].nil? && params[:customer].nil?
137
+ raise Stripe::InvalidRequestError.new('Must provide source or customer.', nil)
135
138
  end
136
139
  end
137
140
 
@@ -0,0 +1,22 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module CountrySpec
4
+
5
+ def CountrySpec.included(klass)
6
+ klass.add_handler 'get /v1/country_specs/(.*)', :retrieve_country_spec
7
+ end
8
+
9
+ def retrieve_country_spec(route, method_url, params, headers)
10
+ route =~ method_url
11
+
12
+ unless ["AT", "AU", "BE", "CA", "DE", "DK", "ES", "FI", "FR", "GB", "IE", "IT", "JP", "LU", "NL", "NO", "SE", "SG", "US"].include?($1)
13
+ raise Stripe::InvalidRequestError.new("#{$1} is not currently supported by Stripe.", $1.to_s)
14
+ end
15
+
16
+ country_spec[$1] ||= Data.mock_country_spec($1)
17
+
18
+ assert_existence :country_spec, $1, country_spec[$1]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -4,9 +4,9 @@ module StripeMock
4
4
 
5
5
  def Customers.included(klass)
6
6
  klass.add_handler 'post /v1/customers', :new_customer
7
- klass.add_handler 'post /v1/customers/(.*)', :update_customer
8
- klass.add_handler 'get /v1/customers/(.*)', :get_customer
9
- klass.add_handler 'delete /v1/customers/(.*)', :delete_customer
7
+ klass.add_handler 'post /v1/customers/([^/]*)', :update_customer
8
+ klass.add_handler 'get /v1/customers/([^/]*)', :get_customer
9
+ klass.add_handler 'delete /v1/customers/([^/]*)', :delete_customer
10
10
  klass.add_handler 'get /v1/customers', :list_customers
11
11
  end
12
12
 
@@ -26,8 +26,11 @@ module StripeMock
26
26
  end
27
27
 
28
28
  def add_subscription_to_customer(cus, sub)
29
- id = new_id('ch')
30
- charges[id] = Data.mock_charge(:id => id, :customer => cus[:id], :amount => sub[:plan][:amount])
29
+ if sub[:trial_end].nil? || sub[:trial_end] == "now"
30
+ id = new_id('ch')
31
+ charges[id] = Data.mock_charge(:id => id, :customer => cus[:id], :amount => sub[:plan][:amount])
32
+ end
33
+
31
34
  if cus[:currency].nil?
32
35
  cus[:currency] = sub[:plan][:currency]
33
36
  elsif cus[:currency] != sub[:plan][:currency]
@@ -35,7 +35,8 @@ module StripeMock
35
35
  end
36
36
 
37
37
  def get_card_or_bank_by_token(token)
38
- @card_tokens[token] || @bank_tokens[token] || raise(Stripe::InvalidRequestError.new("Invalid token id: #{token}", 'tok', 404))
38
+ token_id = token['id'] || token
39
+ @card_tokens[token_id] || @bank_tokens[token_id] || raise(Stripe::InvalidRequestError.new("Invalid token id: #{token_id}", 'tok', 404))
39
40
  end
40
41
 
41
42
  end
@@ -12,6 +12,18 @@ module StripeMock
12
12
  params[:id] ||= new_id('rp')
13
13
  cards = []
14
14
 
15
+ if params[:name].nil?
16
+ raise StripeMock::StripeMockError.new("Missing required parameter name for recipients.")
17
+ end
18
+
19
+ if params[:type].nil?
20
+ raise StripeMock::StripeMockError.new("Missing required parameter type for recipients.")
21
+ end
22
+
23
+ unless %w(individual corporation).include?(params[:type])
24
+ raise StripeMock::StripeMockError.new("Type must be either individual or corporation..")
25
+ end
26
+
15
27
  if params[:bank_account]
16
28
  params[:active_account] = get_bank_by_token(params.delete(:bank_account))
17
29
  end
@@ -0,0 +1,88 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Refunds
4
+
5
+ def Refunds.included(klass)
6
+ klass.add_handler 'post /v1/refunds', :new_refund
7
+ klass.add_handler 'get /v1/refunds', :get_refunds
8
+ klass.add_handler 'get /v1/refunds/(.*)', :get_refund
9
+ klass.add_handler 'post /v1/refunds/(.*)', :update_refund
10
+ end
11
+
12
+ def new_refund(route, method_url, params, headers)
13
+ if params[:idempotency_key] && refunds.any?
14
+ original_refund = refunds.values.find { |c| c[:idempotency_key] == params[:idempotency_key]}
15
+ return refunds[original_refund[:id]] if original_refund
16
+ end
17
+
18
+ charge = get_charge(route, method_url, params, headers)
19
+ params[:amount] ||= charge[:amount]
20
+ id = new_id('re')
21
+ bal_trans_params = {
22
+ amount: params[:amount] * -1,
23
+ source: id,
24
+ type: 'refund'
25
+ }
26
+ balance_transaction_id = new_balance_transaction('txn', bal_trans_params)
27
+ refund = Data.mock_refund params.merge(
28
+ :balance_transaction => balance_transaction_id,
29
+ :id => id,
30
+ :charge => charge[:id],
31
+ )
32
+ add_refund_to_charge(refund, charge)
33
+ refunds[id] = refund
34
+
35
+ if params[:expand] == ['balance_transaction']
36
+ refunds[id][:balance_transaction] =
37
+ balance_transactions[balance_transaction_id]
38
+ end
39
+ refund
40
+ end
41
+
42
+ def update_refund(route, method_url, params, headers)
43
+ route =~ method_url
44
+ id = $1
45
+
46
+ refund = assert_existence :refund, id, refunds[id]
47
+ allowed = allowed_refund_params(params)
48
+ disallowed = params.keys - allowed
49
+ if disallowed.count > 0
50
+ raise Stripe::InvalidRequestError.new("Received unknown parameters: #{disallowed.join(', ')}" , '', 400)
51
+ end
52
+
53
+ refunds[id] = Util.rmerge(refund, params)
54
+ end
55
+
56
+ def get_refunds(route, method_url, params, headers)
57
+ params[:offset] ||= 0
58
+ params[:limit] ||= 10
59
+
60
+ clone = refunds.clone
61
+
62
+ Data.mock_list_object(clone.values, params)
63
+ end
64
+
65
+ def get_refund(route, method_url, params, headers)
66
+ route =~ method_url
67
+ refund_id = $1 || params[:refund]
68
+ assert_existence :refund, refund_id, refunds[refund_id]
69
+ end
70
+
71
+ private
72
+
73
+ def ensure_refund_required_params(params)
74
+ if non_integer_charge_amount?(params)
75
+ raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', 400)
76
+ elsif non_positive_charge_amount?(params)
77
+ raise Stripe::InvalidRequestError.new('Invalid positive integer', 'amount', 400)
78
+ elsif params[:charge].nil?
79
+ raise Stripe::InvalidRequestError.new('Must provide the identifier of the charge to refund.', nil)
80
+ end
81
+ end
82
+
83
+ def allowed_refund_params(params)
84
+ [:metadata]
85
+ end
86
+ end
87
+ end
88
+ end
@@ -9,11 +9,11 @@ module StripeMock
9
9
  klass.add_handler 'post /v1/subscriptions/(.*)', :update_subscription
10
10
  klass.add_handler 'delete /v1/subscriptions/(.*)', :cancel_subscription
11
11
 
12
- klass.add_handler 'post /v1/customers/(.*)/subscriptions', :create_customer_subscription
13
- klass.add_handler 'get /v1/customers/(.*)/subscriptions/(.*)', :retrieve_customer_subscription
14
- klass.add_handler 'get /v1/customers/(.*)/subscriptions', :retrieve_customer_subscriptions
15
- klass.add_handler 'post /v1/customers/(.*)subscriptions/(.*)', :update_subscription
16
- klass.add_handler 'delete /v1/customers/(.*)/subscriptions/(.*)', :cancel_subscription
12
+ klass.add_handler 'post /v1/customers/(.*)/subscription(?:s)?', :create_customer_subscription
13
+ klass.add_handler 'get /v1/customers/(.*)/subscription(?:s)?/(.*)', :retrieve_customer_subscription
14
+ klass.add_handler 'get /v1/customers/(.*)/subscription(?:s)?', :retrieve_customer_subscriptions
15
+ klass.add_handler 'post /v1/customers/(.*)subscription(?:s)?/(.*)', :update_subscription
16
+ klass.add_handler 'delete /v1/customers/(.*)/subscription(?:s)?/(.*)', :cancel_subscription
17
17
  end
18
18
 
19
19
  def retrieve_customer_subscription(route, method_url, params, headers)
@@ -158,9 +158,10 @@ module StripeMock
158
158
  # coupon = assert_existence :coupon, coupon_id, coupons[coupon_id]
159
159
 
160
160
  coupon = coupons[coupon_id]
161
-
162
161
  if coupon
163
162
  subscription[:discount] = Stripe::Util.convert_to_stripe_object({ coupon: coupon }, {})
163
+ elsif coupon_id == ""
164
+ subscription[:discount] = Stripe::Util.convert_to_stripe_object(nil, {})
164
165
  else
165
166
  raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', 400)
166
167
  end
@@ -8,9 +8,14 @@ module StripeMock
8
8
  @base_strategy.create_plan_params.keys.each do |name|
9
9
  raise Stripe::InvalidRequestError.new("Missing required param: #{name}.", name) if params[name].nil?
10
10
  end
11
+
11
12
  if plans[ params[:id] ]
12
13
  raise Stripe::InvalidRequestError.new("Plan already exists.", :id)
13
14
  end
15
+
16
+ unless params[:amount].integer?
17
+ raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", :amount)
18
+ end
14
19
  end
15
20
 
16
21
  end
@@ -3,17 +3,18 @@ module StripeMock
3
3
  class Base
4
4
 
5
5
  def create_plan_params(params={})
6
+ currency = params[:currency] || 'usd'
6
7
  {
7
8
  :id => 'stripe_mock_default_plan_id',
8
9
  :name => 'StripeMock Default Plan ID',
9
10
  :amount => 1337,
10
- :currency => 'usd',
11
+ :currency => currency,
11
12
  :interval => 'month'
12
13
  }.merge(params)
13
14
  end
14
15
 
15
16
  def generate_card_token(card_params={})
16
- card_data = { :number => "4242424242424242", :exp_month => 9, :exp_year => 2018, :cvc => "999" }
17
+ card_data = { :number => "4242424242424242", :exp_month => 9, :exp_year => 2018, :cvc => "999", :tokenization_method => nil }
17
18
  card = StripeMock::Util.card_merge(card_data, card_params)
18
19
  card[:fingerprint] = StripeMock::Util.fingerprint(card[:number]) if StripeMock.state == 'local'
19
20
 
@@ -22,9 +23,10 @@ module StripeMock
22
23
  end
23
24
 
24
25
  def generate_bank_token(bank_account_params={})
26
+ currency = bank_account_params[:currency] || 'usd'
25
27
  bank_account = {
26
28
  :country => "US",
27
- :currency => "usd",
29
+ :currency => currency,
28
30
  :account_holder_name => "Jane Austen",
29
31
  :account_holder_type => "individual",
30
32
  :routing_number => "110000000",
@@ -37,10 +39,11 @@ module StripeMock
37
39
  end
38
40
 
39
41
  def create_coupon_params(params = {})
42
+ currency = params[:currency] || 'usd'
40
43
  {
41
44
  id: '10BUCKS',
42
45
  amount_off: 1000,
43
- currency: 'usd',
46
+ currency: currency,
44
47
  max_redemptions: 100,
45
48
  metadata: {
46
49
  created_by: 'admin_acct_1'
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "2.3.1"
3
+ VERSION = "2.4.0"
4
4
  end
@@ -0,0 +1,27 @@
1
+ {
2
+ "created":1326853478,
3
+ "livemode":false,
4
+ "id":"evt_00000000000000",
5
+ "type":"account.external_account.created",
6
+ "object":"event",
7
+ "data":{
8
+ "object":{
9
+ "id":"ba_00000000000000",
10
+ "object":"bank_account",
11
+ "account":"acct_00000000000000",
12
+ "account_holder_name":"Jane Austen",
13
+ "account_holder_type":"individual",
14
+ "bank_name":"STRIPE TEST BANK",
15
+ "country":"US",
16
+ "currency":"eur",
17
+ "default_for_currency":false,
18
+ "fingerprint":"efGCBmiwp56O1lsN",
19
+ "last4":"6789",
20
+ "metadata":{
21
+
22
+ },
23
+ "routing_number":"110000000",
24
+ "status":"new"
25
+ }
26
+ }
27
+ }