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'); }); });