stripe-ruby-mock 2.4.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.env +2 -0
  3. data/.travis.yml +2 -0
  4. data/README.md +1 -1
  5. data/lib/stripe_mock.rb +1 -0
  6. data/lib/stripe_mock/api/conversion_rate.rb +14 -0
  7. data/lib/stripe_mock/client.rb +12 -0
  8. data/lib/stripe_mock/data/list.rb +7 -0
  9. data/lib/stripe_mock/instance.rb +30 -1
  10. data/lib/stripe_mock/request_handlers/balance_transactions.rb +18 -2
  11. data/lib/stripe_mock/request_handlers/charges.rb +12 -3
  12. data/lib/stripe_mock/request_handlers/coupons.rb +2 -2
  13. data/lib/stripe_mock/request_handlers/customers.rb +9 -0
  14. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +1 -0
  15. data/lib/stripe_mock/request_handlers/invoices.rb +12 -1
  16. data/lib/stripe_mock/request_handlers/orders.rb +1 -1
  17. data/lib/stripe_mock/request_handlers/refunds.rb +1 -1
  18. data/lib/stripe_mock/request_handlers/subscriptions.rb +16 -10
  19. data/lib/stripe_mock/server.rb +9 -0
  20. data/lib/stripe_mock/test_strategies/live.rb +5 -0
  21. data/lib/stripe_mock/test_strategies/mock.rb +8 -0
  22. data/lib/stripe_mock/version.rb +1 -1
  23. data/spec/instance_spec.rb +5 -0
  24. data/spec/list_spec.rb +16 -3
  25. data/spec/server_spec.rb +4 -0
  26. data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
  27. data/spec/shared_stripe_examples/card_examples.rb +7 -0
  28. data/spec/shared_stripe_examples/charge_examples.rb +32 -2
  29. data/spec/shared_stripe_examples/coupon_examples.rb +2 -2
  30. data/spec/shared_stripe_examples/customer_examples.rb +14 -0
  31. data/spec/shared_stripe_examples/dispute_examples.rb +1 -1
  32. data/spec/shared_stripe_examples/invoice_examples.rb +17 -1
  33. data/spec/shared_stripe_examples/refund_examples.rb +1 -1
  34. data/spec/shared_stripe_examples/subscription_examples.rb +42 -0
  35. data/spec/shared_stripe_examples/transfer_examples.rb +16 -0
  36. data/spec/shared_stripe_examples/webhook_event_examples.rb +2 -2
  37. data/spec/spec_helper.rb +1 -1
  38. data/stripe-ruby-mock.gemspec +1 -1
  39. metadata +14 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2dc4a01998c2f9e1cd85aee1281cf75d5b4aa436
4
- data.tar.gz: 045708a8af619fc7b299055f0822eed79f8cae1f
3
+ metadata.gz: a861480c10df772899ac63e55dbc97d84ff3eb2c
4
+ data.tar.gz: 3d44f183f03df9af022be2b36b49fe45a01ed1e6
5
5
  SHA512:
6
- metadata.gz: 918999885f3cf5e32133f85b535e76ecbe7c482b106b4fe70e9a8de03fcd95132bfd4d43496bc397492da84bfb5eded5c46807e70c2562ee38923e202bf6dd89
7
- data.tar.gz: b9ab01a438f10f7148470641a0b0fddcd32b0fedfc28969a8f52020d483ed64e045e384f1acda6ec422680c54f34c36ace6dcb89b2a01949053e96269e9953a6
6
+ metadata.gz: 38a0c8592b9dc4181fdd8730e9b2d2496f852911a480eddc3621a7061d7cd0e1a6e6268a4f722be98483b58b32dd03eb7664135caaa99a638fce5dc70d20d10c
7
+ data.tar.gz: 44f924ab949f7101b1854f413b7120a0cafc5432c83ae23ab993c4cde6e879445f33ef8fa863a066d24bc06c14d3f9c299a5d6917f58890fd32a76a07ed72be9
data/.env ADDED
@@ -0,0 +1,2 @@
1
+ STRIPE_TEST_SECRET_KEY=sk_test_eFvAvN5rz4GqAbsWxg63Jx79
2
+ STRIPE_TEST_OAUTH_ACCESS_TOKEN=sk_test_WnZmEBIHhMcDltNe98sqWN7z
@@ -1,3 +1,5 @@
1
+ dist: trusty
2
+ sudo: required
1
3
  language: ruby
2
4
  rvm:
3
5
  - 1.9.3
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.4.0', :require => 'stripe_mock'
15
+ gem 'stripe-ruby-mock', '~> 2.4.1', :require => 'stripe_mock'
16
16
 
17
17
  ## Features
18
18
 
@@ -26,6 +26,7 @@ require 'stripe_mock/api/client'
26
26
  require 'stripe_mock/api/server'
27
27
 
28
28
  require 'stripe_mock/api/bank_tokens'
29
+ require 'stripe_mock/api/conversion_rate'
29
30
  require 'stripe_mock/api/card_tokens'
