1# frozen_string_literal: true
2
3require "test_helper"
4require "low_balance"
5
6ExpiringLock::REDIS = Minitest::Mock.new
7CustomerPlan::REDIS = Minitest::Mock.new
8CustomerFinancials::REDIS = Minitest::Mock.new
9LowBalance::AutoTopUp::REDIS = Minitest::Mock.new
10LowBalance::DB = Minitest::Mock.new
11
12class LowBalanceTest < Minitest::Test
13 def test_for_locked
14 ExpiringLock::REDIS.expect(
15 :set,
16 EMPromise.resolve(nil),
17 ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"]
18 )
19 assert_kind_of LowBalance::Locked, LowBalance.for(customer).sync
20 end
21 em :test_for_locked
22
23 def test_for_no_auto_top_up
24 ExpiringLock::REDIS.expect(
25 :set,
26 EMPromise.resolve("OK"),
27 ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"]
28 )
29 CustomerFinancials::REDIS.expect(
30 :smembers,
31 EMPromise.resolve([]),
32 ["jmp_customer_btc_addresses-test"]
33 )
34 assert_kind_of(
35 LowBalance,
36 LowBalance.for(customer).sync
37 )
38 assert_mock ExpiringLock::REDIS
39 end
40 em :test_for_no_auto_top_up
41
42 def test_for_auto_top_up_on_transaction_amount
43 ExpiringLock::REDIS.expect(
44 :set,
45 EMPromise.resolve("OK"),
46 ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"]
47 )
48 CustomerFinancials::REDIS.expect(
49 :smembers,
50 EMPromise.resolve([]),
51 ["block_credit_cards"]
52 )
53 LowBalance::AutoTopUp::REDIS.expect(
54 :exists,
55 0,
56 ["jmp_auto_top_up_block-abcd"]
57 )
58 braintree_customer = Minitest::Mock.new
59 CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer)
60 payment_methods = OpenStruct.new(payment_methods: [
61 OpenStruct.new(default?: true, unique_number_identifier: "abcd")
62 ])
63 braintree_customer.expect(
64 :find,
65 EMPromise.resolve(payment_methods),
66 ["test"]
67 )
68 assert_kind_of(
69 LowBalance::AutoTopUp,
70 LowBalance.for(customer(auto_top_up_amount: 1), 15).sync
71 )
72 assert_mock ExpiringLock::REDIS
73 assert_mock CustomerFinancials::REDIS
74 assert_mock CustomerFinancials::BRAINTREE
75 assert_mock braintree_customer
76 end
77 em :test_for_auto_top_up_on_transaction_amount
78
79 def test_for_auto_top_up
80 ExpiringLock::REDIS.expect(
81 :set,
82 EMPromise.resolve("OK"),
83 ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"]
84 )
85 CustomerFinancials::REDIS.expect(
86 :smembers,
87 EMPromise.resolve([]),
88 ["block_credit_cards"]
89 )
90 LowBalance::AutoTopUp::REDIS.expect(
91 :exists,
92 0,
93 ["jmp_auto_top_up_block-abcd"]
94 )
95 braintree_customer = Minitest::Mock.new
96 CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer)
97 payment_methods = OpenStruct.new(payment_methods: [
98 OpenStruct.new(default?: true, unique_number_identifier: "abcd")
99 ])
100 braintree_customer.expect(
101 :find,
102 EMPromise.resolve(payment_methods),
103 ["test"]
104 )
105 assert_kind_of(
106 LowBalance::AutoTopUp,
107 LowBalance.for(customer(auto_top_up_amount: 15)).sync
108 )
109 assert_mock ExpiringLock::REDIS
110 assert_mock CustomerFinancials::REDIS
111 assert_mock CustomerFinancials::BRAINTREE
112 assert_mock braintree_customer
113 end
114 em :test_for_auto_top_up
115
116 def test_for_auto_top_up_blocked
117 ExpiringLock::REDIS.expect(
118 :set,
119 EMPromise.resolve("OK"),
120 ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"]
121 )
122 CustomerFinancials::REDIS.expect(
123 :smembers,
124 EMPromise.resolve([]),
125 ["block_credit_cards"]
126 )
127 CustomerFinancials::REDIS.expect(
128 :smembers,
129 EMPromise.resolve([]),
130 ["jmp_customer_btc_addresses-test"]
131 )
132 LowBalance::AutoTopUp::REDIS.expect(
133 :exists,
134 1,
135 ["jmp_auto_top_up_block-blocked"]
136 )
137 braintree_customer = Minitest::Mock.new
138 CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer)
139 payment_methods = OpenStruct.new(payment_methods: [
140 OpenStruct.new(default?: true, unique_number_identifier: "blocked")
141 ])
142 braintree_customer.expect(
143 :find,
144 EMPromise.resolve(payment_methods),
145 ["test"]
146 )
147 assert_kind_of(
148 LowBalance,
149 LowBalance.for(customer(auto_top_up_amount: 15)).sync
150 )
151 assert_mock ExpiringLock::REDIS
152 assert_mock CustomerFinancials::REDIS
153 assert_mock CustomerFinancials::BRAINTREE
154 assert_mock braintree_customer
155 end
156 em :test_for_auto_top_up_blocked
157
158 class AutoTopUpTest < Minitest::Test
159 LowBalance::AutoTopUp::CreditCardSale = Minitest::Mock.new
160
161 def setup
162 @customer = Minitest::Mock.new(
163 customer(auto_top_up_amount: 100, plan_name: "test_usd")
164 )
165 @auto_top_up = LowBalance::AutoTopUp.new(@customer)
166 end
167
168 def test_notify!
169 tx = OpenStruct.new(total: 13)
170 LowBalance::AutoTopUp::CreditCardSale.expect(
171 :create,
172 EMPromise.resolve(tx),
173 [@customer], amount: 100
174 )
175 @auto_top_up.notify!
176 end
177 em :test_notify!
178
179 def test_top_up_amount_when_target_greater_than_expected_balance
180 customer = Minitest::Mock.new(customer(
181 balance: 10,
182 auto_top_up_amount: 15
183 ))
184 auto_top_up = LowBalance::AutoTopUp.new(customer, nil, 30, margin: 5)
185
186 assert_equal 25, auto_top_up.top_up_amount
187 end
188 em :test_top_up_amount_when_target_greater_than_expected_balance
189
190 def test_top_up_amount_when_target_less_than_expected_balance
191 customer = Minitest::Mock.new(customer(
192 balance: 10,
193 auto_top_up_amount: 15
194 ))
195 auto_top_up = LowBalance::AutoTopUp.new(customer, nil, 12, margin: 5)
196
197 assert_equal 15, auto_top_up.top_up_amount
198 end
199 em :test_top_up_amount_when_target_less_than_expected_balance
200
201 def test_negative_balance_target_less_than_expected_balance
202 customer = Minitest::Mock.new(customer(
203 balance: -11,
204 auto_top_up_amount: 15
205 ))
206 auto_top_up = LowBalance::AutoTopUp.new(customer, nil, 35, margin: 5)
207
208 assert_equal 51, auto_top_up.top_up_amount
209 end
210 em :test_negative_balance_target_less_than_expected_balance
211
212 def test_very_low_balance_notify!
213 customer = Minitest::Mock.new(customer(
214 balance: -100,
215 auto_top_up_amount: 15
216 ))
217 auto_top_up = LowBalance::AutoTopUp.new(customer)
218 tx = OpenStruct.new(total: 13)
219
220 LowBalance::AutoTopUp::CreditCardSale.expect(
221 :create,
222 EMPromise.resolve(tx),
223 [customer], amount: 110
224 )
225 auto_top_up.notify!
226 end
227 em :test_very_low_balance_notify!
228
229 def test_border_low_balance_notify!
230 customer = Minitest::Mock.new(customer(
231 balance: -11,
232 auto_top_up_amount: 15
233 ))
234 auto_top_up = LowBalance::AutoTopUp.new(customer)
235 tx = OpenStruct.new(total: 13)
236
237 LowBalance::AutoTopUp::CreditCardSale.expect(
238 :create,
239 EMPromise.resolve(tx),
240 [customer], amount: 21
241 )
242 auto_top_up.notify!
243 end
244 em :test_border_low_balance_notify!
245
246 def test_decline_notify!
247 req = stub_request(:post, "https://api.churnbuster.io/v1/failed_payments")
248 .with(
249 body: {
250 customer: {
251 source: "braintree",
252 source_id: "test",
253 email: "test@smtp.cheogram.com",
254 properties: {}
255 },
256 payment: {
257 source: "braintree",
258 source_id: "tx",
259 amount_in_cents: 10000,
260 currency: "USD"
261 }
262 }.to_json
263 ).to_return(status: 200, body: "", headers: {})
264
265 @customer.expect(
266 :stanza_to,
267 nil,
268 [Matching.new { |m|
269 assert_equal(
270 "Automatic top-up transaction for $100.00 failed: test",
271 m.body
272 )
273 }]
274 )
275 LowBalance::AutoTopUp::CreditCardSale.expect(
276 :create,
277 EMPromise.reject(BraintreeFailure.new(OpenStruct.new(
278 message: "test",
279 transaction: OpenStruct.new(id: "tx")
280 ))),
281 [@customer], amount: 100.to_d
282 )
283 @auto_top_up.notify!.sync
284 assert_mock @customer
285 assert_requested req
286 end
287 em :test_decline_notify!
288 end
289end