test_credit_card_sale.rb

  1# frozen_string_literal: true
  2
  3require "test_helper"
  4require "credit_card_sale"
  5require "customer"
  6require "transaction"
  7
  8CreditCardSale::BRAINTREE = Minitest::Mock.new
  9CreditCardSale::REDIS = Minitest::Mock.new
 10TrustLevelRepo::REDIS = Minitest::Mock.new
 11TrustLevelRepo::DB = Minitest::Mock.new
 12CustomerFinancials::REDIS = Minitest::Mock.new
 13
 14class CreditCardSaleTest < Minitest::Test
 15	FAKE_BRAINTREE_TRANSACTION =
 16		OpenStruct.new(
 17			customer_details: OpenStruct.new(id: "customer"),
 18			id: "transaction",
 19			created_at: Time.at(0),
 20			amount: 12
 21		)
 22
 23	def test_sale_fails
 24		CreditCardSale::REDIS.expect(
 25			:exists,
 26			EMPromise.resolve(0),
 27			["jmp_customer_credit_card_lock-test"]
 28		)
 29		TrustLevelRepo::REDIS.expect(
 30			:get,
 31			EMPromise.resolve("Customer"),
 32			["jmp_customer_trust_level-test"]
 33		)
 34		TrustLevelRepo::DB.expect(
 35			:query_one,
 36			EMPromise.resolve({}),
 37			[String, "test"], default: {}
 38		)
 39		CustomerFinancials::REDIS.expect(
 40			:get,
 41			EMPromise.resolve("1"),
 42			["jmp_pay_decline-test"]
 43		)
 44		CustomerFinancials::REDIS.expect(
 45			:incr,
 46			EMPromise.resolve(nil),
 47			["jmp_pay_decline-test"]
 48		)
 49		CustomerFinancials::REDIS.expect(
 50			:expire,
 51			EMPromise.resolve(nil),
 52			["jmp_pay_decline-test", 60 * 60 * 24]
 53		)
 54		braintree_transaction = Minitest::Mock.new
 55		CreditCardSale::BRAINTREE.expect(:transaction, braintree_transaction)
 56		braintree_transaction.expect(
 57			:sale,
 58			EMPromise.resolve(
 59				OpenStruct.new(success?: false, message: "declined")
 60			),
 61			amount: 99,
 62			merchant_account_id: "merchant_usd",
 63			options: { submit_for_settlement: true },
 64			payment_method_token: "token"
 65		)
 66		assert_raises(BraintreeFailure) do
 67			CreditCardSale.new(
 68				customer(plan_name: "test_usd"),
 69				amount: 99,
 70				payment_method: OpenStruct.new(token: "token")
 71			).sale.sync
 72		end
 73		assert_mock CustomerFinancials::REDIS
 74		assert_mock CreditCardSale::REDIS
 75		assert_mock TrustLevelRepo::REDIS
 76		assert_mock TrustLevelRepo::DB
 77	end
 78	em :test_sale_fails
 79
 80	def test_sale_locked
 81		CreditCardSale::REDIS.expect(
 82			:exists,
 83			EMPromise.resolve(1),
 84			["jmp_customer_credit_card_lock-test"]
 85		)
 86		TrustLevelRepo::REDIS.expect(
 87			:get,
 88			EMPromise.resolve("Customer"),
 89			["jmp_customer_trust_level-test"]
 90		)
 91		TrustLevelRepo::DB.expect(
 92			:query_one,
 93			EMPromise.resolve({}),
 94			[String, "test"], default: {}
 95		)
 96		CustomerFinancials::REDIS.expect(
 97			:get,
 98			EMPromise.resolve("0"),
 99			["jmp_pay_decline-test"]
100		)
101		assert_raises("locked") do
102			CreditCardSale.new(
103				customer(plan_name: "test_usd"),
104				amount: 123,
105				payment_method: OpenStruct.new(token: "token")
106			).sale.sync
107		end
108		assert_mock CustomerFinancials::REDIS
109		assert_mock CreditCardSale::REDIS
110		assert_mock TrustLevelRepo::REDIS
111		assert_mock TrustLevelRepo::DB
112	end
113	em :test_sale_locked
114
115	def test_sale_amount_too_high
116		CreditCardSale::REDIS.expect(
117			:exists,
118			EMPromise.resolve(0),
119			["jmp_customer_credit_card_lock-test"]
120		)
121		TrustLevelRepo::REDIS.expect(
122			:get,
123			EMPromise.resolve("Customer"),
124			["jmp_customer_trust_level-test"]
125		)
126		TrustLevelRepo::DB.expect(
127			:query_one,
128			EMPromise.resolve({}),
129			[String, "test"], default: {}
130		)
131		CustomerFinancials::REDIS.expect(
132			:get,
133			EMPromise.resolve("0"),
134			["jmp_pay_decline-test"]
135		)
136
137		assert_raises(AmountTooHighError) do
138			CreditCardSale.new(
139				customer(plan_name: "test_usd"),
140				amount: 131,
141				payment_method: OpenStruct.new(token: "token")
142			).sale.sync
143		end
144
145		assert_mock CustomerFinancials::REDIS
146		assert_mock CreditCardSale::REDIS
147		assert_mock TrustLevelRepo::REDIS
148		assert_mock TrustLevelRepo::DB
149	end
150	em :test_sale_amount_too_high
151
152	def test_sale_too_many_declines
153		CreditCardSale::REDIS.expect(
154			:exists,
155			EMPromise.resolve(0),
156			["jmp_customer_credit_card_lock-test"]
157		)
158		TrustLevelRepo::REDIS.expect(
159			:get,
160			EMPromise.resolve("Customer"),
161			["jmp_customer_trust_level-test"]
162		)
163		TrustLevelRepo::DB.expect(
164			:query_one,
165			EMPromise.resolve({}),
166			[String, "test"], default: {}
167		)
168		CustomerFinancials::REDIS.expect(
169			:get,
170			EMPromise.resolve("3"),
171			["jmp_pay_decline-test"]
172		)
173
174		assert_raises(DeclinedError) do
175			CreditCardSale.new(
176				customer(plan_name: "test_usd"),
177				amount: 50,
178				payment_method: OpenStruct.new(token: "token")
179			).sale.sync
180		end
181
182		assert_mock CustomerFinancials::REDIS
183		assert_mock CreditCardSale::REDIS
184		assert_mock TrustLevelRepo::REDIS
185		assert_mock TrustLevelRepo::DB
186	end
187	em :test_sale_too_many_declines
188
189	def test_sale
190		req = stub_request(
191			:post,
192			"https://api.churnbuster.io/v1/successful_payments"
193		).with(
194			body: {
195				customer: {
196					source: "braintree",
197					source_id: "test",
198					email: "test@smtp.cheogram.com",
199					properties: {}
200				},
201				payment: {
202					source: "braintree",
203					source_id: "transaction",
204					amount_in_cents: 9900,
205					currency: "USD"
206				}
207			}.to_json
208		).to_return(status: 200, body: "", headers: {})
209
210		CreditCardSale::REDIS.expect(
211			:exists,
212			EMPromise.resolve(0),
213			["jmp_customer_credit_card_lock-test"]
214		)
215		TrustLevelRepo::REDIS.expect(
216			:get,
217			EMPromise.resolve("Customer"),
218			["jmp_customer_trust_level-test"]
219		)
220		TrustLevelRepo::DB.expect(
221			:query_one,
222			EMPromise.resolve({}),
223			[String, "test"], default: {}
224		)
225		CustomerFinancials::REDIS.expect(
226			:get,
227			EMPromise.resolve("1"),
228			["jmp_pay_decline-test"]
229		)
230		braintree_transaction = Minitest::Mock.new
231		CreditCardSale::BRAINTREE.expect(:transaction, braintree_transaction)
232		braintree_transaction.expect(
233			:sale,
234			EMPromise.resolve(
235				OpenStruct.new(
236					success?: true,
237					transaction: FAKE_BRAINTREE_TRANSACTION
238				)
239			),
240			amount: 99,
241			payment_method_token: "token",
242			merchant_account_id: "merchant_usd",
243			options: { submit_for_settlement: true }
244		)
245		CreditCardSale::REDIS.expect(
246			:setex,
247			EMPromise.resolve(1),
248			["jmp_customer_credit_card_lock-test", 86400, "1"]
249		)
250		result = CreditCardSale.new(
251			customer(plan_name: "test_usd"),
252			amount: 99,
253			payment_method: OpenStruct.new(token: "token")
254		).sale.sync
255		assert_equal FAKE_BRAINTREE_TRANSACTION, result
256		assert_mock CustomerFinancials::REDIS
257		assert_mock CreditCardSale::REDIS
258		assert_mock TrustLevelRepo::REDIS
259		assert_mock TrustLevelRepo::DB
260		assert_requested req
261	end
262	em :test_sale
263
264	def test_builder
265		expected = Transaction.new(
266			customer_id: "customer",
267			transaction_id: "transaction",
268			created_at: Time.at(0),
269			settled_after: Time.at(7776000),
270			amount: 12,
271			note: "Credit card payment"
272		)
273
274		assert_equal(
275			expected,
276			CreditCardSale::BraintreeTransaction.build(FAKE_BRAINTREE_TRANSACTION)
277		)
278	end
279
280	def test_create
281		req = stub_request(
282			:post,
283			"https://api.churnbuster.io/v1/successful_payments"
284		).with(
285			body: {
286				customer: {
287					source: "braintree",
288					source_id: "test",
289					email: "test@smtp.cheogram.com",
290					properties: {}
291				},
292				payment: {
293					source: "braintree",
294					source_id: "transaction",
295					amount_in_cents: 9900,
296					currency: "USD"
297				}
298			}.to_json
299		).to_return(status: 200, body: "", headers: {})
300
301		CreditCardSale::REDIS.expect(
302			:exists,
303			EMPromise.resolve(0),
304			["jmp_customer_credit_card_lock-test"]
305		)
306		TrustLevelRepo::REDIS.expect(
307			:get,
308			EMPromise.resolve("Customer"),
309			["jmp_customer_trust_level-test"]
310		)
311		TrustLevelRepo::DB.expect(
312			:query_one,
313			EMPromise.resolve({}),
314			[String, "test"], default: {}
315		)
316		CustomerFinancials::REDIS.expect(
317			:get,
318			EMPromise.resolve("1"),
319			["jmp_pay_decline-test"]
320		)
321		braintree_transaction = Minitest::Mock.new
322		CreditCardSale::BRAINTREE.expect(:transaction, braintree_transaction)
323		response = EMPromise.resolve(
324			OpenStruct.new(
325				success?: true,
326				transaction: FAKE_BRAINTREE_TRANSACTION
327			)
328		)
329		braintree_transaction.expect(
330			:sale,
331			response,
332			amount: 99,
333			payment_method_token: "token",
334			merchant_account_id: "merchant_usd",
335			options: { submit_for_settlement: true }
336		)
337		CreditCardSale::REDIS.expect(
338			:setex,
339			EMPromise.resolve(1),
340			["jmp_customer_credit_card_lock-test", 86400, "1"]
341		)
342
343		transaction = PromiseMock.new
344		transaction.expect(:insert, EMPromise.resolve(nil))
345
346		transaction_class = Minitest::Mock.new
347		transaction_class.expect(
348			:new,
349			transaction,
350			customer_id: "customer",
351			transaction_id: "transaction",
352			created_at: Time.at(0),
353			settled_after: Time.at(7776000),
354			amount: 12,
355			note: "Credit card payment"
356		)
357
358		result = CreditCardSale.create(
359			customer(plan_name: "test_usd"),
360			amount: 99,
361			payment_method: OpenStruct.new(token: "token"),
362			transaction_class: transaction_class
363		).sync
364
365		assert_equal transaction.object_id, result.object_id
366		assert_mock transaction_class
367		assert_mock transaction
368		assert_mock CustomerFinancials::REDIS
369		assert_mock CreditCardSale::REDIS
370		assert_mock TrustLevelRepo::REDIS
371		assert_mock TrustLevelRepo::DB
372		assert_requested req
373	end
374	em :test_create
375end