30
31
  require 'stripe_mock/api/debug'
31
32
  require 'stripe_mock/api/errors'
@@ -0,0 +1,14 @@
1
+ module StripeMock
2
+
3
+ def self.set_conversion_rate(value)
4
+ case @state
5
+ when 'local'
6
+ instance.conversion_rate = value
7
+ when 'remote'
8
+ client.set_conversion_rate(value)
9
+ else
10
+ raise UnstartedStateError
11
+ end
12
+ end
13
+
14
+ end
@@ -65,6 +65,14 @@ module StripeMock
65
65
  timeout_wrap { Stripe::Util.symbolize_names @pipe.generate_webhook_event(event_data) }
66
66
  end
67
67
 
68
+ def get_conversion_rate
69
+ timeout_wrap { @pipe.get_data(:conversion_rate) }
70
+ end
71
+
72
+ def set_conversion_rate(value)
73
+ timeout_wrap { @pipe.set_conversion_rate(value) }
74
+ end
75
+
68
76
  def destroy_resource(type, id)
69
77
  timeout_wrap { @pipe.destroy_resource(type, id) }
70
78
  end
@@ -73,6 +81,10 @@ module StripeMock
73
81
  timeout_wrap { @pipe.clear_data }
74
82
  end
75
83
 
84
+ def upsert_stripe_object(object, attributes)
85
+ timeout_wrap { @pipe.upsert_stripe_object(object, attributes) }
86
+ end
87
+
76
88
  def close!
77
89
  self.cleanup
78
90
  StripeMock.stop_client(:clear_server_data => false)
@@ -7,6 +7,13 @@ module StripeMock
7
7
  @data = Array(data.clone)
8
8
  @limit = [[options[:limit] || 10, 100].min, 1].max # restrict @limit to 1..100
9
9
  @starting_after = options[:starting_after]
10
+ if @data.first.is_a?(Hash) && @data.first[:created]
11
+ @data.sort_by! { |x| x[:created] }
12
+ @data.reverse!
13
+ elsif @data.first.respond_to?(:created)
14
+ @data.sort_by { |x| x.created }
15
+ @data.reverse!
16
+ end
10
17
  end
11
18
 
12
19
  def url
@@ -45,7 +45,7 @@ module StripeMock
45
45
  :disputes, :events, :invoices, :invoice_items, :orders, :plans, :recipients,
46
46
  :refunds, :transfers, :subscriptions, :country_spec
47
47
 
48
- attr_accessor :error_queue, :debug
48
+ attr_accessor :error_queue, :debug, :conversion_rate
49
49
 
50
50
  def initialize
51
51
  @accounts = {}
@@ -71,6 +71,7 @@ module StripeMock
71
71
  @error_queue = ErrorQueue.new
72
72
  @id_counter = 0
73
73
  @balance_transaction_counter = 0
74
+ @conversion_rate = 1.0
74
75
 
75
76
  # This is basically a cache for ParamValidators
76
77
  @base_strategy = TestStrategies::Base.new
@@ -113,6 +114,33 @@ module StripeMock
113
114
  @events[ event_data[:id] ] = symbolize_names(event_data)
114
115
  end
115
116
 
117
+ def upsert_stripe_object(object, attributes)
118
+ # Most Stripe entities can be created via the API. However, some entities are created when other Stripe entities are
119
+ # created - such as when BalanceTransactions are created when Charges are created. This method provides the ability
120
+ # to create these internal entities.
121
+ # It also provides the ability to modify existing Stripe entities.
122
+ id = attributes[:id]
123
+ if id.nil? || id == ""
124
+ # Insert new Stripe object
125
+ case object
126
+ when :balance_transaction
127
+ id = new_balance_transaction('txn', attributes)
128
+ else
129
+ raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
130
+ end
131
+ else
132
+ # Update existing Stripe object
133
+ case object
134
+ when :balance_transaction
135
+ btxn = assert_existence :balance_transaction, id, @balance_transactions[id]
136
+ btxn.merge!(attributes)
137
+ else
138
+ raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
139
+ end
140
+ end
141
+ id
142
+ end
143
+
116
144
  private
117
145
 
118
146
  def assert_existence(type, id, obj, message=nil)
@@ -135,6 +163,7 @@ module StripeMock
135
163
  unless amount.nil?
136
164
  # Fee calculation
137
165
  params[:fee] ||= (30 + (amount.abs * 0.029).ceil) * (amount > 0 ? 1 : -1)
166
+ params[:amount] = amount * @conversion_rate
138
167
  end
139
168
  @balance_transactions[id] = Data.mock_balance_transaction(params.merge(id: id))
140
169
  id
@@ -9,11 +9,27 @@ module StripeMock
9
9
 
10
10
  def get_balance_transaction(route, method_url, params, headers)
11
11
  route =~ method_url
12
- assert_existence :balance_transaction, $1, balance_transactions[$1]
12
+ assert_existence :balance_transaction, $1, hide_additional_attributes(balance_transactions[$1])
13
13
  end
