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(customer(auto_top_up_amount: 100))
163			@auto_top_up = LowBalance::AutoTopUp.new(@customer)
164		end
165
166		def test_notify!
167			tx = OpenStruct.new(total: 13)
168			LowBalance::AutoTopUp::CreditCardSale.expect(
169				:create,
170				EMPromise.resolve(tx),
171				[@customer], amount: 100
172			)
173			@auto_top_up.notify!
174		end
175		em :test_notify!
176
177		def test_top_up_amount_when_target_greater_than_expected_balance
178			customer = Minitest::Mock.new(customer(
179				balance: 10,
180				auto_top_up_amount: 15
181			))
182			auto_top_up = LowBalance::AutoTopUp.new(customer, nil, 30, margin: 5)
183
184			assert_equal 25, auto_top_up.top_up_amount
185		end
186		em :test_top_up_amount_when_target_greater_than_expected_balance
187
188		def test_top_up_amount_when_target_less_than_expected_balance
189			customer = Minitest::Mock.new(customer(
190				balance: 10,
191				auto_top_up_amount: 15
192			))
193			auto_top_up = LowBalance::AutoTopUp.new(customer, nil, 12, margin: 5)
194
195			assert_equal 15, auto_top_up.top_up_amount
196		end
197		em :test_top_up_amount_when_target_less_than_expected_balance
198
199		def test_negative_balance_target_less_than_expected_balance
200			customer = Minitest::Mock.new(customer(
201				balance: -11,
202				auto_top_up_amount: 15
203			))
204			auto_top_up = LowBalance::AutoTopUp.new(customer, nil, 35, margin: 5)
205
206			assert_equal 51, auto_top_up.top_up_amount
207		end
208		em :test_negative_balance_target_less_than_expected_balance
209
210		def test_very_low_balance_notify!
211			customer = Minitest::Mock.new(customer(
212				balance: -100,
213				auto_top_up_amount: 15
214			))
215			auto_top_up = LowBalance::AutoTopUp.new(customer)
216			tx = OpenStruct.new(total: 13)
217
218			LowBalance::AutoTopUp::CreditCardSale.expect(
219				:create,
220				EMPromise.resolve(tx),
221				[customer], amount: 110
222			)
223			auto_top_up.notify!
224		end
225		em :test_very_low_balance_notify!
226
227		def test_border_low_balance_notify!
228			customer = Minitest::Mock.new(customer(
229				balance: -11,
230				auto_top_up_amount: 15
231			))
232			auto_top_up = LowBalance::AutoTopUp.new(customer)
233			tx = OpenStruct.new(total: 13)
234
235			LowBalance::AutoTopUp::CreditCardSale.expect(
236				:create,
237				EMPromise.resolve(tx),
238				[customer], amount: 21
239			)
240			auto_top_up.notify!
241		end
242		em :test_border_low_balance_notify!
243
244		def test_decline_notify!
245			@customer.expect(
246				:stanza_to,
247				nil,
248				[Matching.new { |m|
249					assert_equal(
250						"Automatic top-up transaction for $100.00 failed: test",
251						m.body
252					)
253				}]
254			)
255			LowBalance::AutoTopUp::CreditCardSale.expect(
256				:create,
257				EMPromise.reject(RuntimeError.new("test")),
258				[@customer], amount: 100.to_d
259			)
260			@auto_top_up.notify!.sync
261			assert_mock @customer
262		end
263		em :test_decline_notify!
264	end
265end