first commit
This commit is contained in:
56
tests/unit/bank-transfer.service.test.js
Normal file
56
tests/unit/bank-transfer.service.test.js
Normal file
@@ -0,0 +1,56 @@
|
||||
const mockCharge = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn().mockReturnValue({
|
||||
charge: mockCharge,
|
||||
transaction: { status: jest.fn(), refund: jest.fn(), cancel: jest.fn() }
|
||||
}),
|
||||
getSnap: jest.fn().mockReturnValue({ createTransaction: jest.fn() })
|
||||
}));
|
||||
|
||||
const mockOrderFindByPk = jest.fn();
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: mockOrderFindByPk, findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const bankTransferService = require('../../app/modules/bank-transfer/services/bank-transfer.service');
|
||||
const db = require('../../models/migration');
|
||||
|
||||
describe('BankTransferService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
process.env.MIDTRANS_EXPIRY_DURATION = '1';
|
||||
process.env.MIDTRANS_EXPIRY_UNIT = 'hour';
|
||||
});
|
||||
|
||||
it('should create a bank transfer transaction (BCA) successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-001', amount: 10000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
const result = await bankTransferService.createTransaction(payload, 'bca');
|
||||
expect(mockCharge).toHaveBeenCalledWith(expect.objectContaining({ payment_type: 'bank_transfer' }));
|
||||
expect(result.status_code).toBe('201');
|
||||
});
|
||||
|
||||
it('should create a mandiri transaction (echannel) successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-001', amount: 10000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
await bankTransferService.createTransaction(payload, 'mandiri');
|
||||
expect(mockCharge).toHaveBeenCalledWith(expect.objectContaining({ payment_type: 'echannel' }));
|
||||
});
|
||||
|
||||
it('should fallback to order total', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-001' };
|
||||
mockOrderFindByPk.mockResolvedValue({ total: 50000 });
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
await bankTransferService.createTransaction(payload, 'bca');
|
||||
expect(mockCharge).toHaveBeenCalledWith(expect.objectContaining({
|
||||
transaction_details: expect.objectContaining({ gross_amount: 50000 })
|
||||
}));
|
||||
});
|
||||
|
||||
it('should throw error if order not found and amount missing', async () => {
|
||||
mockOrderFindByPk.mockResolvedValue(null);
|
||||
await expect(bankTransferService.createTransaction({ order_id: 'wrong' }, 'bca'))
|
||||
.rejects.toThrow('Amount wajib diisi');
|
||||
});
|
||||
});
|
||||
45
tests/unit/credit-card.service.test.js
Normal file
45
tests/unit/credit-card.service.test.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const mockCharge = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn().mockReturnValue({
|
||||
charge: mockCharge,
|
||||
transaction: { status: jest.fn(), refund: jest.fn(), cancel: jest.fn() }
|
||||
}),
|
||||
getSnap: jest.fn().mockReturnValue({ createTransaction: jest.fn() })
|
||||
}));
|
||||
|
||||
const mockOrderFindByPk = jest.fn();
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: mockOrderFindByPk, findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const creditCardService = require('../../app/modules/credit-card/services/credit-card.service');
|
||||
|
||||
describe('CreditCardService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create a credit card transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-cc', external_id: 'INV-CC-001', amount: 500000, credit_card_token: 't-123' };
|
||||
mockCharge.mockResolvedValue({ status_code: '201', transaction_status: 'capture' });
|
||||
const result = await creditCardService.createTransaction(payload);
|
||||
expect(mockCharge).toHaveBeenCalled();
|
||||
expect(result.status_code).toBe('201');
|
||||
});
|
||||
|
||||
it('should fallback to order total if amount is missing', async () => {
|
||||
const payload = { order_id: 'u-cc', external_id: 'INV-CC-001', credit_card_token: 't-123' };
|
||||
mockOrderFindByPk.mockResolvedValue({ total: 500000 });
|
||||
mockCharge.mockResolvedValue({ status_code: '201', transaction_status: 'capture' });
|
||||
|
||||
await creditCardService.createTransaction(payload);
|
||||
|
||||
expect(mockOrderFindByPk).toHaveBeenCalledWith('u-cc');
|
||||
expect(mockCharge).toHaveBeenCalledWith(expect.objectContaining({
|
||||
transaction_details: expect.objectContaining({
|
||||
gross_amount: 500000
|
||||
})
|
||||
}));
|
||||
});
|
||||
});
|
||||
35
tests/unit/cstore.service.test.js
Normal file
35
tests/unit/cstore.service.test.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const mockCharge = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn().mockReturnValue({
|
||||
charge: mockCharge,
|
||||
transaction: { status: jest.fn(), refund: jest.fn(), cancel: jest.fn() }
|
||||
}),
|
||||
getSnap: jest.fn().mockReturnValue({ createTransaction: jest.fn() })
|
||||
}));
|
||||
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: jest.fn(), findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const cstoreService = require('../../app/modules/cstore/services/cstore.service');
|
||||
|
||||
describe('CStoreService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create an indomaret transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-I-001', amount: 50000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
const result = await cstoreService.createTransaction(payload, 'indomaret');
|
||||
expect(mockCharge).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should create an alfamart transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-A-001', amount: 30000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
const result = await cstoreService.createTransaction(payload, 'alfamart');
|
||||
expect(mockCharge).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
36
tests/unit/e-wallet.service.test.js
Normal file
36
tests/unit/e-wallet.service.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const mockCharge = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn().mockReturnValue({
|
||||
charge: mockCharge,
|
||||
transaction: { status: jest.fn(), refund: jest.fn(), cancel: jest.fn() }
|
||||
}),
|
||||
getSnap: jest.fn().mockReturnValue({ createTransaction: jest.fn() })
|
||||
}));
|
||||
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: jest.fn(), findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const eWalletService = require('../../app/modules/e-wallet/services/e-wallet.service');
|
||||
|
||||
describe('EWalletService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create a gopay transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-G-001', amount: 25000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
const result = await eWalletService.createTransaction(payload, 'gopay');
|
||||
expect(mockCharge).toHaveBeenCalled();
|
||||
expect(result.status_code).toBe('201');
|
||||
});
|
||||
|
||||
it('should create a shopeepay transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-S-001', amount: 15000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
const result = await eWalletService.createTransaction(payload, 'shopeepay');
|
||||
expect(mockCharge).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
53
tests/unit/notification.controller.test.js
Normal file
53
tests/unit/notification.controller.test.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const notificationService = require('../../app/modules/notification/services/notification.service');
|
||||
const responseHelper = require('../../app/helpers/response.helper');
|
||||
|
||||
jest.mock('../../app/modules/notification/services/notification.service');
|
||||
jest.mock('../../app/helpers/response.helper');
|
||||
|
||||
const NotificationController = require('../../app/modules/notification/controllers/notification.controller');
|
||||
|
||||
describe('NotificationController', () => {
|
||||
let mockReq, mockRes;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockRes = {
|
||||
status: jest.fn().mockReturnThis(),
|
||||
json: jest.fn().mockReturnThis()
|
||||
};
|
||||
});
|
||||
|
||||
it('should handle notification successfully', async () => {
|
||||
mockReq = {
|
||||
body: { order_id: 'I-123', transaction_status: 'settlement' }
|
||||
};
|
||||
|
||||
notificationService.verifySignature.mockReturnValue(true);
|
||||
notificationService.processNotification.mockResolvedValue();
|
||||
|
||||
await NotificationController.handle(mockReq, mockRes);
|
||||
|
||||
expect(notificationService.verifySignature).toHaveBeenCalledWith(mockReq.body);
|
||||
expect(notificationService.processNotification).toHaveBeenCalledWith(mockReq.body);
|
||||
expect(responseHelper.success).toHaveBeenCalledWith(mockRes, expect.stringContaining('Handled'));
|
||||
});
|
||||
|
||||
it('should return 403 if signature invalid', async () => {
|
||||
mockReq = { body: { signature_key: 'invalid' } };
|
||||
notificationService.verifySignature.mockReturnValue(false);
|
||||
|
||||
await NotificationController.handle(mockReq, mockRes);
|
||||
|
||||
expect(responseHelper.error).toHaveBeenCalledWith(mockRes, expect.stringContaining('Invalid Signature'), 403);
|
||||
});
|
||||
|
||||
it('should return error on service error', async () => {
|
||||
mockReq = { body: { order_id: 'I-123' } };
|
||||
notificationService.verifySignature.mockReturnValue(true);
|
||||
notificationService.processNotification.mockRejectedValue(new Error('DB Error'));
|
||||
|
||||
await NotificationController.handle(mockReq, mockRes);
|
||||
|
||||
expect(responseHelper.error).toHaveBeenCalledWith(mockRes, expect.stringContaining('DB Error'));
|
||||
});
|
||||
});
|
||||
93
tests/unit/notification.service.test.js
Normal file
93
tests/unit/notification.service.test.js
Normal file
@@ -0,0 +1,93 @@
|
||||
const mockPaymentFindOne = jest.fn();
|
||||
const mockOrderFindByPk = jest.fn();
|
||||
const mockOrderFindOne = jest.fn();
|
||||
|
||||
jest.mock('../../../../models/migration', () => ({
|
||||
Payment: { findOne: mockPaymentFindOne, update: jest.fn() },
|
||||
Order: { findByPk: mockOrderFindByPk, findOne: mockOrderFindOne, update: jest.fn() }
|
||||
}));
|
||||
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Payment: { findOne: mockPaymentFindOne, update: jest.fn() },
|
||||
Order: { findByPk: mockOrderFindByPk, findOne: mockOrderFindOne, update: jest.fn() }
|
||||
}));
|
||||
|
||||
const notificationService = require('../../app/modules/notification/services/notification.service');
|
||||
const crypto = require('crypto');
|
||||
|
||||
describe('NotificationService', () => {
|
||||
const serverKey = 'SB-Mid-server-test';
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
process.env.MIDTRANS_SERVER_KEY = serverKey;
|
||||
});
|
||||
|
||||
describe('verifySignature', () => {
|
||||
it('should return true for a valid signature', () => {
|
||||
const payload = { order_id: 'I-123', status_code: '200', gross_amount: '10.00', signature_key: '' };
|
||||
const data = payload.order_id + payload.status_code + payload.gross_amount + serverKey;
|
||||
payload.signature_key = crypto.createHash('sha512').update(data).digest('hex');
|
||||
expect(notificationService.verifySignature(payload)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for invalid signature', () => {
|
||||
const payload = { order_id: 'I-123', status_code: '200', gross_amount: '10.00', signature_key: 'wrong' };
|
||||
expect(notificationService.verifySignature(payload)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('processNotification', () => {
|
||||
it('should update order to COMPLETED on settlement', async () => {
|
||||
const payload = { order_id: 'I-123', transaction_status: 'settlement', fraud_status: 'accept' };
|
||||
const mockUpdateOrder = jest.fn();
|
||||
const mockUpdatePayment = jest.fn();
|
||||
const mockPayment = { order_id: 'u-123', update: mockUpdatePayment };
|
||||
const mockOrder = { id: 'u-123', status: 'PENDING', payment_status: 'PENDING', update: mockUpdateOrder };
|
||||
|
||||
mockPaymentFindOne.mockResolvedValue(mockPayment);
|
||||
mockOrderFindByPk.mockResolvedValue(mockOrder);
|
||||
|
||||
await notificationService.processNotification(payload);
|
||||
expect(mockUpdateOrder).toHaveBeenCalledWith(expect.objectContaining({ status: 'COMPLETED', payment_status: 'PAID' }));
|
||||
expect(mockUpdatePayment).toHaveBeenCalledWith(expect.objectContaining({ status: 'SUCCESS' }));
|
||||
});
|
||||
|
||||
it('should update order to FAILED on deny/cancel/expire', async () => {
|
||||
const payload = { order_id: 'I-123', transaction_status: 'expire' };
|
||||
const mockUpdate = jest.fn();
|
||||
const mockOrder = { id: 'u-123', status: 'PENDING', update: mockUpdate };
|
||||
|
||||
mockPaymentFindOne.mockResolvedValue(null);
|
||||
mockOrderFindOne.mockResolvedValue(mockOrder);
|
||||
|
||||
await notificationService.processNotification(payload);
|
||||
expect(mockUpdate).toHaveBeenCalledWith(expect.objectContaining({ status: 'FAILED', payment_status: 'REJECT' }));
|
||||
});
|
||||
|
||||
it('should update to PENDING on pending status', async () => {
|
||||
const payload = { order_id: 'I-123', transaction_status: 'pending' };
|
||||
const mockUpdate = jest.fn();
|
||||
const mockOrder = { id: 'u-123', status: 'PENDING', payment_status: 'PENDING', update: mockUpdate };
|
||||
|
||||
mockPaymentFindOne.mockResolvedValue(null);
|
||||
mockOrderFindOne.mockResolvedValue(mockOrder);
|
||||
|
||||
await notificationService.processNotification(payload);
|
||||
// If already pending, it should skip update
|
||||
expect(mockUpdate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should warn if order not found', async () => {
|
||||
const payload = { order_id: 'unknown' };
|
||||
mockPaymentFindOne.mockResolvedValue(null);
|
||||
mockOrderFindOne.mockResolvedValue(null);
|
||||
mockOrderFindByPk.mockResolvedValue(null);
|
||||
|
||||
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
|
||||
await notificationService.processNotification(payload);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('tidak ditemukan'));
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
});
|
||||
46
tests/unit/paylater.service.test.js
Normal file
46
tests/unit/paylater.service.test.js
Normal file
@@ -0,0 +1,46 @@
|
||||
const mockCharge = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn().mockReturnValue({
|
||||
charge: mockCharge,
|
||||
transaction: { status: jest.fn(), refund: jest.fn(), cancel: jest.fn() }
|
||||
}),
|
||||
getSnap: jest.fn().mockReturnValue({ createTransaction: jest.fn() })
|
||||
}));
|
||||
|
||||
const mockOrderFindByPk = jest.fn();
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: mockOrderFindByPk, findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const paylaterService = require('../../app/modules/paylater/services/paylater.service');
|
||||
|
||||
describe('PayLaterService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create an akulaku transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-AK-001', amount: 1000000 };
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
await paylaterService.createTransaction(payload, 'akulaku');
|
||||
expect(mockCharge).toHaveBeenCalledWith(expect.objectContaining({
|
||||
payment_type: 'akulaku'
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fallback to order total if amount is missing', async () => {
|
||||
const payload = { order_id: 'u-123', external_id: 'INV-AK-001' };
|
||||
mockOrderFindByPk.mockResolvedValue({ total: 1000000 });
|
||||
mockCharge.mockResolvedValue({ status_code: '201' });
|
||||
|
||||
await paylaterService.createTransaction(payload, 'kredivo');
|
||||
|
||||
expect(mockOrderFindByPk).toHaveBeenCalledWith('u-123');
|
||||
expect(mockCharge).toHaveBeenCalledWith(expect.objectContaining({
|
||||
transaction_details: expect.objectContaining({
|
||||
gross_amount: 1000000
|
||||
})
|
||||
}));
|
||||
});
|
||||
});
|
||||
63
tests/unit/payment_logger.helper.test.js
Normal file
63
tests/unit/payment_logger.helper.test.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const mockOrderFindByPk = jest.fn();
|
||||
const mockOrderFindOne = jest.fn();
|
||||
const mockPaymentCreate = jest.fn();
|
||||
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: mockOrderFindByPk, findOne: mockOrderFindOne },
|
||||
Payment: { create: mockPaymentCreate }
|
||||
}));
|
||||
|
||||
const paymentLogger = require('../../app/helpers/payment_logger.helper');
|
||||
|
||||
describe('PaymentLoggerHelper', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should log a payment successfully', async () => {
|
||||
const midtransResponse = {
|
||||
order_id: 'INV-EXT-001',
|
||||
gross_amount: '10000.00',
|
||||
transaction_status: 'settlement',
|
||||
payment_type: 'credit_card',
|
||||
status_message: 'Success'
|
||||
};
|
||||
const requestPayload = { order_id: 'u-123' };
|
||||
|
||||
mockOrderFindByPk.mockResolvedValue({ id: 'u-123', total: 10000, user_id: 1 });
|
||||
mockPaymentCreate.mockResolvedValue({ id: 'p-123' });
|
||||
|
||||
const result = await paymentLogger.log(midtransResponse, requestPayload);
|
||||
|
||||
expect(mockOrderFindByPk).toHaveBeenCalledWith('u-123');
|
||||
expect(mockPaymentCreate).toHaveBeenCalledWith(expect.objectContaining({
|
||||
status: 'SUCCESS',
|
||||
channel_code: 'credit_card',
|
||||
channel_type: 'CREDIT_CARD'
|
||||
}));
|
||||
expect(result.id).toBe('p-123');
|
||||
});
|
||||
|
||||
it('should map bank transfer types correctly', async () => {
|
||||
const midtransResponse = { order_id: 'INV-EXT', payment_type: 'bank_transfer', transaction_status: 'pending' };
|
||||
mockOrderFindOne.mockResolvedValue({ id: 'u-123', total: 10000 });
|
||||
|
||||
await paymentLogger.log(midtransResponse);
|
||||
|
||||
expect(mockPaymentCreate).toHaveBeenCalledWith(expect.objectContaining({
|
||||
channel_type: 'BANK'
|
||||
}));
|
||||
});
|
||||
|
||||
it('should return null if order not found', async () => {
|
||||
mockOrderFindByPk.mockResolvedValue(null);
|
||||
mockOrderFindOne.mockResolvedValue(null);
|
||||
|
||||
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
|
||||
const result = await paymentLogger.log({ order_id: 'none' });
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
32
tests/unit/response.helper.test.js
Normal file
32
tests/unit/response.helper.test.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const ResponseHelper = require('../../app/helpers/response.helper');
|
||||
|
||||
describe('ResponseHelper', () => {
|
||||
let mockRes;
|
||||
|
||||
beforeEach(() => {
|
||||
mockRes = {
|
||||
status: jest.fn().mockReturnThis(),
|
||||
json: jest.fn().mockReturnThis()
|
||||
};
|
||||
});
|
||||
|
||||
it('should send success response', () => {
|
||||
ResponseHelper.success(mockRes, 'Success test', { id: 1 });
|
||||
expect(mockRes.status).toHaveBeenCalledWith(200);
|
||||
expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
|
||||
success: true,
|
||||
message: 'Success test',
|
||||
data: { id: 1 }
|
||||
}));
|
||||
});
|
||||
|
||||
it('should send error response', () => {
|
||||
ResponseHelper.error(mockRes, 'Error test', 400, { field: 'required' });
|
||||
expect(mockRes.status).toHaveBeenCalledWith(400);
|
||||
expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
|
||||
success: false,
|
||||
message: 'Error test',
|
||||
errors: { field: 'required' }
|
||||
}));
|
||||
});
|
||||
});
|
||||
28
tests/unit/snap.service.test.js
Normal file
28
tests/unit/snap.service.test.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const mockCreateTransaction = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn(),
|
||||
getSnap: jest.fn().mockReturnValue({
|
||||
createTransaction: mockCreateTransaction
|
||||
})
|
||||
}));
|
||||
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: jest.fn(), findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const snapService = require('../../app/modules/snap/services/snap.service');
|
||||
|
||||
describe('SnapService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create a snap transaction successfully', async () => {
|
||||
const payload = { order_id: 'u-snap', external_id: 'INV-S-001', amount: 100000 };
|
||||
mockCreateTransaction.mockResolvedValue({ token: 't-123', redirect_url: 'http://m.com' });
|
||||
const result = await snapService.createTransaction(payload);
|
||||
expect(mockCreateTransaction).toHaveBeenCalled();
|
||||
expect(result.token).toBe('t-123');
|
||||
});
|
||||
});
|
||||
34
tests/unit/transaction.service.test.js
Normal file
34
tests/unit/transaction.service.test.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const mockStatus = jest.fn();
|
||||
const mockRefund = jest.fn();
|
||||
jest.mock('../../app/core/midtrans.service', () => ({
|
||||
getCoreApi: jest.fn().mockReturnValue({
|
||||
transaction: { status: mockStatus, refund: mockRefund, cancel: jest.fn() }
|
||||
}),
|
||||
getSnap: jest.fn()
|
||||
}));
|
||||
|
||||
jest.mock('../../models/migration', () => ({
|
||||
Order: { findByPk: jest.fn(), findOne: jest.fn(), update: jest.fn() },
|
||||
Payment: { findOne: jest.fn(), create: jest.fn(), update: jest.fn() }
|
||||
}));
|
||||
|
||||
const transactionService = require('../../app/modules/transaction/services/transaction.service');
|
||||
|
||||
describe('TransactionService', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should get transaction status successfully', async () => {
|
||||
mockStatus.mockResolvedValue({ transaction_status: 'settlement' });
|
||||
const result = await transactionService.getStatus('INV-123');
|
||||
expect(mockStatus).toHaveBeenCalledWith('INV-123');
|
||||
expect(result.transaction_status).toBe('settlement');
|
||||
});
|
||||
|
||||
it('should process refund successfully', async () => {
|
||||
mockRefund.mockResolvedValue({ status_code: '200' });
|
||||
const result = await transactionService.refund({ order_id: 'INV-123', external_id: 'INV-123', amount: 5000 });
|
||||
expect(mockRefund).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user