14
14
 
15
15
  def list_balance_transactions(route, method_url, params, headers)
16
- Data.mock_list_object(balance_transactions.values, params)
16
+ values = balance_transactions.values
17
+ if params.has_key?(:transfer)
18
+ # If transfer supplied as params, need to filter the btxns returned to only include those with the specified transfer id
19
+ values = values.select{|btxn| btxn[:transfer] == params[:transfer]}
20
+ end
21
+ Data.mock_list_object(values.map{|btxn| hide_additional_attributes(btxn)}, params)
22
+ end
23
+
24
+ private
25
+
26
+ def hide_additional_attributes(btxn)
27
+ # For automatic Stripe transfers, the transfer attribute on balance_transaction stores the transfer which
28
+ # included this balance_transaction. However, it is not exposed as a field returned on a balance_transaction.
29
+ # Therefore, need to not show this attribute if it exists.
30
+ if !btxn.nil?
31
+ btxn.reject{|k,v| k == :transfer }
32
+ end
17
33
  end
18
34
 
19
35
  end
@@ -49,12 +49,13 @@ module StripeMock
49
49
  params.merge :id => id,
50
50
  :balance_transaction => balance_transaction_id)
51
51
 
52
+ charge = charges[id].clone
52
53
  if params[:expand] == ['balance_transaction']
53
- charges[id][:balance_transaction] =
54
+ charge[:balance_transaction] =
54
55
  balance_transactions[balance_transaction_id]
55
56
  end
56
57
 
57
- charges[id]
58
+ charge
58
59
  end
59
60
 
60
61
  def update_charge(route, method_url, params, headers)
@@ -87,7 +88,15 @@ module StripeMock
87
88
  def get_charge(route, method_url, params, headers)
88
89
  route =~ method_url
89
90
  charge_id = $1 || params[:charge]
90
- assert_existence :charge, charge_id, charges[charge_id]
91
+ charge = assert_existence :charge, charge_id, charges[charge_id]
92
+
93
+ charge = charge.clone
94
+ if params[:expand] == ['balance_transaction']
95
+ balance_transaction = balance_transactions[charge[:balance_transaction]]
96
+ charge[:balance_transaction] = balance_transaction
97
+ end
98
+
99
+ charge
91
100
  end
92
101
 
93
102
  def capture_charge(route, method_url, params, headers)
@@ -17,12 +17,12 @@ module StripeMock
17
17
 
18
18
  def get_coupon(route, method_url, params, headers)
19
19
  route =~ method_url
20
- assert_existence :id, $1, coupons[$1]
20
+ assert_existence :coupon, $1, coupons[$1]
21
21
  end
22
22
 
23
23
  def delete_coupon(route, method_url, params, headers)
24
24
  route =~ method_url
25
- assert_existence :id, $1, coupons.delete($1)
25
+ assert_existence :coupon, $1, coupons.delete($1)
26
26
  end
27
27
 
28
28
  def list_coupons(route, method_url, params, headers)
@@ -8,6 +8,7 @@ module StripeMock
8
8
  klass.add_handler 'get /v1/customers/([^/]*)', :get_customer
9
9
  klass.add_handler 'delete /v1/customers/([^/]*)', :delete_customer
10
10
  klass.add_handler 'get /v1/customers', :list_customers
11
+ klass.add_handler 'delete /v1/customers/([^/]*)/discount', :delete_customer_discount
11
12
  end
12
13
 
13
14
  def new_customer(route, method_url, params, headers)
@@ -114,6 +115,14 @@ module StripeMock
114
115
  Data.mock_list_object(customers.values, params)
115
116
  end
116
117
 
118
+ def delete_customer_discount(route, method_url, params, headers)
119
+ route =~ method_url
120
+ cus = assert_existence :customer, $1, customers[$1]
121
+
122
+ cus[:discount] = nil
123
+
124
+ cus
125
+ end
117
126
  end
118
127
  end
119
128
  end
@@ -77,6 +77,7 @@ module StripeMock
77
77
  is_customer = resource.has_key?(:sources)
78
78
  new_default = cards_or_sources[:data].count > 0 ? cards_or_sources[:data].first[:id] : nil
79
79
  resource[:default_card] = new_default unless is_customer
80
+ resource[:sources][:total_count] = cards_or_sources[:data].count if is_customer
80
81
  resource[:default_source] = new_default if is_customer
81
82
  card
82
83
  end
@@ -52,7 +52,8 @@ module StripeMock
52
52
  def pay_invoice(route, method_url, params, headers)
53
53
  route =~ method_url
54
54
  assert_existence :invoice, $1, invoices[$1]
55
- invoices[$1].merge!(:paid => true, :attempted => true, :charge => 'ch_1fD6uiR9FAA2zc')
55
+ charge = invoice_charge(invoices[$1])
56
+ invoices[$1].merge!(:paid => true, :attempted => true, :charge => charge[:id])
56
57
  end
57
58
 
58
59
  def upcoming_invoice(route, method_url, params, headers)
