stripe-ruby-mock 2.5.3 → 2.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e81f8b287a3ea9c2c80e4376f24a61e93dc7c0e
4
- data.tar.gz: b8da1c4bfe60eacb520828cf2ea86341bff536ac
3
+ metadata.gz: 771c4e4adbc92b37176d94b8f91fb1f2bef740ba
4
+ data.tar.gz: 86c21735586588ea3aabc958d3eb93dda6dbc7ec
5
5
  SHA512:
6
- metadata.gz: 5a8fc8faa377c537d8c67893b1d71b65ed21e241827e4a391ca73fbc46333a66e6fb7bfb011e9f83a47d7019f6a75bdc738c04e42dc7e78a5b3ef7d1d46349e2
7
- data.tar.gz: 028228088b4f8848c7fadae70fdcaf10a939975e08cad0b2efb45547f172ad0e79c7b79a7ff8d56687d41fba09311812c1240a9dffdebb6d0073e1a09872ff72
6
+ metadata.gz: 0c747fed9cf7824d59fdb1be3ec1b399beabd69d54d08101c1c46d96792fe400e4d7b8c1aa6a816c981d58d902a3fdf46c6edff21bd280a07615799384a4a82f
7
+ data.tar.gz: 68b2ab17e0f504f783bd8c5a20893ec89bee491a29cac16a824d8cdb45e48f7a2a34e307b153feb7fe58662ee661d2732c4d838391cf23497ea20fe0a90393a5
data/README.md CHANGED
@@ -12,7 +12,7 @@ This gem has unexpectedly grown in popularity and I've gotten pretty busy, so I'
12
12
 
13
13
  In your gemfile:
14
14
 
15
- gem 'stripe-ruby-mock', '~> 2.5.3', :require => 'stripe_mock'
15
+ gem 'stripe-ruby-mock', '~> 2.5.4', :require => 'stripe_mock'
16
16
 
17
17
  ## Features
18
18
 
@@ -68,7 +68,7 @@ describe MyApp do
68
68
  # Specify :source in place of :card (with same value) to return customer with source data
69
69
  customer = Stripe::Customer.create({
70
70
  email: 'johnny@appleseed.com',
71
- card: stripe_helper.generate_card_token
71
+ source: stripe_helper.generate_card_token
72
72
  })
73
73
  expect(customer.email).to eq('johnny@appleseed.com')
74
74
  end
@@ -170,6 +170,7 @@ StripeMock.prepare_card_error(:incorrect_cvc)
170
170
  StripeMock.prepare_card_error(:card_declined)
171
171
  StripeMock.prepare_card_error(:missing)
172
172
  StripeMock.prepare_card_error(:processing_error)
