Files
lislgosms/api/src/send-chain/gateway-events.controller.spec.ts
T

188 lines
5.7 KiB
TypeScript

import { BadRequestException } from '@nestjs/common';
import { GatewayEventsController } from './gateway-events.controller';
describe('GatewayEventsController protocol logging', () => {
const sendChain = {
handleSubmitResult: jest.fn(),
handleSubmitSegmentResult: jest.fn(),
handleReceipt: jest.fn(),
intakeReceipt: jest.fn(),
};
const protocolLogs = {
record: jest.fn(),
};
const controller = new GatewayEventsController(sendChain as never, {} as never, protocolLogs as never);
beforeEach(() => {
jest.clearAllMocks();
});
it('does not duplicate a supplier SubmitResp from the internal aggregate callback', async () => {
sendChain.handleSubmitResult.mockResolvedValue({ accepted: true });
const body = {
messageId: 'MSG-1',
channelId: 'channel-1',
gatewayMessageId: '123',
sequenceId: 7,
submitStatus: 'accepted' as const,
};
await controller.submitResult(body);
expect(protocolLogs.record).not.toHaveBeenCalled();
});
it('persists each supplier segment response without adding a duplicate protocol log', async () => {
sendChain.handleSubmitSegmentResult.mockResolvedValue({ accepted: true });
const body = {
messageId: 'MSG-LONG-1',
channelId: 'channel-1',
submitId: 'submit-1',
segmentIndex: 2,
segmentTotal: 3,
gatewayMessageId: '456',
sequenceId: 8,
submitStatus: 'accepted' as const,
};
await expect(controller.submitSegmentResult(body)).resolves.toEqual({ accepted: true });
expect(sendChain.handleSubmitSegmentResult).toHaveBeenCalledWith(body);
expect(protocolLogs.record).not.toHaveBeenCalled();
});
it('logs a supplier receipt only after it is durably accepted by the inbox', async () => {
sendChain.intakeReceipt.mockResolvedValue({ accepted: true, inboxId: 'inbox-1', status: 'pending' });
const body = {
messageId: 'receipt-456',
channelId: 'channel-1',
connectionId: 'channel-1:0',
gatewayMessageId: '456',
phoneNumber: '13127620092',
receiptStatus: 'undelivered' as const,
rawStatus: 'UNDELIV',
};
await expect(controller.receiptIntake(body)).resolves.toEqual({
accepted: true,
inboxId: 'inbox-1',
status: 'pending',
});
expect(protocolLogs.record).toHaveBeenCalledWith(expect.objectContaining({
direction: 'channel_to_platform',
eventType: 'deliver_receipt',
channelId: 'channel-1',
messageId: 'receipt-456',
gatewayMessageId: '456',
status: 'success',
}));
});
it('accepts only safe outbound Gateway packet events', () => {
expect(controller.protocolLog({
protocol: 'cmpp',
direction: 'platform_to_channel',
eventType: 'submit',
status: 'success',
messageId: 'MSG-1',
})).toEqual({ accepted: true });
expect(protocolLogs.record).toHaveBeenCalledTimes(1);
expect(() => controller.protocolLog({
protocol: 'cmpp',
direction: 'client_to_platform',
eventType: 'submit',
status: 'success',
})).toThrow(BadRequestException);
expect(controller.protocolLog({
protocol: 'cmpp',
direction: 'channel_to_platform',
eventType: 'submit_resp',
status: 'success',
messageId: 'MSG-1',
})).toEqual({ accepted: true });
expect(controller.protocolLog({
protocol: 'cmpp',
direction: 'platform_to_client',
eventType: 'submit_resp',
status: 'success',
messageId: 'MSG-1',
})).toEqual({ accepted: true });
expect(controller.protocolLog({
protocol: 'cmpp',
direction: 'platform_to_client',
eventType: 'deliver_receipt',
status: 'success',
messageId: 'MSG-1',
})).toEqual({ accepted: true });
expect(controller.protocolLog({
protocol: 'cmpp',
direction: 'platform_to_client',
eventType: 'deliver_uplink',
status: 'success',
messageId: 'MSG-1',
})).toEqual({ accepted: true });
expect(controller.protocolLog({
protocol: 'cmpp',
direction: 'client_to_platform',
eventType: 'deliver_resp',
status: 'success',
messageId: 'MSG-1',
})).toEqual({ accepted: true });
});
it('enriches an enterprise Submit packet with identifiers returned by the real service', async () => {
(sendChain as Record<string, jest.Mock>).submitInboundMessage = jest.fn().mockResolvedValue({
accepted: true,
tenantId: 'tenant-1',
applicationId: 'app-1',
messageId: 'MSG-1',
status: 'fragment_pending',
});
await controller.submitInbound({
account: '607532',
phoneNumber: '13127620092',
content: 'fragment',
sequenceId: 141,
});
expect(protocolLogs.record).toHaveBeenCalledWith(expect.objectContaining({
direction: 'client_to_platform',
eventType: 'submit',
tenantId: 'tenant-1',
applicationId: 'app-1',
messageId: 'MSG-1',
status: 'success',
}));
});
it('replaces a fallback receipt identifier with the resolved main message identifier', async () => {
sendChain.handleReceipt.mockResolvedValue({
tenantId: 'tenant-1',
applicationId: 'app-1',
messageId: 'MSG-LONG-1',
});
await controller.receipt({
messageId: 'receipt-736070230367350788',
channelId: 'channel-copy',
gatewayMessageId: '736070230367350788',
phoneNumber: '13127620092',
receiptStatus: 'delivered',
rawStatus: 'DELIVRD',
});
expect(protocolLogs.record).toHaveBeenCalledWith(expect.objectContaining({
direction: 'channel_to_platform',
eventType: 'deliver_receipt',
channelId: 'channel-copy',
messageId: 'MSG-LONG-1',
gatewayMessageId: '736070230367350788',
tenantId: 'tenant-1',
applicationId: 'app-1',
status: 'success',
}));
});
});