@@ -93,6 +94,16 @@ module StripeMock
93
94
  })
94
95
  end
95
96
 
97
+ ## charge the customer on the invoice, if one does not exist, create
98
+ #anonymous charge
99
+ def invoice_charge(invoice)
100
+ begin
101
+ new_charge(nil, nil, {customer: invoice[:customer]["id"], amount: invoice[:amount_due], currency: 'usd'}, nil)
102
+ rescue Stripe::InvalidRequestError
103
+ new_charge(nil, nil, {source: generate_card_token, amount: invoice[:amount_due], currency: 'usd'}, nil)
104
+ end
105
+ end
106
+
96
107
  end
97
108
  end
98
109
  end
@@ -45,7 +45,7 @@ module StripeMock
45
45
  end
46
46
  end
47
47
 
48
- if [:created, :paid, :canceled, :fulfilled, :returned].includes? params[:status]
48
+ if %w(created paid canceled fulfilled returned).include? params[:status]
49
49
  order[:status] = params[:status]
50
50
  end
51
51
  order
@@ -15,7 +15,7 @@ module StripeMock
15
15
  return refunds[original_refund[:id]] if original_refund
16
16
  end
17
17
 
18
- charge = get_charge(route, method_url, params, headers)
18
+ charge = assert_existence :charge, params[:charge], charges[params[:charge]]
19
19
  params[:amount] ||= charge[:amount]
20
20
  id = new_id('re')
21
21
  bal_trans_params = {
@@ -46,12 +46,12 @@ module StripeMock
46
46
  customer[:default_source] = new_card[:id]
47
47
  end
48
48
 
49
- # Ensure customer has card to charge if plan has no trial and is not free
50
- verify_card_present(customer, plan, params)
51
-
52
49
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
53
50
  subscription.merge!(custom_subscription_params(plan, customer, params))
54
51
 
52
+ # Ensure customer has card to charge if plan has no trial and is not free
53
+ verify_card_present(customer, plan, subscription, params)
54
+
55
55
  if params[:coupon]
56
56
  coupon_id = params[:coupon]
57
57
 
@@ -79,7 +79,8 @@ module StripeMock
79
79
  plan_id = params[:plan].to_s
80
80
  plan = assert_existence :plan, plan_id, plans[plan_id]
81
81
 
82
- customer_id = params[:customer].to_s
82
+ customer = params[:customer]
83
+ customer_id = customer.is_a?(Stripe::Customer) ? customer[:id] : customer.to_s
83
84
  customer = assert_existence :customer, customer_id, customers[customer_id]
84
85
 
85
86
  if params[:source]
@@ -88,12 +89,18 @@ module StripeMock
88
89
  customer[:default_source] = new_card[:id]
89
90
  end
90
91
 
91
- # Ensure customer has card to charge if plan has no trial and is not free
92
- verify_card_present(customer, plan, params)
92
+ allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days)
93
+ unknown_params = params.keys - allowed_params.map(&:to_sym)
94
+ if unknown_params.length > 0
95
+ raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, 400)
96
+ end
93
97
 
94
98
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
95
99
  subscription.merge!(custom_subscription_params(plan, customer, params))
96
100
 
101
+ # Ensure customer has card to charge if plan has no trial and is not free
102
+ verify_card_present(customer, plan, subscription, params)
103
+
97
104
  if params[:coupon]
98
105
  coupon_id = params[:coupon]
99
106
 
@@ -169,7 +176,7 @@ module StripeMock
169
176
 
170
177
  assert_existence :plan, plan_name, plan
171
178
  params[:plan] = plan if params[:plan]
172
- verify_card_present(customer, plan)
179
+ verify_card_present(customer, plan, subscription)
173
180
 
174
181
  if subscription[:cancel_at_period_end]
175
182
  subscription[:cancel_at_period_end] = false
@@ -216,9 +223,8 @@ module StripeMock
216
223
 
217
224
  private
218
225
 
219
- def verify_card_present(customer, plan, params={})
220
- if customer[:default_source].nil? && customer[:trial_end].nil? && plan[:trial_period_days].nil? &&
221
- plan[:amount] != 0 && plan[:trial_end].nil? && params[:trial_end].nil?
226
+ def verify_card_present(customer, plan, subscription, params={})
227
+ if customer[:default_source].nil? && customer[:trial_end].nil? && plan[:trial_period_days].nil? && plan[:amount] != 0 && plan[:trial_end].nil? && params[:trial_end].nil? && (subscription.nil? || subscription[:trial_end].nil? || subscription[:trial_end] == 'now')
222
228
  raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, 400)
223
229
  end
224
230
  end
@@ -65,6 +65,10 @@ module StripeMock
65
65
  @instance.generate_webhook_event(event_data)
66
66
  end
67
67
 
68
+ def set_conversion_rate(value)
69
+ @instance.conversion_rate = value
70
+ end
71
+
68
72
  def error_queue
69
73
  @instance.error_queue
70
74
  end
@@ -76,5 +80,10 @@ module StripeMock
76
80
  def ping