173
+ StripeMock.prepare_card_error(:incorrect_zip)
173
174
  ```
174
175
 
175
176
  You can see the details of each error in [lib/stripe_mock/api/errors.rb](lib/stripe_mock/api/errors.rb)
@@ -1,6 +1,7 @@
1
1
  require 'ostruct'
2
2
  require 'multi_json'
3
3
  require 'dante'
4
+ require 'time'
4
5
 
5
6
  require 'stripe'
6
7
 
@@ -37,6 +38,7 @@ require 'stripe_mock/api/test_helpers'
37
38
  require 'stripe_mock/api/webhooks'
38
39
 
39
40
  require 'stripe_mock/request_handlers/helpers/bank_account_helpers.rb'
41
+ require 'stripe_mock/request_handlers/helpers/external_account_helpers.rb'
40
42
  require 'stripe_mock/request_handlers/helpers/card_helpers.rb'
41
43
  require 'stripe_mock/request_handlers/helpers/charge_helpers.rb'
42
44
  require 'stripe_mock/request_handlers/helpers/coupon_helpers.rb'
@@ -46,6 +48,7 @@ require 'stripe_mock/request_handlers/helpers/token_helpers.rb'
46
48
  require 'stripe_mock/request_handlers/validators/param_validators.rb'
47
49
 
48
50
  require 'stripe_mock/request_handlers/accounts.rb'
51
+ require 'stripe_mock/request_handlers/external_accounts.rb'
49
52
  require 'stripe_mock/request_handlers/balance.rb'
50
53
  require 'stripe_mock/request_handlers/balance_transactions.rb'
51
54
  require 'stripe_mock/request_handlers/charges.rb'
@@ -74,11 +77,13 @@ require 'stripe_mock/test_strategies/live.rb'
74
77
 
75
78
  module StripeMock
76
79
 
80
+ @default_currency = 'usd'
77
81
  lib_dir = File.expand_path(File.dirname(__FILE__), '../..')
78
82
  @webhook_fixture_path = './spec/fixtures/stripe_webhooks/'
79
83
  @webhook_fixture_fallback_path = File.join(lib_dir, 'stripe_mock/webhook_fixtures')
80
84
 
81
85
  class << self
86
+ attr_accessor :default_currency
82
87
  attr_accessor :webhook_fixture_path
83
88
  end
84
89
  end
@@ -3,7 +3,7 @@ module StripeMock
3
3
 
4
4
  def self.mock_account(params = {})
5
5
  id = params[:id] || 'acct_103ED82ePvKYlo2C'
6
- currency = params[:currency] || 'usd'
6
+ currency = params[:currency] || StripeMock.default_currency
7
7
  {
8
8
  id: id,
9
9
  email: "bob@example.com",
@@ -103,7 +103,7 @@ module StripeMock
103
103
 
104
104
  def self.mock_customer(sources, params)
105
105
  cus_id = params[:id] || "test_cus_default"
106
- currency = params[:currency] || 'usd'
106
+ currency = params[:currency] || StripeMock.default_currency
107
107
  sources.each {|source| source[:customer] = cus_id}
108
108
  {
109
109
  email: 'stripe_mock@example.com',
@@ -134,7 +134,7 @@ module StripeMock
134
134
 
135
135
  def self.mock_charge(params={})
136
136
  charge_id = params[:id] || "ch_1fD6uiR9FAA2zc"
137
- currency = params[:currency] || 'usd'
137
+ currency = params[:currency] || StripeMock.default_currency
138
138
  {
139
139
  id: charge_id,
140
140
  object: "charge",
@@ -196,7 +196,7 @@ module StripeMock
196
196
  end
197
197
 
198
198
  def self.mock_refund(params={})
199
- currency = params[:currency] || 'usd'
199
+ currency = params[:currency] || StripeMock.default_currency
200
200
  {
201
201
  id: "re_4fWhgUh5si7InF",
202
202
  amount: 1,
@@ -248,7 +248,7 @@ module StripeMock
248
248
  end
249
249
 
250
250
  def self.mock_bank_account(params={})
251
- currency = params[:currency] || 'usd'
251
+ currency = params[:currency] || StripeMock.default_currency
252
252
  {
253
253
  id: "test_ba_default",
254
254
  object: "bank_account",
@@ -306,7 +306,7 @@ module StripeMock
306
306
  plan: {
307
307
  amount: 999,
308
308
  created: 1504035972,
309
- currency: 'usd'
309
+ currency: StripeMock.default_currency
310
310
  },
311
311
  quantity: 1
312
312
  }]
@@ -328,7 +328,7 @@ module StripeMock
328
328
 
329
329
  def self.mock_invoice(lines, params={})
330
330
  in_id = params[:id] || "test_in_default"
331
- currency = params[:currency] || 'usd'
331
+ currency = params[:currency] || StripeMock.default_currency
332
332
  lines << Data.mock_line_item() if lines.empty?
333
333
  invoice = {
334
334
  id: 'in_test_invoice',
@@ -379,7 +379,7 @@ module StripeMock
379
379
  end
380
380
 
381
381
  def self.mock_line_item(params = {})
382
- currency = params[:currency] || 'usd'
382
+ currency = params[:currency] || StripeMock.default_currency
383
383
  {
384
384
  id: "ii_test",
385
385
  object: "line_item",
@@ -402,7 +402,7 @@ module StripeMock
402
402
  end
403
403
 
404
404
  def self.mock_invoice_item(params = {})
405
- currency = params[:currency] || 'usd'
405
+ currency = params[:currency] || StripeMock.default_currency
406
406
  {
407
407
  id: "test_ii",
408
408
  object: "invoiceitem",
@@ -490,7 +490,7 @@ module StripeMock
490
490
  end
491
491
 
492
492
  def self.mock_plan(params={})
493
- currency = params[:currency] || 'usd'
493
+ currency = params[:currency] || StripeMock.default_currency
494
494
  {
495
495
  id: "2",
496
496
  object: "plan",
@@ -591,7 +591,7 @@ module StripeMock
591
591
  end
592
592
 
593
593
  def self.mock_transfer(params={})
594
- currency = params[:currency] || 'usd'
594
+ currency = params[:currency] || StripeMock.default_currency
595
595
  id = params[:id] || 'tr_test_transfer'
596
596
  {
597
597
  :status => 'pending',
@@ -623,7 +623,7 @@ module StripeMock
623
623
  end
624
624
 
625
625
  def self.mock_payout(params={})
626
- currency = params[:currency] || 'usd'
626
+ currency = params[:currency] || StripeMock.default_currency
627
627
  id = params[:id] || 'po_test_payout'
628
628
  {
629
629
  :amount => 100,
@@ -647,7 +647,7 @@ module StripeMock
647
647
 
648
648
  def self.mock_dispute(params={})
649
649
  @timestamp ||= Time.now.to_i
650
- currency = params[:currency] || 'usd'
650
+ currency = params[:currency] || StripeMock.default_currency
651
651
  id = params[:id] || "dp_test_dispute"
652
652
  {
653
653
  :id => id,
@@ -967,7 +967,7 @@ module StripeMock
967
967
  end
968
968
 
969
969
  def self.mock_balance_transaction(params = {})
970
- currency = params[:currency] || 'usd'
970
+ currency = params[:currency] || StripeMock.default_currency
971
971
  bt_id = params[:id] || 'test_txn_default'
972
972
  source = params[:source] || 'ch_test_charge'
973
973
  {
@@ -1015,7 +1015,7 @@ module StripeMock
1015
1015
  object: 'plan',
1016
1016
  amount: 1337,
1017
1017
  created: 1504716177,
1018
- currency: 'usd',
1018
+ currency: StripeMock.default_currency,
1019
1019
  interval: 'month',
1020
1020
  interval_count: 1,
1021
1021
  livemode: false,
@@ -20,6 +20,7 @@ module StripeMock
20
20
  @@handlers.find {|h| method_url =~ h[:route] }
21
21
  end
22
22
 
23
+ include StripeMock::RequestHandlers::ExternalAccounts
23
24
  include StripeMock::RequestHandlers::Accounts
24
25
  include StripeMock::RequestHandlers::Balance
25
26
  include StripeMock::RequestHandlers::BalanceTransactions
@@ -41,7 +41,7 @@ module StripeMock
41
41
  end
42
42
 
43
43
  ensure_required_params(params)
44
- bal_trans_params = { amount: params[:amount], source: params[:source] }
44
+ bal_trans_params = { amount: params[:amount], source: id }
45
45
 
46
46
  balance_transaction_id = new_balance_transaction('txn', bal_trans_params)
47
47
 
@@ -40,7 +40,7 @@ module StripeMock
40
40
  end
41
41
 
42
42
  subscription = Data.mock_subscription({ id: new_id('su') })
43
- subscription.merge!(custom_subscription_params(plan, customers[ params[:id] ], params))
43
+ subscription = resolve_subscription_changes(subscription, [plan], customers[ params[:id] ], params)
44
44
  add_subscription_to_customer(customers[ params[:id] ], subscription)
45
45
  subscriptions[subscription[:id]] = subscription
46
46
  elsif params[:trial_end]
@@ -0,0 +1,55 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module ExternalAccounts
4
+
5
+ def ExternalAccounts.included(klass)
6
+ klass.add_handler 'get /v1/accounts/(.*)/external_accounts', :retrieve_external_accounts
7
+ klass.add_handler 'post /v1/accounts/(.*)/external_accounts', :create_external_account
8
+ klass.add_handler 'post /v1/accounts/(.*)/external_accounts/(.*)/verify', :verify_external_account
9
+ klass.add_handler 'get /v1/accounts/(.*)/external_accounts/(.*)', :retrieve_external_account
10
+ klass.add_handler 'delete /v1/accounts/(.*)/external_accounts/(.*)', :delete_external_account
11
+ klass.add_handler 'post /v1/accounts/(.*)/external_accounts/(.*)', :update_external_account
12
+ end
13
+
14
+ def create_external_account(route, method_url, params, headers)
15
+ route =~ method_url
16
+ add_external_account_to(:account, $1, params, accounts)
17
+ end
18
+
19
+ def retrieve_external_accounts(route, method_url, params, headers)
20
+ route =~ method_url
21
+ retrieve_object_cards(:account, $1, accounts)
22
+ end
23
+
24
+ def retrieve_external_account(route, method_url, params, headers)
25
+ route =~ method_url
26
+ account = assert_existence :account, $1, accounts[$1]
27
+
28
+ assert_existence :card, $2, get_card(account, $2)
29
+ end
30
+
31
+ def delete_external_account(route, method_url, params, headers)
32
+ route =~ method_url
33
+ delete_card_from(:account, $1, $2, accounts)
34
+ end
35
+
36
+ def update_external_account(route, method_url, params, headers)
37
+ route =~ method_url
38
+ account = assert_existence :account, $1, accounts[$1]
39
+
40
+ card = assert_existence :card, $2, get_card(account, $2)
41
+ card.merge!(params)
42
+ card
43
+ end
44
+
45
+ def verify_external_account(route, method_url, params, headers)
46
+ route =~ method_url
47
+ account = assert_existence :account, $1, accounts[$1]
48
+
49
+ external_account = assert_existence :bank_account, $2, verify_bank_account(account, $2)
50
+ external_account
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -3,7 +3,7 @@ module StripeMock
3
3
  module Helpers
4
4
 
5
5
  def verify_bank_account(object, bank_account_id, class_name='Customer')
6
- bank_accounts = object[:bank_accounts] || object[:sources]
6
+ bank_accounts = object[:external_accounts] || object[:bank_accounts] || object[:sources]
7
7
  bank_account = bank_accounts[:data].find{|acc| acc[:id] == bank_account_id }
8
8
  return if bank_account.nil?
9
9
  bank_account['status'] = 'verified'
@@ -3,7 +3,7 @@ module StripeMock
3
3
  module Helpers
4
4
 
5
5
  def get_card(object, card_id, class_name='Customer')
6
- cards = object[:cards] || object[:sources]
6
+ cards = object[:cards] || object[:sources] || object[:external_accounts]
7
7
  card = cards[:data].find{|cc| cc[:id] == card_id }
8
8
  if card.nil?
9
9
  if class_name == 'Recipient'
@@ -36,7 +36,7 @@ module StripeMock
36
36
 
37
37
  def add_card_to_object(type, card, object, replace_current=false)
38
38
  card[type] = object[:id]
39
- cards_or_sources = object[:cards] || object[:sources]
39
+ cards_or_sources = object[:cards] || object[:sources] || object[:external_accounts]
40
40
 
41
41
  is_customer = object.has_key?(:sources)
42
42
 
@@ -58,7 +58,7 @@ module StripeMock
58
58
 
59
59
  def retrieve_object_cards(type, type_id, objects)
60
60
  resource = assert_existence type, type_id, objects[type_id]
61
- cards = resource[:cards] || resource[:sources]
61
+ cards = resource[:cards] || resource[:sources] || resource[:external_accounts]
62
62
 
63
63
  Data.mock_list_object(cards[:data])
64
64
  end
@@ -69,7 +69,7 @@ module StripeMock
69
69
  assert_existence :card, card_id, get_card(resource, card_id)
70
70
 
71
71
  card = { id: card_id, deleted: true }
72
- cards_or_sources = resource[:cards] || resource[:sources]
72
+ cards_or_sources = resource[:cards] || resource[:sources] || resource[:external_accounts]
73
73
  cards_or_sources[:data].reject!{|cc|
74
74
  cc[:id] == card[:id]
75
75
  }
@@ -103,7 +103,7 @@ module StripeMock
103
103
  def add_card_to(type, type_id, params, objects)
104
104
  resource = assert_existence type, type_id, objects[type_id]
105
105
 
106
- card = card_from_params(params[:card] || params[:source])
106
+ card = card_from_params(params[:card] || params[:source] || params[:external_accounts])
107
107
  add_card_to_object(type, card, resource)
108
108
  end
109
109
 
@@ -0,0 +1,49 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Helpers
4
+
5
+ def add_external_account_to(type, type_id, params, objects)
6
+ resource = assert_existence type, type_id, objects[type_id]
7
+
8
+ source =
9
+ if params[:card]
10
+ card_from_params(params[:card])
11
+ elsif params[:bank_account]
12
+ bank_from_params(params[:bank_account])
13
+ else
14
+ begin
15
+ get_card_by_token(params[:external_account])
16
+ rescue Stripe::InvalidRequestError
17
+ bank_from_params(params[:external_account])
18
+ end
19
+ end
20
+ add_external_account_to_object(type, source, resource)
21
+ end
22
+
23
+ def add_external_account_to_object(type, source, object, replace_current=false)
24
+ source[type] = object[:id]
25
+ accounts = object[:external_accounts]
26
+
27
+ if replace_current && accounts[:data]
28
+ accounts[:data].delete_if {|source| source[:id] == object[:default_source]}
29
+ object[:default_source] = source[:id]
30
+ accounts[:data] = [source]
31
+ else
32
+ accounts[:total_count] = (accounts[:total_count] || 0) + 1
33
+ (accounts[:data] ||= []) << source
34
+ end
35
+ object[:default_source] = source[:id] if object[:default_source].nil?
36
+
37
+ source
38
+ end
39
+
40
+ def bank_from_params(attrs_or_token)
41
+ if attrs_or_token.is_a? Hash
42
+ attrs_or_token = generate_bank_token(attrs_or_token)
43
+ end
44
+ get_bank_by_token(attrs_or_token)
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -6,22 +6,31 @@ module StripeMock
6
6
  customer[:subscriptions][:data].find{|sub| sub[:id] == sub_id }
7
7
  end
8
8
 
9
- def custom_subscription_params(plan, cus, options = {})
9
+ def resolve_subscription_changes(subscription, plans, customer, options = {})
10
+ subscription.merge!(custom_subscription_params(plans, customer, options))
11
+ subscription[:items][:data] = plans.map { |plan| Data.mock_subscription_item({ plan: plan }) }
12
+ subscription
13
+ end
14
+
15
+ def custom_subscription_params(plans, cus, options = {})
10
16
  verify_trial_end(options[:trial_end]) if options[:trial_end]
11
17
 
18
+ plan = plans.first if plans.size == 1
19
+
12
20
  now = Time.now.utc.to_i
13
21
  created_time = options[:created] || now
14
22
  start_time = options[:current_period_start] || now
15
- params = { plan: plan, customer: cus[:id], current_period_start: start_time, created: created_time }
23
+ params = { customer: cus[:id], current_period_start: start_time, created: created_time }
24
+ params.merge!({ :plan => (plans.size == 1 ? plans.first : nil) })
16
25
  params.merge! options.select {|k,v| k =~ /application_fee_percent|quantity|metadata|tax_percent/}
17
26
  # TODO: Implement coupon logic
18
27
 
19
28
  if (((plan && plan[:trial_period_days]) || 0) == 0 && options[:trial_end].nil?) || options[:trial_end] == "now"
20
- end_time = get_ending_time(start_time, plan)
21
- params.merge!({status: 'active', current_period_end: end_time, trial_start: nil, trial_end: nil})
29
+ end_time = options[:billing_cycle_anchor] || get_ending_time(start_time, plan)
30
+ params.merge!({status: 'active', current_period_end: end_time, trial_start: nil, trial_end: nil, billing_cycle_anchor: options[:billing_cycle_anchor]})
22
31
  else
23
32
  end_time = options[:trial_end] || (Time.now.utc.to_i + plan[:trial_period_days]*86400)
24
- params.merge!({status: 'trialing', current_period_end: end_time, trial_start: start_time, trial_end: end_time})
33
+ params.merge!({status: 'trialing', current_period_end: end_time, trial_start: start_time, trial_end: end_time, billing_cycle_anchor: nil})
25
34
  end
26
35
 
27
36
  params
@@ -87,14 +96,6 @@ module StripeMock
87
96
  items.each { |i| total += (i[:quantity] || 1) * i[:plan][:amount] }
88
97
  total
89
98
  end
90
-
91
- def mock_subscription_items(items = [])
92
- data = []
93
- items.each do |i|
94
- data << Data.mock_subscription_item(i.merge(plan: plans[i[:plan].to_s]))
95
- end
96
- data
97
- end
98
99
  end
99
100
  end
100
101
  end
@@ -87,7 +87,7 @@ module StripeMock
87
87
  invoice_date = Time.now.to_i
88
88
  subscription_plan = assert_existence :plan, subscription_plan_id, plans[subscription_plan_id.to_s]
89
89
  preview_subscription = Data.mock_subscription
90
- preview_subscription.merge!(custom_subscription_params(subscription_plan, customer, { trial_end: params[:subscription_trial_end] }))
90
+ preview_subscription = resolve_subscription_changes(preview_subscription, [subscription_plan], customer, { trial_end: params[:subscription_trial_end] })
91
91
  preview_subscription[:id] = subscription[:id]
92
92
  preview_subscription[:quantity] = subscription_quantity
93
93
  subscription_proration_date = params[:subscription_proration_date] || Time.now
@@ -166,9 +166,9 @@ module StripeMock
166
166
  #anonymous charge
167
167
  def invoice_charge(invoice)
168
168
  begin
169
- new_charge(nil, nil, {customer: invoice[:customer]["id"], amount: invoice[:amount_due], currency: 'usd'}, nil)
169
+ new_charge(nil, nil, {customer: invoice[:customer]["id"], amount: invoice[:amount_due], currency: StripeMock.default_currency}, nil)
170
170
  rescue Stripe::InvalidRequestError
171
- new_charge(nil, nil, {source: generate_card_token, amount: invoice[:amount_due], currency: 'usd'}, nil)
171
+ new_charge(nil, nil, {source: generate_card_token, amount: invoice[:amount_due], currency: StripeMock.default_currency}, nil)
172
172
  end
173
173
  end
174
174
 
@@ -11,6 +11,7 @@ module StripeMock
11
11
  end
12
12
 
13
13
  def new_plan(route, method_url, params, headers)
14
+ params[:id] ||= new_id('plan')
14
15
  validate_create_plan_params(params)
15
16
  plans[ params[:id] ] = Data.mock_plan(params)
16
17
  end
@@ -32,24 +32,10 @@ module StripeMock
32
32
  customer[:subscriptions]
33
33
  end
34
34
 
35
- def plan_id_from_params(params)
36
- if params[:plan]
37
- params[:plan].to_s
38
- elsif params[:items]
39
- item = params[:items].values.find { |item| item[:plan] }
40
- if item
41
- item[:plan].to_s
42
- end
43
- end
44
- end
45
-
46
35
  def create_customer_subscription(route, method_url, params, headers)
47
36
  route =~ method_url
48
37
 
49
- plan_id = plan_id_from_params(params)
50
-
51
- plan = assert_existence :plan, plan_id, plans[plan_id]
52
-
38
+ subscription_plans = get_subscription_plans_from_params(params)
53
39
  customer = assert_existence :customer, $1, customers[$1]
54
40
 
55
41
  if params[:source]
@@ -59,10 +45,11 @@ module StripeMock
59
45
  end
60
46
 
61
47
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
62
- subscription.merge!(custom_subscription_params(plan, customer, params))
48
+ subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
63
49
 
64
50
  # Ensure customer has card to charge if plan has no trial and is not free
65
- verify_card_present(customer, plan, subscription, params)
51
+ # Note: needs updating for subscriptions with multiple plans
52
+ verify_card_present(customer, subscription_plans.first, subscription, params)
66
53
 
67
54
  if params[:coupon]
68
55
  coupon_id = params[:coupon]
@@ -82,25 +69,23 @@ module StripeMock
82
69
  subscriptions[subscription[:id]] = subscription
83
70
  add_subscription_to_customer(customer, subscription)
84
71
 
85
- clear_top_level_plan_if_multiple_items(subscription)
86
-
87
72
  subscriptions[subscription[:id]]
88
73
  end
89
74
 
90
75
  def create_subscription(route, method_url, params, headers)
91
76
  route =~ method_url
92
77
 
93
- plan_id = plan_id_from_params(params)
94
-
95
- plan = plan_id ? assert_existence(:plan, plan_id, plans[plan_id]) : nil
78
+ subscription_plans = get_subscription_plans_from_params(params)
96
79
 
97
80
  customer = params[:customer]
98
81
  customer_id = customer.is_a?(Stripe::Customer) ? customer[:id] : customer.to_s
99
82
  customer = assert_existence :customer, customer_id, customers[customer_id]
100
83
 
101
- if plan && customer
102
- unless customer[:currency].to_s == plan[:currency].to_s
103
- raise Stripe::InvalidRequestError.new('lol', 'currency', http_status: 400)
84
+ if subscription_plans && customer
85
+ subscription_plans.each do |plan|
86
+ unless customer[:currency].to_s == plan[:currency].to_s
87
+ raise Stripe::InvalidRequestError.new("Customer's currency of #{customer[:currency]} does not match plan's currency of #{plan[:currency]}", 'currency', http_status: 400)
88
+ end
104
89
  end
105
90
  end
106
91
 
@@ -110,18 +95,18 @@ module StripeMock
110
95
  customer[:default_source] = new_card[:id]
111
96
  end
112
97
 
113
- 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)
98
+ 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)
114
99
  unknown_params = params.keys - allowed_params.map(&:to_sym)
115
100
  if unknown_params.length > 0
116
101
  raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
117
102
  end
118
103
 
119
104
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
120
- subscription.merge!(custom_subscription_params(plan, customer, params))
121
- subscription[:items][:data] = mock_subscription_items(params[:items].values) if params[:items]
105
+ subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
122
106
 
123
107
  # Ensure customer has card to charge if plan has no trial and is not free
124
- verify_card_present(customer, plan, subscription, params)
108
+ # Note: needs updating for subscriptions with multiple plans
109
+ verify_card_present(customer, subscription_plans.first, subscription, params)
125
110
 
126
111
  if params[:coupon]
127
112
  coupon_id = params[:coupon]
@@ -141,8 +126,6 @@ module StripeMock
141
126
  subscriptions[subscription[:id]] = subscription
142
127
  add_subscription_to_customer(customer, subscription)
143
128
 
144
- clear_top_level_plan_if_multiple_items(subscription)
145
-
146
129
  subscriptions[subscription[:id]]
147
130
  end
148
131
 
@@ -176,21 +159,12 @@ module StripeMock
176
159
  customer[:default_source] = new_card[:id]
177
160
  end
178
161
 
179
- # expand the plan for addition to the customer object
180
- plan_id = plan_id_from_params(params)
181
-
182
- unless plan_id
183
- plan_id = if subscription[:plan]
184
- subscription[:plan][:id]
185
- elsif subscription[:items]
186
- row = subscription[:items][:data].find { |item| item[:plan] }
187
- if row
188
- row[:plan][:id]
189
- end
190
- end
191
- end
162
+ subscription_plans = get_subscription_plans_from_params(params)
192
163
 
193
- plan = plans[plan_id]
164
+ # subscription plans are not being updated but load them for the response
165
+ if subscription_plans.empty?
166
+ subscription_plans = subscription[:items][:data].map { |item| item[:plan] }
167
+ end
194
168
 
195
169
  if params[:coupon]
196
170
  coupon_id = params[:coupon]
@@ -207,10 +181,7 @@ module StripeMock
207
181
  raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
208
182
  end
209
183
  end
210
-
211
- assert_existence :plan, plan_id, plan
212
- params[:plan] = plan if params[:plan]
213
- verify_card_present(customer, plan, subscription)
184
+ verify_card_present(customer, subscription_plans.first, subscription)
214
185
 
215
186
  if subscription[:cancel_at_period_end]
216
187
  subscription[:cancel_at_period_end] = false
@@ -218,14 +189,12 @@ module StripeMock
218
189
  end
219
190
 
220
191
  params[:current_period_start] = subscription[:current_period_start]
221
- subscription.merge!(custom_subscription_params(plan, customer, params))
192
+ subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
222
193
 
223
194
  # delete the old subscription, replace with the new subscription
224
195
  customer[:subscriptions][:data].reject! { |sub| sub[:id] == subscription[:id] }
225
196
  customer[:subscriptions][:data] << subscription
226
197
 
227
- clear_top_level_plan_if_multiple_items(subscription)
228
-
229
198
  subscription
230
199
  end
231
200
 
@@ -259,8 +228,20 @@ module StripeMock
259
228
 
260
229
  private
261
230
 
262
- def clear_top_level_plan_if_multiple_items(subscription)
263
- subscription[:plan] = nil if subscription[:items][:data].size > 1
231
+ def get_subscription_plans_from_params(params)
232
+ plan_ids = if params[:plan]
233
+ [params[:plan].to_s]
234
+ elsif params[:items]
235
+ items = params[:items]
236
+ items = items.values if items.respond_to?(:values)
237
+ items.map { |item| item[:plan].to_s if item[:plan] }
238
+ else
239
+ []
240
+ end
241
+ plan_ids.each do |plan_id|
242
+ assert_existence :plan, plan_id, plans[plan_id]
243
+ end
244
+ plan_ids.map { |plan_id| plans[plan_id] }
264
245
  end
265
246
 
266
247
  def verify_card_present(customer, plan, subscription, params={})
@@ -3,7 +3,7 @@ module StripeMock
3
3
  class Base
4
4
 
5
5
  def create_plan_params(params={})
6
- currency = params[:currency] || 'usd'
6
+ currency = params[:currency] || StripeMock.default_currency
7
7
  {
8
8
  :id => 'stripe_mock_default_plan_id',
9
9
  :name => 'StripeMock Default Plan ID',
@@ -23,7 +23,7 @@ module StripeMock
23
23
  end
24
24
 
25
25
  def generate_bank_token(bank_account_params={})
26
- currency = bank_account_params[:currency] || 'usd'
26
+ currency = bank_account_params[:currency] || StripeMock.default_currency
27
27
  bank_account = {
28
28
  :country => "US",
29
29
  :currency => currency,
@@ -39,7 +39,7 @@ module StripeMock
39
39
  end
40
40
 
41
41
  def create_coupon_params(params = {})
42
- currency = params[:currency] || 'usd'
42
+ currency = params[:currency] || StripeMock.default_currency
43
43
  {
44
44
  id: '10BUCKS',
45
45
  amount_off: 1000,
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "2.5.3"
3
+ VERSION = "2.5.4"
4
4
  end
@@ -52,4 +52,18 @@ describe StripeMock::Instance do
52
52
  StripeMock.set_conversion_rate(1.25)
53
53
  expect(StripeMock.instance.conversion_rate).to eq(1.25)
54
54
  end
55
+
56
+ it "allows non-usd default currency" do
57
+ old_default_currency = StripeMock.default_currency
58
+ customer = begin
59
+ StripeMock.default_currency = "jpy"
60
+ Stripe::Customer.create({
61
+ email: 'johnny@appleseed.com',
62
+ source: stripe_helper.generate_card_token
63
+ })
64
+ ensure
65
+ StripeMock.default_currency = old_default_currency
66
+ end
67
+ expect(customer.currency).to eq("jpy")
68
+ end
55
69
  end
@@ -40,7 +40,7 @@ shared_examples 'Bank API' do
40
40
  expect(bank.last4).to eq("6789")
41
41
  end
42
42
 
43
- it "creates a single bank with a generated bank token", :live => true do
43
+ it "creates a single bank with a generated bank token" do
44
44
  customer = Stripe::Customer.create
45
45
  expect(customer.sources.count).to eq 0
46
46
 
@@ -171,7 +171,7 @@ shared_examples 'Charge API' do
171
171
  bal_trans = Stripe::BalanceTransaction.retrieve(charge.balance_transaction)
172
172
  expect(bal_trans.amount).to eq(charge.amount)
173
173
  expect(bal_trans.fee).to eq(39)
174
- expect(bal_trans.source).to eq(charge.source)
174
+ expect(bal_trans.source).to eq(charge.id)
175
175
  end
176
176
 
177
177
  context 'when conversion rate is set' do
@@ -220,8 +220,8 @@ shared_examples 'Customer API' do
220
220
  end
221
221
 
222
222
  describe 'repeating coupon with duration limit', live: true do
223
- let!(:coupon) { Stripe::Coupon.create(id: '10OFF', amount_off: 1000, currency: 'usd', duration: 'repeating', duration_in_months: 12) }
224
- let!(:customer) { Stripe::Customer.create(coupon: '10OFF') }
223
+ let!(:coupon) { stripe_helper.create_coupon(id: '10OFF', amount_off: 1000, currency: 'usd', duration: 'repeating', duration_in_months: 12) }
224
+ let!(:customer) { Stripe::Customer.create(coupon: coupon.id) }
225
225
  it 'creates the discount with the end date', live: true do
226
226
  discount = Stripe::Customer.retrieve(customer.id).discount
227
227
  expect(discount).to_not be_nil
@@ -0,0 +1,170 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples 'External Account API' do
4
+
5
+ it 'creates/returns a bank when using account.external_accounts.create given a bank token' do
6
+ account = Stripe::Account.create(id: 'test_account', type: 'custom', country: "US")
7
+ bank_token = stripe_helper.generate_bank_token(last4: "1123", exp_month: 11, exp_year: 2099)
8
+ bank = account.external_accounts.create(external_account: bank_token)
9
+
10
+ expect(bank.account).to eq('test_account')
11
+ expect(bank.last4).to eq("1123")
12
+ expect(bank.exp_month).to eq(11)
13
+ expect(bank.exp_year).to eq(2099)
14
+
15
+ account = Stripe::Account.retrieve('test_account')
16
+ expect(account.external_accounts.count).to eq(1)
17
+ bank = account.external_accounts.first
18
+ expect(bank.account).to eq('test_account')
19
+ expect(bank.last4).to eq("1123")
20
+ expect(bank.exp_month).to eq(11)
21
+ expect(bank.exp_year).to eq(2099)
22
+ end
23
+
24
+ it 'creates/returns a bank when using account.external_accounts.create given bank params' do
25
+ account = Stripe::Account.create(id: 'test_account', type: 'custom', country: "US")
26
+ bank = account.external_accounts.create(external_account: {
27
+ object: 'bank_account',
28
+ account_number: '000123456789',
29
+ routing_number: '110000000',
30
+ country: 'US',
31
+ currency: 'usd'
32
+ })
33
+
34
+ expect(bank.account).to eq('test_account')
35
+ expect(bank.routing_number).to eq('110000000')
36
+ expect(bank.country).to eq('US')
37
+ expect(bank.currency).to eq('usd')
38
+
39
+ account = Stripe::Account.retrieve('test_account')
40
+ expect(account.external_accounts.count).to eq(1)
41
+ bank = account.external_accounts.first
42
+ expect(bank.account).to eq('test_account')
43
+ expect(bank.routing_number).to eq('110000000')
44
+ expect(bank.country).to eq('US')
45
+ expect(bank.currency).to eq('usd')
46
+ end
47
+
48
+ it "creates a single bank with a generated bank token" do
49
+ account = Stripe::Account.create(type: 'custom', country: "US")
50
+ expect(account.external_accounts.count).to eq 0
51
+
52
+ account.external_accounts.create external_account: stripe_helper.generate_bank_token
53
+ # Yes, stripe-ruby does not actually add the new bank to the account instance
54
+ expect(account.external_accounts.count).to eq 0
55
+
56
+ account2 = Stripe::Account.retrieve(account.id)
57
+ expect(account2.external_accounts.count).to eq 1
58
+ end
59
+
60
+ describe "retrieval and deletion with accounts" do
61
+ let!(:account) { Stripe::Account.create(id: 'test_account', type: 'custom', country: "US") }
62
+ let!(:bank_token) { stripe_helper.generate_bank_token(last4: "1123", exp_month: 11, exp_year: 2099) }
63
+ let!(:bank) { account.external_accounts.create(external_account: bank_token) }
64
+
65
+ it "can retrieve all account's banks" do
66
+ retrieved = account.external_accounts.all
67
+ expect(retrieved.count).to eq(1)
68
+ end
69
+
70
+ it "retrieves an account bank" do
71
+ retrieved = account.external_accounts.retrieve(bank.id)
72
+ expect(retrieved.to_s).to eq(bank.to_s)
73
+ end
74
+
75
+ it "retrieves an account's bank after re-fetching the account" do
76
+ retrieved = Stripe::Account.retrieve(account.id).external_accounts.retrieve(bank.id)
77
+ expect(retrieved.id).to eq bank.id
78
+ end
79
+
80
+ it "deletes an accounts bank" do
81
+ bank.delete
82
+ retrieved_acct = Stripe::Account.retrieve(account.id)
83
+ expect(retrieved_acct.external_accounts.data).to be_empty
84
+ end
85
+
86
+ context "deletion when the user has two external accounts" do
87
+ let!(:bank_token_2) { stripe_helper.generate_bank_token(last4: "1123", exp_month: 11, exp_year: 2099) }
88
+ let!(:bank_2) { account.external_accounts.create(external_account: bank_token_2) }
89
+
90
+ it "has just one bank anymore" do
91
+ bank.delete
92
+ retrieved_acct = Stripe::Account.retrieve(account.id)
93
+ expect(retrieved_acct.external_accounts.data.count).to eq 1
94
+ expect(retrieved_acct.external_accounts.data.first.id).to eq bank_2.id
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "Errors" do
100
+ it "throws an error when the account does not have the retrieving bank id" do
101
+ account = Stripe::Account.create(type: 'custom', country: "US")
102
+ bank_id = "bank_123"
103
+ expect { account.external_accounts.retrieve(bank_id) }.to raise_error {|e|
104
+ expect(e).to be_a Stripe::InvalidRequestError
105
+ expect(e.message).to match /no.*source/i
106
+ expect(e.message).to include bank_id
107
+ expect(e.param).to eq 'id'
108
+ expect(e.http_status).to eq 404
109
+ }
110
+ end
111
+ end
112
+
113
+ context "update bank" do
114
+ let!(:account) { Stripe::Account.create(id: 'test_account', type: 'custom', country: "US") }
115
+ let!(:bank_token) { stripe_helper.generate_bank_token(last4: "1123", exp_month: 11, exp_year: 2099) }
116
+ let!(:bank) { account.external_accounts.create(external_account: bank_token) }
117
+
118
+ it "updates the bank" do
119
+ exp_month = 10
120
+ exp_year = 2098
121
+
122
+ bank.exp_month = exp_month
123
+ bank.exp_year = exp_year
124
+ bank.save
125
+
126
+ retrieved = account.external_accounts.retrieve(bank.id)
127
+
128
+ expect(retrieved.exp_month).to eq(exp_month)
129
+ expect(retrieved.exp_year).to eq(exp_year)
130
+ end
131
+ end
132
+
133
+ context "retrieve multiple banks" do
134
+
135
+ it "retrieves a list of multiple banks" do
136
+ account = Stripe::Account.create(id: 'test_account', type: 'custom', country: "US")
137
+
138
+ bank_token = stripe_helper.generate_bank_token(last4: "1123", exp_month: 11, exp_year: 2099)
139
+ bank1 = account.external_accounts.create(external_accout: bank_token)
140
+ bank_token = stripe_helper.generate_bank_token(last4: "1124", exp_month: 12, exp_year: 2098)
141
+ bank2 = account.external_accounts.create(external_account: bank_token)
142
+
143
+ account = Stripe::Account.retrieve('test_account')
144
+
145
+ list = account.external_accounts.all
146
+
147
+ expect(list.object).to eq("list")
148
+ expect(list.count).to eq(2)
149
+ expect(list.data.length).to eq(2)
150
+
151
+ expect(list.data.first.object).to eq("bank_account")
152
+ expect(list.data.first.to_hash).to eq(bank1.to_hash)
153
+
154
+ expect(list.data.last.object).to eq("bank_account")
155
+ expect(list.data.last.to_hash).to eq(bank2.to_hash)
156
+ end
157
+
158
+ it "retrieves an empty list if there's no subscriptions" do
159
+ Stripe::Account.create(id: 'no_banks', type: 'custom', country: "US")
160
+ account = Stripe::Account.retrieve('no_banks')
161
+
162
+ list = account.external_accounts.all
163
+
164
+ expect(list.object).to eq("list")
165
+ expect(list.count).to eq(0)
166
+ expect(list.data.length).to eq(0)
167
+ end
168
+ end
169
+
170
+ end
@@ -107,12 +107,12 @@ shared_examples 'Invoice API' do
107
107
  end
108
108
 
109
109
  context "retrieving upcoming invoice" do
110
- let(:customer) { @teardown_customer = true; Stripe::Customer.create(source: stripe_helper.generate_card_token) }
111
- let(:coupon_amtoff) { @teardown_coupon_amtoff = true; Stripe::Coupon.create(id: '100OFF', currency: 'usd', amount_off: 100_00, duration: 'repeating', duration_in_months: 6) }
112
- let(:coupon_pctoff) { @teardown_coupon_pctoff = true; Stripe::Coupon.create(id: '50%OFF', currency: 'usd', percent_off: 50, duration: 'repeating', duration_in_months: 6) }
113
- let(:plan) { @teardown_plan = true; Stripe::Plan.create(id: '50m', amount: 50_00, interval: 'month', name: '50m', currency: 'usd') }
110
+ let(:customer) { Stripe::Customer.create(source: stripe_helper.generate_card_token) }
111
+ 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') }
114
114
  let(:quantity) { 3 }
115
- let(:subscription) { @teardown_subscription = true; Stripe::Subscription.create(plan: plan.id, customer: customer.id, quantity: quantity) }
115
+ let(:subscription) { Stripe::Subscription.create(plan: plan.id, customer: customer.id, quantity: quantity) }
116
116
 
117
117
  before(with_customer: true) { customer }
118
118
  before(with_coupon_amtoff: true) { coupon_amtoff }
@@ -122,11 +122,11 @@ shared_examples 'Invoice API' do
122
122
  before(with_plan: true) { plan }
123
123
  before(with_subscription: true) { subscription }
124
124
 
125
- after { subscription.delete rescue nil if @teardown_subscription }
126
- after { plan.delete rescue nil if @teardown_plan }
127
- after { coupon_pctoff.delete rescue nil if @teardown_coupon_pctoff }
128
- after { coupon_amtoff.delete rescue nil if @teardown_coupon_amtoff }
129
- after { customer.delete rescue nil if @teardown_customer }
125
+ # after { subscription.delete rescue nil if @teardown_subscription }
126
+ # after { plan.delete rescue nil if @teardown_plan }
127
+ # after { coupon_pctoff.delete rescue nil if @teardown_coupon_pctoff }
128
+ # after { coupon_amtoff.delete rescue nil if @teardown_coupon_amtoff }
129
+ # after { customer.delete rescue nil if @teardown_customer }
130
130
 
131
131
  describe 'parameter validation' do
132
132
  it 'fails without parameters' do
@@ -248,8 +248,9 @@ shared_examples 'Invoice API' do
248
248
 
249
249
  [false, true].each do |with_trial|
250
250
  describe "prorating a subscription with a new plan, with_trial: #{with_trial}" do
251
- let(:new_monthly_plan) { @teardown_monthly_plan = true; Stripe::Plan.create(id: '100m', amount: 100_00, interval: 'month', name: '100m', currency: 'usd') }
252
- let(:new_yearly_plan) { @teardown_yearly_plan = true; Stripe::Plan.create(id: '100y', amount: 100_00, interval: 'year', name: '100y', currency: 'usd') }
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') }
253
254
 
254
255
  it 'prorates while maintaining billing interval', live: true do
255
256
  # Given
@@ -341,8 +342,8 @@ shared_examples 'Invoice API' do
341
342
  expect(upcoming.lines.data[1].quantity).to eq new_quantity
342
343
  end
343
344
 
344
- after { new_monthly_plan.delete rescue nil if @teardown_monthly_plan }
345
- after { new_yearly_plan.delete rescue nil if @teardown_yearly_plan }
345
+ # after { new_monthly_plan.delete rescue nil if @teardown_monthly_plan }
346
+ # after { new_yearly_plan.delete rescue nil if @teardown_yearly_plan }
346
347
  end
347
348
  end
348
349
 
@@ -30,6 +30,17 @@ shared_examples 'Plan API' do
30
30
  end
31
31
 
32
32
 
33
+ it "creates a stripe plan without specifying ID" do
34
+ plan = Stripe::Plan.create(
35
+ :name => 'The Mock Plan',
36
+ :amount => 9900,
37
+ :currency => 'USD',
38
+ :interval => 1,
39
+ )
40
+
41
+ expect(plan.id).to match(/^test_plan/)
42
+ end
43
+
33
44
  it "stores a created stripe plan in memory" do
34
45
  plan = Stripe::Plan.create(
35
46
  :id => 'pid_2',
@@ -283,6 +283,7 @@ shared_examples 'Customer Subscriptions' do
283
283
  expect(sub.object).to eq('subscription')
284
284
  expect(sub.plan.to_hash).to eq(plan.to_hash)
285
285
  expect(sub.trial_end - sub.trial_start).to eq(14 * 86400)
286
+ expect(sub.billing_cycle_anchor).to be_nil
286
287
 
287
288
  customer = Stripe::Customer.retrieve('cardless')
288
289
  expect(customer.subscriptions.data).to_not be_empty
@@ -398,6 +399,18 @@ shared_examples 'Customer Subscriptions' do
398
399
  }
399
400
  end
400
401
 
402
+ it 'overrides current period end when billing cycle anchor is set' do
403
+ plan = stripe_helper.create_plan(id: 'plan', amount: 999)
404
+ customer = Stripe::Customer.create(source: gen_card_tk)
405
+ billing_cycle_anchor = Time.now.utc.to_i + 3600
406
+
407
+ sub = Stripe::Subscription.create({ plan: 'plan', customer: customer.id, billing_cycle_anchor: billing_cycle_anchor })
408
+
409
+ expect(sub.status).to eq('active')
410
+ expect(sub.current_period_end).to eq(billing_cycle_anchor)
411
+ expect(sub.billing_cycle_anchor).to eq(billing_cycle_anchor)
412
+ end
413
+
401
414
  it 'when plan defined inside items', live: true do
402
415
  plan = stripe_helper.create_plan(id: 'BASE_PRICE_PLAN1')
403
416
 
@@ -504,6 +517,57 @@ shared_examples 'Customer Subscriptions' do
504
517
  expect(customer.subscriptions.data.first.customer).to eq(customer.id)
505
518
  end
506
519
 
520
+ it "updates a stripe customer's existing subscription with single plan when multiple plans inside of items" do
521
+ silver_plan = stripe_helper.create_plan(id: 'silver')
522
+ gold_plan = stripe_helper.create_plan(id: 'gold')
523
+ addon_plan = stripe_helper.create_plan(id: 'addon_plan')
524
+ customer = Stripe::Customer.create(id: 'test_customer_sub', source: gen_card_tk, plan: silver_plan.id)
525
+
526
+ sub = Stripe::Subscription.retrieve(customer.subscriptions.data.first.id)
527
+ sub.items = [{ plan: gold_plan.id, quantity: 2 }, { plan: addon_plan.id, quantity: 2 }]
528
+ expect(sub.save).to be_truthy
529
+
530
+ expect(sub.object).to eq('subscription')
531
+ expect(sub.plan).to be_nil
532
+
533
+ customer = Stripe::Customer.retrieve('test_customer_sub')
534
+ expect(customer.subscriptions.data).to_not be_empty
535
+ expect(customer.subscriptions.count).to eq(1)
536
+ expect(customer.subscriptions.data.length).to eq(1)
537
+
538
+ expect(customer.subscriptions.data.first.id).to eq(sub.id)
539
+ expect(customer.subscriptions.data.first.plan).to be_nil
540
+ expect(customer.subscriptions.data.first.customer).to eq(customer.id)
541
+ expect(customer.subscriptions.data.first.items.data[0].plan.to_hash).to eq(gold_plan.to_hash)
542
+ expect(customer.subscriptions.data.first.items.data[1].plan.to_hash).to eq(addon_plan.to_hash)
543
+ end
544
+
545
+ it "updates a stripe customer's existing subscription with multple plans when multiple plans inside of items" do
546
+ silver_plan = stripe_helper.create_plan(id: 'silver')
547
+ gold_plan = stripe_helper.create_plan(id: 'gold')
548
+ addon1_plan = stripe_helper.create_plan(id: 'addon1')
549
+ addon2_plan = stripe_helper.create_plan(id: 'addon2')
550
+ customer = Stripe::Customer.create(id: 'test_customer_sub', source: gen_card_tk)
551
+ sub = Stripe::Subscription.create(customer: customer.id, items: [{ plan: silver_plan.id }, { plan: addon1_plan.id }])
552
+
553
+ sub.items = [{ plan: gold_plan.id, quantity: 2 }, { plan: addon2_plan.id, quantity: 2 }]
554
+ expect(sub.save).to be_truthy
555
+
556
+ expect(sub.object).to eq('subscription')
557
+ expect(sub.plan).to be_nil
558
+
559
+ customer = Stripe::Customer.retrieve('test_customer_sub')
560
+ expect(customer.subscriptions.data).to_not be_empty
561
+ expect(customer.subscriptions.count).to eq(1)
562
+ expect(customer.subscriptions.data.length).to eq(1)
563
+
564
+ expect(customer.subscriptions.data.first.id).to eq(sub.id)
565
+ expect(customer.subscriptions.data.first.plan).to be_nil
566
+ expect(customer.subscriptions.data.first.customer).to eq(customer.id)
567
+ expect(customer.subscriptions.data.first.items.data[0].plan.to_hash).to eq(gold_plan.to_hash)
568
+ expect(customer.subscriptions.data.first.items.data[1].plan.to_hash).to eq(addon2_plan.to_hash)
569
+ end
570
+
507
571
  it 'when adds coupon', live: true do
508
572
  plan = stripe_helper.create_plan(id: 'plan_with_coupon2', name: 'One More Test Plan', amount: 777)
509
573
  coupon = stripe_helper.create_coupon
@@ -857,13 +921,13 @@ shared_examples 'Customer Subscriptions' do
857
921
  expect(subscription.items.object).to eq('list')
858
922
  expect(subscription.items.data.class).to eq(Array)
859
923
  expect(subscription.items.data.count).to eq(1)
860
- expect(subscription.items.data.first.id).to eq('si_1AwFf62eZvKYlo2C9u6Dhf9')
861
- expect(subscription.items.data.first.created).to eq(1504035973)
924
+ expect(subscription.items.data.first.id).to eq('test_txn_default')
925
+ expect(subscription.items.data.first.created).to eq(1504716183)
862
926
  expect(subscription.items.data.first.object).to eq('subscription_item')
863
- expect(subscription.items.data.first.plan.amount).to eq(999)
864
- expect(subscription.items.data.first.plan.created).to eq(1504035972)
927
+ expect(subscription.items.data.first.plan.amount).to eq(0)
928
+ expect(subscription.items.data.first.plan.created).to eq(1466698898)
865
929
  expect(subscription.items.data.first.plan.currency).to eq('usd')
866
- expect(subscription.items.data.first.quantity).to eq(1)
930
+ expect(subscription.items.data.first.quantity).to eq(2)
867
931
  end
868
932
  end
869
933
 
@@ -13,6 +13,7 @@ def it_behaves_like_stripe(&block)
13
13
  it_behaves_like 'Card API', &block
14
14
  it_behaves_like 'Charge API', &block
15
15
  it_behaves_like 'Bank API', &block
16
+ it_behaves_like 'External Account API', &block
16
17
  it_behaves_like 'Coupon API', &block
17
18
  it_behaves_like 'Customer API', &block
18
19
  it_behaves_like 'Dispute API', &block
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stripe-ruby-mock
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.3
4
+ version: 2.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gilbert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-22 00:00:00.000000000 Z
11
+ date: 2018-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: stripe
@@ -105,7 +105,6 @@ files:
105
105
  - .gitignore
106
106
  - .rspec
107
107
  - .travis.yml
108
- - ChangeLog.rdoc
109
108
  - Gemfile
110
109
  - LICENSE.txt
111
110
  - README.md
@@ -146,10 +145,12 @@ files:
146
145
  - lib/stripe_mock/request_handlers/customers.rb
147
146
  - lib/stripe_mock/request_handlers/disputes.rb
148
147
  - lib/stripe_mock/request_handlers/events.rb
148
+ - lib/stripe_mock/request_handlers/external_accounts.rb
149
149
  - lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb
150
150
  - lib/stripe_mock/request_handlers/helpers/card_helpers.rb
151
151
  - lib/stripe_mock/request_handlers/helpers/charge_helpers.rb
152
152
  - lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb
153
+ - lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb
153
154
  - lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb
154
155
  - lib/stripe_mock/request_handlers/helpers/token_helpers.rb
155
156
  - lib/stripe_mock/request_handlers/invoice_items.rb
@@ -238,6 +239,7 @@ files:
238
239
  - spec/shared_stripe_examples/customer_examples.rb
239
240
  - spec/shared_stripe_examples/dispute_examples.rb
240
241
  - spec/shared_stripe_examples/error_mock_examples.rb
242
+ - spec/shared_stripe_examples/external_account_examples.rb
241
243
  - spec/shared_stripe_examples/extra_features_examples.rb
242
244
  - spec/shared_stripe_examples/invoice_examples.rb
243
245
  - spec/shared_stripe_examples/invoice_item_examples.rb
@@ -304,6 +306,7 @@ test_files:
304
306
  - spec/shared_stripe_examples/customer_examples.rb
305
307
  - spec/shared_stripe_examples/dispute_examples.rb
306
308
  - spec/shared_stripe_examples/error_mock_examples.rb
309
+ - spec/shared_stripe_examples/external_account_examples.rb
307
310
  - spec/shared_stripe_examples/extra_features_examples.rb
308
311
  - spec/shared_stripe_examples/invoice_examples.rb
309
312
  - spec/shared_stripe_examples/invoice_item_examples.rb
@@ -1,4 +0,0 @@
1
- === 0.1.0 / 2013-04-28
2
-
3
- * Initial release:
4
-