Skip to content

Commit 91bf0db

Browse files
committed
Add support for automatic Stripe transfers. This includes adding the upsert_stripe_object method to insert or update balance_transactions with transfer id. Also updates balance_transaction API methods to not return the transfer value if present (since Stripe does not expose this value).
1 parent f8fb040 commit 91bf0db

File tree

7 files changed

+95
-2
lines changed

7 files changed

+95
-2
lines changed

lib/stripe_mock/client.rb

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def clear_server_data
7373
timeout_wrap { @pipe.clear_data }
7474
end
7575

76+
def upsert_stripe_object(object, attributes)
77+
timeout_wrap { @pipe.upsert_stripe_object(object, attributes) }
78+
end
79+
7680
def close!
7781
self.cleanup
7882
StripeMock.stop_client(:clear_server_data => false)

lib/stripe_mock/instance.rb

+27
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,33 @@ def generate_webhook_event(event_data)
113113
@events[ event_data[:id] ] = symbolize_names(event_data)
114114
end
115115

116+
def upsert_stripe_object(object, attributes)
117+
# Most Stripe entities can be created via the API. However, some entities are created when other Stripe entities are
118+
# created - such as when BalanceTransactions are created when Charges are created. This method provides the ability
119+
# to create these internal entities.
120+
# It also provides the ability to modify existing Stripe entities.
121+
id = attributes[:id]
122+
if id.nil? || id == ""
123+
# Insert new Stripe object
124+
case object
125+
when :balance_transaction
126+
id = new_balance_transaction('txn', attributes)
127+
else
128+
raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
129+
end
130+
else
131+
# Update existing Stripe object
132+
case object
133+
when :balance_transaction
134+
btxn = assert_existence :balance_transaction, id, @balance_transactions[id]
135+
btxn.merge!(attributes)
136+
else
137+
raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
138+
end
139+
end
140+
id
141+
end
142+
116143
private
117144

118145
def assert_existence(type, id, obj, message=nil)

lib/stripe_mock/request_handlers/balance_transactions.rb

+18-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,27 @@ def BalanceTransactions.included(klass)
99

1010
def get_balance_transaction(route, method_url, params, headers)
1111
route =~ method_url
12-
assert_existence :balance_transaction, $1, balance_transactions[$1]
12+
assert_existence :balance_transaction, $1, hide_additional_attributes(balance_transactions[$1])
1313
end
1414

1515
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
1733
end
1834

1935
end

lib/stripe_mock/server.rb

+5
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,10 @@ def debug?
7676
def ping
7777
true
7878
end
79+
80+
def upsert_stripe_object(object, attributes)
81+
@instance.upsert_stripe_object(object, attributes)
82+
end
83+
7984
end
8085
end

lib/stripe_mock/test_strategies/live.rb

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ def delete_coupon(id)
3030
# do nothing
3131
end
3232
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+
3338
end
3439
end
3540
end

lib/stripe_mock/test_strategies/mock.rb

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ def delete_plan(plan_id)
1414
end
1515
end
1616

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+
1725
end
1826
end
1927
end

spec/shared_stripe_examples/balance_transaction_examples.rb

+28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
shared_examples 'Balance Transaction API' do
44

5+
let(:stripe_helper) { StripeMock.create_test_helper }
6+
57
it "returns an error if balance transaction does not exist" do
68
txn_id = 'txn_xxxxxxxxxxxxxxxxxxxxxxxx'
79

@@ -32,4 +34,30 @@
3234

3335
end
3436

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+
3563
end

0 commit comments

Comments
 (0)