77
81
  true
78
82
  end
83
+
84
+ def upsert_stripe_object(object, attributes)
85
+ @instance.upsert_stripe_object(object, attributes)
86
+ end
87
+
79
88
  end
80
89
  end
@@ -30,6 +30,11 @@ module StripeMock
30
30
  # do nothing
31
31
  end
32
32
  end
33
+
34
+ def upsert_stripe_object(object, attributes)
35
+ raise UnsupportedRequestError.new "Updating or inserting Stripe objects in Live mode not supported"
36
+ end
37
+
33
38
  end
34
39
  end
35
40
  end
@@ -14,6 +14,14 @@ module StripeMock
14
14
  end
15
15
  end
16
16
 
17
+ def upsert_stripe_object(object, attributes = {})
18
+ if StripeMock.state == 'remote'
19
+ StripeMock.client.upsert_stripe_object(object, attributes)
20
+ elsif StripeMock.state == 'local'
21
+ StripeMock.instance.upsert_stripe_object(object, attributes)
22
+ end
23
+ end
24
+
17
25
  end
18
26
  end
19
27
  end
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "2.4.0"
3
+ VERSION = "2.4.1"
4
4
  end
@@ -47,4 +47,9 @@ describe StripeMock::Instance do
47
47
  StripeMock.start
48
48
  expect(StripeMock.instance.debug).to eq(false)
49
49
  end
50
+
51
+ it "can set a conversion rate" do
52
+ StripeMock.set_conversion_rate(1.25)
53
+ expect(StripeMock.instance.conversion_rate).to eq(1.25)
54
+ end
50
55
  end
@@ -34,6 +34,20 @@ describe StripeMock::Data::List do
34
34
  expect(list.url).to eq("/v1/customers")
35
35
  end
36
36
 
37
+ it "returns in descending order if created available" do
38
+ charge_newer = Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token, created: 5)
39
+ charge_older = Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token, created: 4)
40
+ list = StripeMock::Data::List.new([charge_older, charge_newer])
41
+ hash = list.to_h
42
+
43
+ expect(hash).to eq(
44
+ object: "list",
45
+ data: [charge_newer, charge_older],
46
+ url: "/v1/charges",
47
+ has_more: false
48
+ )
49
+ end
50
+
37
51
  it "eventually gets turned into a hash" do
38
52
  charge1 = Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token)
39
53
  charge2 = Stripe::Charge.create(amount: 1, currency: 'usd', source: stripe_helper.generate_card_token)
@@ -43,7 +57,7 @@ describe StripeMock::Data::List do
43
57
 
44
58
  expect(hash).to eq(
45
59
  object: "list",
46
- data: [charge1, charge2, charge3],
60
+ data: [charge3, charge2, charge1],
47
61
  url: "/v1/charges",
48
62
  has_more: false
49
63
  )
@@ -111,9 +125,8 @@ describe StripeMock::Data::List do
111
125
  data[89] = new_charge
112
126
  list = StripeMock::Data::List.new(data, starting_after: new_charge.id)
113
127
  hash = list.to_h
114
-
115
128
  expect(hash[:data].size).to eq(10)
116
- expect(hash[:data]).to eq(data[90, 10])
129
+ expect(hash[:data]).to eq(data[79, 10].reverse)
117
130
  end
118
131
 
119
132
  it "raises an error if starting_after cursor is not found" do
@@ -132,4 +132,8 @@ describe 'StripeMock Server', :mock_server => true do
132
132
  end
133
133
  end
134
134
 
135
+ it "can set a conversion rate" do
136
+ StripeMock.set_conversion_rate(1.2)
137
+ expect(StripeMock.client.get_conversion_rate).to eq(1.2)
138
+ end
135
139
  end
@@ -2,6 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  shared_examples 'Balance Transaction API' do
4
4
 
5
+ let(:stripe_helper) { StripeMock.create_test_helper }
6
+
5
7
  it "returns an error if balance transaction does not exist" do
6
8
  txn_id = 'txn_xxxxxxxxxxxxxxxxxxxxxxxx'
7
9
 
@@ -32,4 +34,30 @@ shared_examples 'Balance Transaction API' do
32
34
 
33
35
  end
34
36
 
