import { describe, it, expect, mock } from 'bun:test';
import { withRetry, defaultRetryOptions } from '@/utils/retry.js';
describe('retry utility', () => {
describe('withRetry', () => {
it('should succeed on first try', async () => {
const fn = mock().mockResolvedValue('success');
const result = await withRetry(fn);
expect(result).toBe('success');
expect(fn).toHaveBeenCalledTimes(1);
});
it('should retry on failure and eventually succeed', async () => {
let callCount = 0;
const fn = mock(() => {
callCount++;
if (callCount === 1) throw new Error('fail 1');
if (callCount === 2) throw new Error('fail 2');
return Promise.resolve('success');
});
const result = await withRetry(fn, { maxAttempts: 3, baseDelay: 1 });
expect(result).toBe('success');
expect(fn).toHaveBeenCalledTimes(3);
});
it('should throw after max attempts', async () => {
const fn = mock().mockRejectedValue(new Error('always fails'));
await expect(withRetry(fn, { maxAttempts: 2, baseDelay: 1 })).rejects.toThrow('always fails');
expect(fn).toHaveBeenCalledTimes(2);
});
it('should use default options', async () => {
const fn = mock().mockRejectedValue(new Error('fail'));
await expect(withRetry(fn, { baseDelay: 1 })).rejects.toThrow('fail');
expect(fn).toHaveBeenCalledTimes(defaultRetryOptions.maxAttempts);
});
it('should handle non-error rejections', async () => {
const fn = mock().mockRejectedValue('string error');
await expect(withRetry(fn, { maxAttempts: 1 })).rejects.toThrow('string error');
});
});
});