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.
- checksums.yaml +4 -4
- data/.env +2 -0
- data/.travis.yml +2 -0
- data/README.md +1 -1
- data/lib/stripe_mock.rb +1 -0
- data/lib/stripe_mock/api/conversion_rate.rb +14 -0
- data/lib/stripe_mock/client.rb +12 -0
- data/lib/stripe_mock/data/list.rb +7 -0
- data/lib/stripe_mock/instance.rb +30 -1
- data/lib/stripe_mock/request_handlers/balance_transactions.rb +18 -2
- data/lib/stripe_mock/request_handlers/charges.rb +12 -3
- data/lib/stripe_mock/request_handlers/coupons.rb +2 -2
- data/lib/stripe_mock/request_handlers/customers.rb +9 -0
- data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +1 -0
- data/lib/stripe_mock/request_handlers/invoices.rb +12 -1
- data/lib/stripe_mock/request_handlers/orders.rb +1 -1
- data/lib/stripe_mock/request_handlers/refunds.rb +1 -1
- data/lib/stripe_mock/request_handlers/subscriptions.rb +16 -10
- data/lib/stripe_mock/server.rb +9 -0
- data/lib/stripe_mock/test_strategies/live.rb +5 -0
- data/lib/stripe_mock/test_strategies/mock.rb +8 -0
- data/lib/stripe_mock/version.rb +1 -1
- data/spec/instance_spec.rb +5 -0
- data/spec/list_spec.rb +16 -3
- data/spec/server_spec.rb +4 -0
- data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
- data/spec/shared_stripe_examples/card_examples.rb +7 -0
- data/spec/shared_stripe_examples/charge_examples.rb +32 -2
- data/spec/shared_stripe_examples/coupon_examples.rb +2 -2
- data/spec/shared_stripe_examples/customer_examples.rb +14 -0
- data/spec/shared_stripe_examples/dispute_examples.rb +1 -1
- data/spec/shared_stripe_examples/invoice_examples.rb +17 -1
- data/spec/shared_stripe_examples/refund_examples.rb +1 -1
- data/spec/shared_stripe_examples/subscription_examples.rb +42 -0
- data/spec/shared_stripe_examples/transfer_examples.rb +16 -0
- data/spec/shared_stripe_examples/webhook_event_examples.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- data/stripe-ruby-mock.gemspec +1 -1
- metadata +14 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a861480c10df772899ac63e55dbc97d84ff3eb2c
|
4
|
+
data.tar.gz: 3d44f183f03df9af022be2b36b49fe45a01ed1e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38a0c8592b9dc4181fdd8730e9b2d2496f852911a480eddc3621a7061d7cd0e1a6e6268a4f722be98483b58b32dd03eb7664135caaa99a638fce5dc70d20d10c
|
7
|
+
data.tar.gz: 44f924ab949f7101b1854f413b7120a0cafc5432c83ae23ab993c4cde6e879445f33ef8fa863a066d24bc06c14d3f9c299a5d6917f58890fd32a76a07ed72be9
|
data/.env
ADDED
data/.travis.yml
CHANGED
data/README.md
CHANGED
data/lib/stripe_mock.rb
CHANGED
@@ -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'
|
data/lib/stripe_mock/client.rb
CHANGED
@@ -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
|
data/lib/stripe_mock/instance.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
54
|
+
charge[:balance_transaction] =
|
54
55
|
balance_transactions[balance_transaction_id]
|
55
56
|
end
|
56
57
|
|
57
|
-
|
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 :
|
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 :
|
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]
|
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
|
@@ -15,7 +15,7 @@ module StripeMock
|
|
15
15
|
return refunds[original_refund[:id]] if original_refund
|
16
16
|
end
|
17
17
|
|
18
|
-
charge =
|
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
|
-
|
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
|
-
|
92
|
-
|
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
|
data/lib/stripe_mock/server.rb
CHANGED
@@ -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
|
@@ -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
|
data/lib/stripe_mock/version.rb
CHANGED
data/spec/instance_spec.rb
CHANGED
@@ -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
|
data/spec/list_spec.rb
CHANGED
@@ -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: [
|
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[
|
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
|
data/spec/server_spec.rb
CHANGED
@@ -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
|
-
|
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('
|
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('
|
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('
|
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([@
|
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(
|
187
|
-
expect(events.map &:type).to include('
|
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
|
data/spec/spec_helper.rb
CHANGED
data/stripe-ruby-mock.gemspec
CHANGED
@@ -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', '
|
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.
|
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
|
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:
|
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:
|
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
|