Files
dbis_core-lite/tests/unit/exports/identity-map.test.ts
2026-02-09 21:51:45 -08:00

222 lines
7.0 KiB
TypeScript

/**
* Unit tests for Payment Identity Map Service
*/
import { PaymentIdentityMapService } from '@/exports/identity-map';
import { TestHelpers } from '../../utils/test-helpers';
import { PaymentRepository } from '@/repositories/payment-repository';
import { MessageRepository } from '@/repositories/message-repository';
import { PaymentStatus } from '@/models/payment';
import { MessageType, MessageStatus } from '@/models/message';
import { v4 as uuidv4 } from 'uuid';
describe('PaymentIdentityMapService', () => {
let paymentRepository: PaymentRepository;
let messageRepository: MessageRepository;
beforeAll(async () => {
paymentRepository = new PaymentRepository();
messageRepository = new MessageRepository();
// Clean database before starting
await TestHelpers.cleanDatabase();
}, 10000); // Increase timeout for database setup
beforeEach(async () => {
await TestHelpers.cleanDatabase();
});
afterAll(async () => {
await TestHelpers.cleanDatabase();
// Close database connections
const pool = TestHelpers.getTestDb();
await pool.end();
}, 10000);
describe('buildForPayment', () => {
it('should build identity map for payment with all identifiers', async () => {
// Create test operator
const operator = await TestHelpers.createTestOperator('TEST_ID_MAP', 'MAKER' as any);
// Create payment
const paymentRequest = TestHelpers.createTestPaymentRequest();
const paymentId = await paymentRepository.create(
paymentRequest,
operator.id,
`TEST-PAY-${Date.now()}`
);
const uetr = uuidv4();
const internalTxnId = 'TXN-12345';
// Update payment with identifiers
await paymentRepository.update(paymentId, {
internalTransactionId: internalTxnId,
uetr,
status: PaymentStatus.LEDGER_POSTED,
});
// Create ledger posting
const { query } = require('@/database/connection');
await query(
`INSERT INTO ledger_postings (
internal_transaction_id, payment_id, account_number, transaction_type,
amount, currency, status, posting_timestamp, reference
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
[
internalTxnId,
paymentId,
paymentRequest.senderAccount,
'DEBIT',
paymentRequest.amount,
paymentRequest.currency,
'POSTED',
new Date(),
paymentId,
]
);
// Create ISO message
const messageId = uuidv4();
const msgId = 'MSG-12345';
const xmlContent = `<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10">
<FIToFICstmrCdtTrf>
<GrpHdr>
<MsgId>${msgId}</MsgId>
<CreDtTm>${new Date().toISOString()}</CreDtTm>
</GrpHdr>
<CdtTrfTxInf>
<PmtId>
<EndToEndId>E2E-123</EndToEndId>
<TxId>TX-123</TxId>
<UETR>${uetr}</UETR>
</PmtId>
</CdtTrfTxInf>
</FIToFICstmrCdtTrf>
</Document>`;
await messageRepository.create({
id: messageId,
messageId: messageId,
paymentId,
messageType: MessageType.PACS_008,
uetr,
msgId,
xmlContent,
xmlHash: 'test-hash',
status: MessageStatus.VALIDATED,
});
// Build identity map
const identityMap = await PaymentIdentityMapService.buildForPayment(paymentId);
expect(identityMap).toBeDefined();
expect(identityMap?.paymentId).toBe(paymentId);
expect(identityMap?.uetr).toBe(uetr);
expect(identityMap?.endToEndId).toBe('E2E-123');
expect(identityMap?.txId).toBe('TX-123');
expect(identityMap?.ledgerJournalIds.length).toBeGreaterThan(0);
expect(identityMap?.internalTransactionIds).toContain(internalTxnId);
});
it('should return null for non-existent payment', async () => {
const identityMap = await PaymentIdentityMapService.buildForPayment(uuidv4());
expect(identityMap).toBeNull();
});
});
describe('findByUETR', () => {
it('should find payment by UETR', async () => {
const operator = await TestHelpers.createTestOperator('TEST_UETR', 'MAKER' as any);
const paymentRequest = TestHelpers.createTestPaymentRequest();
const paymentId = await paymentRepository.create(
paymentRequest,
operator.id,
`TEST-UETR-${Date.now()}`
);
const uetr = uuidv4();
await paymentRepository.update(paymentId, {
uetr,
status: PaymentStatus.LEDGER_POSTED,
});
const identityMap = await PaymentIdentityMapService.findByUETR(uetr);
expect(identityMap).toBeDefined();
expect(identityMap?.paymentId).toBe(paymentId);
expect(identityMap?.uetr).toBe(uetr);
});
it('should return null for non-existent UETR', async () => {
const identityMap = await PaymentIdentityMapService.findByUETR(uuidv4());
expect(identityMap).toBeNull();
});
});
describe('buildForPayments', () => {
it('should build identity maps for multiple payments', async () => {
const operator = await TestHelpers.createTestOperator('TEST_MULTI', 'MAKER' as any);
const paymentIds: string[] = [];
// Create multiple payments
for (let i = 0; i < 3; i++) {
const paymentRequest = TestHelpers.createTestPaymentRequest();
const paymentId = await paymentRepository.create(
paymentRequest,
operator.id,
`TEST-MULTI-${Date.now()}-${i}`
);
paymentIds.push(paymentId);
}
const identityMaps = await PaymentIdentityMapService.buildForPayments(paymentIds);
expect(identityMaps.size).toBe(3);
paymentIds.forEach((id) => {
expect(identityMaps.has(id)).toBe(true);
});
});
});
describe('verifyUETRPassThrough', () => {
it('should verify valid UETR format', async () => {
const operator = await TestHelpers.createTestOperator('TEST_VERIFY', 'MAKER' as any);
const paymentRequest = TestHelpers.createTestPaymentRequest();
const paymentId = await paymentRepository.create(
paymentRequest,
operator.id,
`TEST-VERIFY-${Date.now()}`
);
const uetr = uuidv4();
await paymentRepository.update(paymentId, {
uetr,
status: PaymentStatus.LEDGER_POSTED,
});
const isValid = await PaymentIdentityMapService.verifyUETRPassThrough(paymentId);
expect(isValid).toBe(true);
});
it('should return false for invalid UETR', async () => {
const operator = await TestHelpers.createTestOperator('TEST_INVALID', 'MAKER' as any);
const paymentRequest = TestHelpers.createTestPaymentRequest();
const paymentId = await paymentRepository.create(
paymentRequest,
operator.id,
`TEST-INVALID-${Date.now()}`
);
await paymentRepository.update(paymentId, {
uetr: 'invalid-uetr',
status: PaymentStatus.LEDGER_POSTED,
});
const isValid = await PaymentIdentityMapService.verifyUETRPassThrough(paymentId);
expect(isValid).toBe(false);
});
});
});