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