kt-template-online-api/test/qqbot/plugins/bangDream/provider/cache-policy.spec.ts

62 lines
1.8 KiB
TypeScript

import {
getCacheClientErrorMessage,
getCacheClientResponseStatus,
isCacheClientNotFound,
normalizeCacheClientRetryCount,
runWithCacheClientRetry,
} from '@/qqbot/plugins/bangDream/provider/cache-policy';
describe('BangDream cache client policy', () => {
it('normalizes retry count and reads http status safely', () => {
const notFoundError = Object.assign(new Error('not found'), {
response: { status: 404 },
});
expect(normalizeCacheClientRetryCount(0)).toBe(1);
expect(normalizeCacheClientRetryCount(3)).toBe(3);
expect(getCacheClientResponseStatus(notFoundError)).toBe(404);
expect(isCacheClientNotFound(notFoundError)).toBe(true);
expect(getCacheClientErrorMessage(notFoundError)).toBe('not found');
expect(getCacheClientResponseStatus('plain')).toBeUndefined();
});
it('retries transient failures with a bounded retry count', async () => {
const action = jest
.fn()
.mockRejectedValueOnce(new Error('temporary'))
.mockResolvedValue('ok');
const onRetry = jest.fn();
await expect(
runWithCacheClientRetry({
action,
delayMs: 0,
onRetry,
retryCount: 2,
}),
).resolves.toBe('ok');
expect(action).toHaveBeenCalledTimes(2);
expect(onRetry).toHaveBeenCalledWith(
2,
2,
expect.objectContaining({ message: 'temporary' }),
);
});
it('does not retry when the caller marks the error as non-retryable', async () => {
const action = jest.fn().mockRejectedValue(new Error('missing'));
await expect(
runWithCacheClientRetry({
action,
delayMs: 0,
retryCount: 3,
shouldRetry: () => false,
}),
).rejects.toThrow('missing');
expect(action).toHaveBeenCalledTimes(1);
});
});