stripe-ruby-mock 2.4.0 → 2.4.1
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 +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
|