37
+ it 'retrieves balance transactions for an automated transfer' do
38
+ transfer_id = Stripe::Transfer.create({ amount: 2730, currency: "usd" })
39
+
40
+ # verify transfer currently has no balance transactions
41
+ transfer_transactions = Stripe::BalanceTransaction.all({transfer: transfer_id})
42
+ expect(transfer_transactions.count).to eq(0)
43
+
44
+ # verify we can create a new balance transaction associated with the transfer
45
+ new_txn_id = stripe_helper.upsert_stripe_object(:balance_transaction, {amount: 12300, transfer: transfer_id})
46
+ new_txn = Stripe::BalanceTransaction.retrieve(new_txn_id)
47
+ expect(new_txn).to be_a(Stripe::BalanceTransaction)
48
+ expect(new_txn.amount).to eq(12300)
49
+ # although transfer was specified as an attribute on the balance_transaction, it should not be returned in the object
50
+ expect{new_txn.transfer}.to raise_error(NoMethodError)
51
+
52
+ # verify we can update an existing balance transaction to associate with the transfer
53
+ existing_txn_id = 'txn_05RsQX2eZvKYlo2C0FRTGSSA'
54
+ existing_txn = Stripe::BalanceTransaction.retrieve(existing_txn_id)
55
+ stripe_helper.upsert_stripe_object(:balance_transaction, {id: existing_txn_id, transfer: transfer_id})
56
+
57
+ # now verify that only these balance transactions are retrieved with the transfer
58
+ transfer_transactions = Stripe::BalanceTransaction.all({transfer: transfer_id})
59
+ expect(transfer_transactions.count).to eq(2)
60
+ expect(transfer_transactions.map &:id).to include(new_txn_id, existing_txn_id)
61
+ end
62
+
35
63
  end
@@ -166,6 +166,13 @@ shared_examples 'Card API' do
166
166
  expect(retrieved_cus.default_source).to be_nil
167
167
  end
168
168
 
169
+ it 'updates total_count if deleted' do
170
+ card.delete
171
+ sources = Stripe::Customer.retrieve(customer.id).sources
172
+
173
+ expect(sources.total_count).to eq 0
174
+ end
175
+
169
176
  context "deletion when the user has two cards" do
170
177
  let!(:card_token_2) { stripe_helper.generate_card_token(last4: "1123", exp_month: 11, exp_year: 2099) }
171
178
  let!(:card_2) { customer.sources.create(source: card_token_2) }
@@ -174,7 +174,23 @@ shared_examples 'Charge API' do
174
174
  expect(bal_trans.source).to eq(charge.source)
175
175
  end
176
176
 
