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