fix: resolve all test failures after vitest 2.x upgrade
- Attach rejects handler before advancing timers (vitest 2.x strict mode) - Fix FK constraint cleanup order in test setup - Fix 7-char prefix matching test data - Add INSERT OR IGNORE for deposit concurrency safety - Add secondary ORDER BY for deterministic transaction ordering - Update summary-service test assertions to match current prompt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -145,9 +145,12 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 2 });
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
// Attach error handler before advancing timers
|
||||
const expectPromise = expect(promise).rejects.toThrow(RetryError);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
|
||||
await expect(promise).rejects.toThrow(RetryError);
|
||||
expect(mockFn).toHaveBeenCalledTimes(3); // Initial + 2 retries
|
||||
});
|
||||
|
||||
@@ -159,21 +162,20 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 1 });
|
||||
|
||||
// Attach catch handler before advancing timers
|
||||
const errorPromise = promise.catch(error => error);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
try {
|
||||
await promise;
|
||||
expect.fail('Should have thrown RetryError');
|
||||
} catch (error) {
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
const error = await errorPromise;
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.name).toBe('RetryError');
|
||||
expect(retryError.attempts).toBe(2); // Initial + 1 retry
|
||||
expect(retryError.lastError).toBe(originalError);
|
||||
expect(retryError.lastError.message).toBe('Original failure');
|
||||
expect(retryError.lastError.stack).toBe('Original stack trace');
|
||||
}
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.name).toBe('RetryError');
|
||||
expect(retryError.attempts).toBe(2); // Initial + 1 retry
|
||||
expect(retryError.lastError).toBe(originalError);
|
||||
expect(retryError.lastError.message).toBe('Original failure');
|
||||
expect(retryError.lastError.stack).toBe('Original stack trace');
|
||||
});
|
||||
|
||||
it('should include attempts count in RetryError message', async () => {
|
||||
@@ -181,16 +183,15 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 2 });
|
||||
|
||||
// Attach catch handler before advancing timers
|
||||
const errorPromise = promise.catch(error => error);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
try {
|
||||
await promise;
|
||||
expect.fail('Should have thrown RetryError');
|
||||
} catch (error) {
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.message).toContain('3 attempts'); // Initial + 2 retries
|
||||
expect(retryError.message).toContain('API error');
|
||||
}
|
||||
const error = await errorPromise;
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.message).toContain('3 attempts'); // Initial + 2 retries
|
||||
expect(retryError.message).toContain('API error');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -294,11 +295,14 @@ describe('retryWithBackoff', () => {
|
||||
jitter: false,
|
||||
});
|
||||
|
||||
// Attach error handler before advancing timers
|
||||
const expectPromise = expect(promise).rejects.toThrow(RetryError);
|
||||
|
||||
// After several retries, delay should cap at 10000ms
|
||||
// Let's verify it doesn't exceed 10000ms by checking timer behavior
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
await expect(promise).rejects.toThrow(RetryError);
|
||||
await expectPromise;
|
||||
expect(mockFn).toHaveBeenCalledTimes(21); // Initial + 20 retries
|
||||
});
|
||||
});
|
||||
@@ -395,9 +399,12 @@ describe('retryWithBackoff', () => {
|
||||
maxRetries: customMaxRetries,
|
||||
});
|
||||
|
||||
// Attach error handler before advancing timers
|
||||
const expectPromise = expect(promise).rejects.toThrow(RetryError);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
await expect(promise).rejects.toThrow(RetryError);
|
||||
await expectPromise;
|
||||
expect(mockFn).toHaveBeenCalledTimes(customMaxRetries + 1); // Initial + retries
|
||||
});
|
||||
|
||||
@@ -470,9 +477,12 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 0 });
|
||||
|
||||
// Attach error handler before advancing timers
|
||||
const expectPromise = expect(promise).rejects.toThrow(RetryError);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
await expect(promise).rejects.toThrow(RetryError);
|
||||
await expectPromise;
|
||||
expect(mockFn).toHaveBeenCalledTimes(1); // Only initial attempt
|
||||
});
|
||||
});
|
||||
@@ -483,17 +493,16 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 1 });
|
||||
|
||||
// Attach catch handler before advancing timers
|
||||
const errorPromise = promise.catch(error => error);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
try {
|
||||
await promise;
|
||||
expect.fail('Should have thrown RetryError');
|
||||
} catch (error) {
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.lastError).toBeInstanceOf(Error);
|
||||
expect(retryError.lastError.message).toBe('String error');
|
||||
}
|
||||
const error = await errorPromise;
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.lastError).toBeInstanceOf(Error);
|
||||
expect(retryError.lastError.message).toBe('String error');
|
||||
});
|
||||
|
||||
it('should handle undefined rejections', async () => {
|
||||
@@ -501,17 +510,16 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 1 });
|
||||
|
||||
// Attach catch handler before advancing timers
|
||||
const errorPromise = promise.catch(error => error);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
try {
|
||||
await promise;
|
||||
expect.fail('Should have thrown RetryError');
|
||||
} catch (error) {
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.lastError).toBeInstanceOf(Error);
|
||||
expect(retryError.lastError.message).toBe('undefined');
|
||||
}
|
||||
const error = await errorPromise;
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.lastError).toBeInstanceOf(Error);
|
||||
expect(retryError.lastError.message).toBe('undefined');
|
||||
});
|
||||
|
||||
it('should work with serviceName for metrics tracking', async () => {
|
||||
@@ -567,22 +575,21 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 2 });
|
||||
|
||||
// Attach catch handler before advancing timers
|
||||
const errorPromise = promise.catch(error => error);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
try {
|
||||
await promise;
|
||||
expect.fail('Should have thrown RetryError');
|
||||
} catch (error) {
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
const error = await errorPromise;
|
||||
expect(error).toBeInstanceOf(RetryError);
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.name).toBe('RetryError');
|
||||
expect(retryError.attempts).toBe(3); // Initial + 2 retries
|
||||
expect(retryError.lastError).toBe(originalError);
|
||||
expect(retryError.message).toContain('3 attempts');
|
||||
expect(retryError.message).toContain('Test error');
|
||||
}
|
||||
const retryError = error as RetryError;
|
||||
expect(retryError.name).toBe('RetryError');
|
||||
expect(retryError.attempts).toBe(3); // Initial + 2 retries
|
||||
expect(retryError.lastError).toBe(originalError);
|
||||
expect(retryError.message).toContain('3 attempts');
|
||||
expect(retryError.message).toContain('Test error');
|
||||
});
|
||||
|
||||
it('should be catchable as Error', async () => {
|
||||
@@ -590,17 +597,17 @@ describe('retryWithBackoff', () => {
|
||||
|
||||
const promise = retryWithBackoff(mockFn, { maxRetries: 0 });
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
// Attach catch handler before advancing timers
|
||||
let caughtError: Error | null = null;
|
||||
|
||||
try {
|
||||
await promise;
|
||||
} catch (error) {
|
||||
const errorPromise = promise.catch(error => {
|
||||
if (error instanceof Error) {
|
||||
caughtError = error;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
});
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
await errorPromise;
|
||||
|
||||
expect(caughtError).not.toBeNull();
|
||||
expect(caughtError).toBeInstanceOf(Error);
|
||||
|
||||
Reference in New Issue
Block a user