177
- it "can expand balance transaction" do
177
+ context 'when conversion rate is set' do
178
+ it "balance transaction stores amount converted from charge currency to USD" do
179
+ StripeMock.set_conversion_rate(1.2)
180
+
181
+ charge = Stripe::Charge.create({
182
+ amount: 300,
183
+ currency: 'CAD',
184
+ source: stripe_helper.generate_card_token
185
+ })
186
+ bal_trans = Stripe::BalanceTransaction.retrieve(charge.balance_transaction)
187
+ expect(bal_trans.amount).to eq(charge.amount * 1.2)
188
+ expect(bal_trans.fee).to eq(39)
189
+ expect(bal_trans.currency).to eq('usd')
190
+ end
191
+ end
192
+
193
+ it "can expand balance transaction when creating a charge" do
178
194
  charge = Stripe::Charge.create({
179
195
  amount: 300,
180
196
  currency: 'USD',
@@ -196,6 +212,20 @@ shared_examples 'Charge API' do
196
212
  expect(charge.amount).to eq(original.amount)
197
213
  end
198
214
 
215
+ it "can expand balance transaction when retrieving a charge" do
216
+ original = Stripe::Charge.create({
217
+ amount: 300,
218
+ currency: 'USD',
219
+ source: stripe_helper.generate_card_token
220
+ })
221
+ charge = Stripe::Charge.retrieve(
222
+ id: original.id,
223
+ expand: ['balance_transaction']
224
+ )
225
+
226
+ expect(charge.balance_transaction).to be_a(Stripe::BalanceTransaction)
227
+ end
228
+
199
229
  it "cannot retrieve a charge that doesn't exist" do
200
230
  expect { Stripe::Charge.retrieve('nope') }.to raise_error {|e|
201
231
  expect(e).to be_a Stripe::InvalidRequestError
@@ -310,7 +340,7 @@ shared_examples 'Charge API' do
310
340
  end
311
341
 
312
342
  it "stores all charges in memory" do
313
- expect(Stripe::Charge.all.data.map(&:id)).to eq([@charge.id, @charge2.id])
343
+ expect(Stripe::Charge.all.data.map(&:id).reverse).to eq([@charge.id, @charge2.id])
314
344
  end
315
345
 
316
346
  it "defaults count to 10 charges" do
@@ -56,7 +56,7 @@ shared_examples 'Coupon API' do
56
56
  it "cannot retrieve a stripe coupon that doesn't exist" do
57
57
  expect { Stripe::Coupon.retrieve('nope') }.to raise_error {|e|
58
58
  expect(e).to be_a Stripe::InvalidRequestError
59
- expect(e.param).to eq('id')
59
+ expect(e.param).to eq('coupon')
60
60
  expect(e.http_status).to eq(404)
61
61
  }
62
62
  end
@@ -71,7 +71,7 @@ shared_examples 'Coupon API' do
71
71
 
72
72
  expect { Stripe::Coupon.retrieve(coupon.id) }.to raise_error {|e|
73
73
  expect(e).to be_a Stripe::InvalidRequestError
74
- expect(e.param).to eq('id')
74
+ expect(e.param).to eq('coupon')
75
75
  expect(e.http_status).to eq(404)
76
76
  }
77
77
  end
@@ -387,4 +387,18 @@ shared_examples 'Customer API' do
387
387
  }.not_to raise_error
388
388
  end
389
389
 
390
+ it "deletes a stripe customer discount" do
391
+ original = Stripe::Customer.create(id: 'test_customer_update')
392
+
393
+ coupon = Stripe::Coupon.create(id: "10PERCENT", duration: 'once')
394
+ original.coupon = coupon.id
395
+ original.save
396
+
397
+ expect(original.discount.coupon).to be_a Stripe::Coupon
398
+
399
+ original.delete_discount
400
+
401
+ customer = Stripe::Customer.retrieve("test_customer_update")
402
+ expect(customer.discount).to be nil
403
+ end
390
404
  end
@@ -79,7 +79,7 @@ shared_examples 'Dispute API' do
79
79
  disputes = Stripe::Dispute.all(limit: 3)
80
80
 
81
81
  expect(disputes.count).to eq(3)
82
- expect(disputes.map &:id).to include('dp_05RsQX2eZvKYlo2C0FRTGSSA','dp_15RsQX2eZvKYlo2C0ERTYUIA', 'dp_25RsQX2eZvKYlo2C0ZXCVBNM')
82
+ expect(disputes.map &:id).to include('dp_95RsQX2eZvKYlo2C0EDFRYUI','dp_85RsQX2eZvKYlo2C0UJMCDET', 'dp_75RsQX2eZvKYlo2C0EDCXSWQ')
83
83
  end
84
84
 
85
85
  end
@@ -76,18 +76,34 @@ shared_examples 'Invoice API' do
76
76
  context "paying an invoice" do
77
77
  before do
78
78
  @invoice = Stripe::Invoice.create
79
- @invoice.pay
80
79
  end
81
80
 
82
81
  it 'updates attempted and paid flags' do
82
+ @invoice.pay
83
83
  expect(@invoice.attempted).to eq(true)
84
84
  expect(@invoice.paid).to eq(true)
85
85
  end
86
86
 
87
+ it 'creates a new charge object' do
88
+ expect{ @invoice.pay }.to change { Stripe::Charge.list.data.count }.by 1
89
+ end
90
+
87
91
  it 'sets the charge attribute' do
92
+ @invoice.pay
88
93
  expect(@invoice.charge).to be_a String
89
94
  expect(@invoice.charge.length).to be > 0
90
95
  end
96
+
97
+ it 'charges the invoice customers default card' do
98
+ customer = Stripe::Customer.create({
99
+ source: stripe_helper.generate_card_token
100
+ })
101
+ customer_invoice = Stripe::Invoice.create({customer: customer})
102
+
103
+ customer_invoice.pay
104
+
105
+ expect(Stripe::Charge.list.data.first.customer).to eq customer.id
106
+ end
91
107
  end
92
108
 
93
109
  context "retrieving upcoming invoice" do
@@ -262,7 +262,7 @@ shared_examples 'Refund API' do
262
262
  end
263
263
 
264
264
  it "stores all charges in memory" do
265
- expect(Stripe::Refund.all.data.map(&:id)).to eq([@refund.id, @refund2.id])
265
+ expect(Stripe::Refund.all.data.map(&:id)).to eq([@refund2.id, @refund.id])
266
266
  end
267
267
 
268
268
  it "defaults count to 10 charges" do
@@ -35,6 +35,36 @@ shared_examples 'Customer Subscriptions' do
35
35
  expect(customer.subscriptions.data.first.metadata.example).to eq( "yes" )
36
36
  end
37
37
 
38
+ it 'when customer object provided' do
39
+ plan = stripe_helper.create_plan(id: 'silver', name: 'Silver Plan', amount: 4999, currency: 'usd')
40
+ customer = Stripe::Customer.create(source: gen_card_tk)
41
+
42
+ expect(customer.subscriptions.data).to be_empty
43
+ expect(customer.subscriptions.count).to eq(0)
44
+
45
+ sub = Stripe::Subscription.create({ plan: 'silver', customer: customer, metadata: { foo: "bar", example: "yes" } })
46
+
47
+ expect(sub.object).to eq('subscription')
48
+ expect(sub.plan.to_hash).to eq(plan.to_hash)
49
+ expect(sub.metadata.foo).to eq( "bar" )
50
+ expect(sub.metadata.example).to eq( "yes" )
51
+
52
+ customer = Stripe::Customer.retrieve(customer.id)
53
+ expect(customer.subscriptions.data).to_not be_empty
54
+ expect(customer.subscriptions.count).to eq(1)
55
+ expect(customer.subscriptions.data.length).to eq(1)
56
+ expect(customer.charges.data.length).to eq(1)
57
+ expect(customer.currency).to eq( "usd" )
58
+
59
+ expect(customer.subscriptions.data.first.id).to eq(sub.id)
60
+ expect(customer.subscriptions.data.first.plan.to_hash).to eq(plan.to_hash)
61
+
62
+ expect(customer.subscriptions.data.first.customer).to eq(customer.id)
63
+
64
+ expect(customer.subscriptions.data.first.metadata.foo).to eq( "bar" )
65
+ expect(customer.subscriptions.data.first.metadata.example).to eq( "yes" )
66
+ end
67
+
38
68
  it "adds a new subscription to customer (string/symbol agnostic)" do
39
69
  customer = Stripe::Customer.create(source: gen_card_tk)
40
70
  expect(customer.subscriptions.count).to eq(0)
@@ -185,6 +215,18 @@ shared_examples 'Customer Subscriptions' do
185
215
  }
186
216
  end
187
217
 
218
+ it 'when attempting to create a new subscription with the params trial', focus: true, live: true do
219
+ plan = stripe_helper.create_plan(id: 'trial', amount: 999)
220
+ customer = Stripe::Customer.create(source: gen_card_tk)
221
+
222
+ expect{ Stripe::Subscription.create(plan: plan.id, customer: customer.id, trial: 10) }.to raise_error {|e|
223
+ expect(e).to be_a Stripe::InvalidRequestError
224
+ expect(e.http_status).to eq(400)
225
+ expect(e.param).to eq('trial')
226
+ expect(e.message).to match /Received unknown parameter/
227
+ }
228
+ end
229
+
188
230
  it "subscribes a customer with no card to a plan with a free trial" do
189
231
  plan = stripe_helper.create_plan(id: 'trial', amount: 999, trial_period_days: 14)
190
232
  customer = Stripe::Customer.create(id: 'cardless')
@@ -78,4 +78,20 @@ shared_examples 'Transfer API' do
78
78
  expect(e.http_status).to eq(400)
79
79
  }
