UNPKG

medusa-payment-ipay

Version:

iPay Africa payment provider for Medusa v2 - Supports M-Pesa, Airtel Money, Credit Cards, and PesaLink

322 lines 24.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const service_1 = __importDefault(require("../service")); describe("IPayProviderService", () => { let service; let mockOptions; let mockContainer; beforeEach(() => { mockOptions = { vid: 'test_vid', hashKey: 'test_hash_key', live: false, enabledChannels: { mpesa: true, airtel: true, creditcard: true, pesalink: true, }, }; mockContainer = {}; service = new service_1.default(mockContainer, mockOptions); }); describe("Static properties", () => { it("should have correct identifier", () => { expect(service_1.default.identifier).toBe("ipay"); }); }); describe("Constructor", () => { it("should initialize with correct options", () => { expect(service["options_"]).toEqual(mockOptions); }); }); describe("validateOptions", () => { it("should validate required options successfully", () => { expect(() => { service_1.default.validateOptions(mockOptions); }).not.toThrow(); }); it("should throw error if vid is missing", () => { expect(() => { service_1.default.validateOptions({ hashKey: 'test' }); }).toThrow("iPay VID is required"); }); it("should throw error if hashKey is missing", () => { expect(() => { service_1.default.validateOptions({ vid: 'test' }); }).toThrow("iPay hash key is required"); }); }); describe("initiatePayment", () => { const mockInput = { amount: 10000, // 100.00 in cents currency_code: 'KES', context: { customer: { email: 'test@example.com', phone: '+254700000000', }, order: { id: 'order_test_123', }, }, }; it("should initiate payment successfully", async () => { const result = await service.initiatePayment(mockInput); expect(result).toEqual({ data: expect.objectContaining({ id: expect.stringContaining('order_'), paymentData: expect.objectContaining({ vid: mockOptions.vid, ttl: '100', eml: mockInput.context.customer.email, tel: mockInput.context.customer.phone, curr: 'KES', live: '0', }), gatewayUrl: 'https://www.ipayafrica.com/ipn/', status: 'pending', amount: 10000, currency_code: 'KES', }), }); }); it("should handle live mode correctly", async () => { service = new service_1.default(mockContainer, { ...mockOptions, live: true }); const result = await service.initiatePayment(mockInput); expect(result.data.paymentData.live).toBe('1'); expect(result.data.paymentData.cst).toBe('1'); }); it("should handle test mode correctly", async () => { const result = await service.initiatePayment(mockInput); expect(result.data.paymentData.live).toBe('0'); expect(result.data.paymentData.cst).toBe('0'); }); it("should include hash in payment data", async () => { const result = await service.initiatePayment(mockInput); expect(result.data.paymentData.hsh).toBeDefined(); expect(typeof result.data.paymentData.hsh).toBe('string'); }); }); describe("authorizePayment", () => { it("should authorize payment successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'pending', amount: 10000, }, }; const result = await service.authorizePayment(mockInput); expect(result).toEqual({ status: 'authorized', data: expect.objectContaining({ id: 'order_test_123', status: 'authorized', authorized_at: expect.any(String), }), }); }); }); describe("capturePayment", () => { it("should capture payment successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'authorized', amount: 10000, }, }; const result = await service.capturePayment(mockInput); expect(result).toEqual({ data: expect.objectContaining({ id: 'order_test_123', status: 'captured', captured_at: expect.any(String), }), }); }); }); describe("cancelPayment", () => { it("should cancel payment successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'pending', }, }; const result = await service.cancelPayment(mockInput); expect(result).toEqual({ data: expect.objectContaining({ id: 'order_test_123', status: 'cancelled', cancelled_at: expect.any(String), }), }); }); }); describe("refundPayment", () => { it("should process refund successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'captured', amount: 10000, }, amount: 5000, }; const result = await service.refundPayment(mockInput); expect(result).toEqual({ data: expect.objectContaining({ id: 'order_test_123', refund_requested: true, refund_amount: 5000, refund_requested_at: expect.any(String), }), }); }); }); describe("retrievePayment", () => { it("should retrieve payment data successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'captured', amount: 10000, }, }; const result = await service.retrievePayment(mockInput); expect(result).toEqual(mockInput.data); }); it("should handle empty input", async () => { const result = await service.retrievePayment({}); expect(result).toEqual({}); }); }); describe("updatePayment", () => { it("should update payment successfully", async () => { const mockInput = { amount: 15000, currency_code: 'KES', data: { id: 'order_test_123', amount: 10000, currency_code: 'KES', }, }; const result = await service.updatePayment(mockInput); expect(result).toEqual(expect.objectContaining({ id: 'order_test_123', amount: 15000, currency_code: 'KES', updated_at: expect.any(String), })); }); }); describe("deletePayment", () => { it("should delete payment successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'pending', }, }; const result = await service.deletePayment(mockInput); expect(result).toEqual({ data: mockInput.data, }); }); }); describe("getPaymentStatus", () => { it("should get payment status successfully", async () => { const mockInput = { data: { id: 'order_test_123', status: 'captured', }, }; const result = await service.getPaymentStatus(mockInput); expect(result).toEqual({ status: 'captured', }); }); it("should default to pending status", async () => { const mockInput = { data: { id: 'order_test_123', }, }; const result = await service.getPaymentStatus(mockInput); expect(result).toEqual({ status: 'pending', }); }); }); describe("getWebhookActionAndData", () => { it("should handle successful payment webhook", async () => { const mockPayload = { data: { status: 'aei7p7yrx4ae34', p1: 'order_test_123', ttl: '100', }, }; const result = await service.getWebhookActionAndData(mockPayload); expect(result).toEqual({ action: 'authorized', data: { session_id: 'order_test_123', amount: 10000, }, }); }); it("should handle pending payment webhook", async () => { const mockPayload = { data: { status: 'bdi6p2yy76etrs', p1: 'order_test_123', mc: '100', }, }; const result = await service.getWebhookActionAndData(mockPayload); expect(result).toEqual({ action: 'not_supported', data: { session_id: 'order_test_123', amount: 10000, }, }); }); }); describe("generateHash (private method)", () => { it("should generate correct hash", () => { const testData = { vid: 'test_vid', ttl: '100', oid: 'order_123', eml: 'test@example.com', }; // Access private method for testing const hash = service.generateHash(testData); expect(hash).toBeDefined(); expect(typeof hash).toBe('string'); expect(hash.length).toBeGreaterThan(0); }); }); describe("Error handling", () => { it("should handle missing context gracefully", async () => { const mockInput = { amount: 10000, currency_code: 'KES', context: {}, }; const result = await service.initiatePayment(mockInput); expect(result.data.paymentData.eml).toBe(''); expect(result.data.paymentData.tel).toBe(''); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS51bml0LnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2lwYXkvX190ZXN0c19fL3NlcnZpY2UudW5pdC5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBRUEseURBQTZDO0FBRTdDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDbkMsSUFBSSxPQUE0QixDQUFDO0lBQ2pDLElBQUksV0FBZ0IsQ0FBQztJQUNyQixJQUFJLGFBQThCLENBQUM7SUFFbkMsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUVkLFdBQVcsR0FBRztZQUNaLEdBQUcsRUFBRSxVQUFVO1lBQ2YsT0FBTyxFQUFFLGVBQWU7WUFDeEIsSUFBSSxFQUFFLEtBQUs7WUFDWCxlQUFlLEVBQUU7Z0JBQ2YsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsTUFBTSxFQUFFLElBQUk7Z0JBQ1osVUFBVSxFQUFFLElBQUk7Z0JBQ2hCLFFBQVEsRUFBRSxJQUFJO2FBQ2Y7U0FDRixDQUFDO1FBRUYsYUFBYSxHQUFHLEVBQXFCLENBQUM7UUFFdEMsT0FBTyxHQUFHLElBQUksaUJBQW1CLENBQUMsYUFBYSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ2hFLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRTtRQUNqQyxFQUFFLENBQUMsZ0NBQWdDLEVBQUUsR0FBRyxFQUFFO1lBQ3hDLE1BQU0sQ0FBQyxpQkFBbUIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxhQUFhLEVBQUUsR0FBRyxFQUFFO1FBQzNCLEVBQUUsQ0FBQyx3Q0FBd0MsRUFBRSxHQUFHLEVBQUU7WUFDaEQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMs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