stripe-ruby-mock 2.5.3 → 2.5.4

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.
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
-