test_credit_card_sale.rb

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