Files
lislgosms/api/src/send-chain/night-sending-gate.spec.ts
T
2026-09-07 22:55:29 +08:00

61 lines
2.4 KiB
TypeScript

import { SendGatewaySubmitService } from './send-gateway-submit.service';
describe('shared dispatch night gate', () => {
function setup() {
const message = {
id: 'm1',
status: 'queued',
tenantId: 't1',
applicationId: 'a1',
batchTaskId: 'b1',
content: '任意内容',
};
const prisma = {
smsMessageRecord: {
findUnique: jest.fn().mockResolvedValue(message),
findMany: jest.fn().mockResolvedValue([message, { ...message, id: 'm2' }]),
update: jest.fn(),
},
};
const risk = { guardNightSending: jest.fn().mockResolvedValue(new Set(['m1'])) };
const facade = {
refreshTaskProgress: jest.fn(),
selectChannelForMessage: jest.fn(),
submitMessageToGateway: jest.fn(),
};
const sut = new SendGatewaySubmitService(
prisma as never,
{} as never,
risk as never,
{} as never,
{} as never,
facade as never,
{} as never,
);
return { sut, prisma, risk, facade };
}
it('holds single-message jobs before any channel or Submit operation', async () => {
const { sut, facade } = setup();
expect(await sut.processSendJob({ messageRecordId: 'm1' })).toMatchObject({
status: 'pending_review',
submitted: false,
});
expect(facade.selectChannelForMessage).not.toHaveBeenCalled();
expect(facade.submitMessageToGateway).not.toHaveBeenCalled();
});
it('partitions the fast worker batch by persistent gate decisions', async () => {
const { sut } = setup();
const route = jest.spyOn(sut as never, 'planRoutesBatch').mockResolvedValue({ planned: [], failed: [] } as never);
const result = await sut['processSendJobBatch']([{ messageRecordId: 'm1' }, { messageRecordId: 'm2' }]);
expect(result.get('m1')).toMatchObject({ status: 'pending_review' });
expect(route).toHaveBeenCalledWith([expect.objectContaining({ id: 'm2' })]);
});
it('propagates database failures without submitting or misclassifying them as routing failures', async () => {
const { sut, risk, facade, prisma } = setup();
risk.guardNightSending.mockRejectedValue(new Error('database unavailable'));
await expect(sut.processSendJob({ messageRecordId: 'm1' })).rejects.toThrow('database unavailable');
expect(prisma.smsMessageRecord.update).not.toHaveBeenCalled();
expect(facade.submitMessageToGateway).not.toHaveBeenCalled();
});
});