80
80
  end
81
+
82
+ it 'when amount is negative', focus: true, live: true do
83
+ rec = Stripe::Recipient.create({
84
+ type: 'individual',
85
+ name: 'Alex Smith',
86
+ })
87
+ expect { Stripe::Transfer.create(amount: '-400',
88
+ currency: 'usd',
89
+ recipient: rec.id,
90
+ description: 'Transfer for test@example.com') }.to raise_error { |e|
91
+ expect(e).to be_a Stripe::InvalidRequestError
92
+ expect(e.param).to eq('amount')
93
+ expect(e.message).to match(/^Invalid.*integer/)
94
+ expect(e.http_status).to eq(400)
95
+ }
96
+ end
81
97
  end
@@ -183,8 +183,8 @@ shared_examples 'Webhook Events API' do
183
183
  events = Stripe::Event.all(limit: 3)
184
184
 
185
185
  expect(events.count).to eq(3)
186
- expect(events.map &:id).to include(customer_created_event.id, plan_created_event.id, coupon_created_event.id)
187
- expect(events.map &:type).to include('customer.created', 'plan.created', 'coupon.created')
186
+ expect(events.map &:id).to include(invoice_item_created_event.id, invoice_created_event.id, coupon_created_event.id)
187
+ expect(events.map &:type).to include('invoiceitem.created', 'invoice.created', 'coupon.created')
188
188
  end
189
189
 
190
190
  end
@@ -46,7 +46,7 @@ RSpec.configure do |c|
46
46
  StripeMock.stub(:stop).and_return(nil)
47
47
  Stripe.api_key = api_key
48
48
  end
49
- c.after(:each) { sleep 1 }
49
+ c.after(:each) { sleep 0.01 }
50
50
  else
51
51
  c.filter_run_excluding :oauth => true
52
52
  Stripe.api_key ||= ''
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ['lib']
19
19
 
20
- gem.add_dependency 'stripe', '~> 1.31'
20
+ gem.add_dependency 'stripe', ['>= 1.31.0', '<= 1.58.0']
21
21
  gem.add_dependency 'multi_json', '~> 1.0'
22
22
  gem.add_dependency 'dante', '>= 0.2.0'
23
23
 
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stripe-ruby-mock
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gilbert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-10 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: stripe
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.31.0
20
+ - - <=
18
21
  - !ruby/object:Gem::Version
19
- version: '1.31'
22
+ version: 1.58.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - ~>
27
+ - - '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.31.0
30
+ - - <=
25
31
  - !ruby/object:Gem::Version
26
- version: '1.31'
32
+ version: 1.58.0
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: multi_json
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -101,6 +107,7 @@ executables:
101
107
  extensions: []
102
108
  extra_rdoc_files: []
103
109
  files:
110
+ - .env
104
111
  - .gitignore
105
112
  - .rspec
106
113
  - .travis.yml
@@ -114,6 +121,7 @@ files:
114
121
  - lib/stripe_mock/api/bank_tokens.rb
115
122
  - lib/stripe_mock/api/card_tokens.rb
116
123
  - lib/stripe_mock/api/client.rb
124
+ - lib/stripe_mock/api/conversion_rate.rb
117
125
  - lib/stripe_mock/api/debug.rb
118
126
  - lib/stripe_mock/api/errors.rb
119
127
  - lib/stripe_mock/api/global_id_prefix.rb