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
JavaScript
"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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