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:
@@ -8,10 +8,6 @@
|
||||
* 4. 타임아웃 처리
|
||||
* 5. 재시도 로직 통합
|
||||
* 6. 커스텀 헤더 및 옵션
|
||||
*
|
||||
* Note: Vitest may report "unhandled errors" due to timing issues with
|
||||
* fake timers and async promise rejections. All tests pass successfully
|
||||
* (25/25 passing) - these are expected error logs, not test failures.
|
||||
*/
|
||||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
||||
import { z } from 'zod';
|
||||
@@ -144,13 +140,12 @@ describe('callApi', () => {
|
||||
json: async () => ({ error: 'Resource not found' }),
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/missing', {
|
||||
retries: 0, // 재시도 없음
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/missing', {
|
||||
retries: 0, // 재시도 없음
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
it('should throw error on 5xx server error', async () => {
|
||||
@@ -161,13 +156,12 @@ describe('callApi', () => {
|
||||
json: async () => ({ error: 'Server crashed' }),
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/error', {
|
||||
retries: 0,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/error', {
|
||||
retries: 0,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
it('should include status code in error message', async () => {
|
||||
@@ -178,13 +172,12 @@ describe('callApi', () => {
|
||||
json: async () => ({}),
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/forbidden', {
|
||||
retries: 0,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow(/403/);
|
||||
const promise = callApi('https://api.example.com/forbidden', {
|
||||
retries: 0,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow(/403/);
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -230,14 +223,13 @@ describe('callApi', () => {
|
||||
json: async () => invalidData,
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/user', {
|
||||
schema: UserSchema,
|
||||
retries: 0,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/user', {
|
||||
schema: UserSchema,
|
||||
retries: 0,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
it('should throw error on invalid schema (wrong type)', async () => {
|
||||
@@ -252,14 +244,13 @@ describe('callApi', () => {
|
||||
json: async () => invalidData,
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/user', {
|
||||
schema: UserSchema,
|
||||
retries: 0,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/user', {
|
||||
schema: UserSchema,
|
||||
retries: 0,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
it('should throw error on invalid email format', async () => {
|
||||
@@ -274,14 +265,13 @@ describe('callApi', () => {
|
||||
json: async () => invalidData,
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/user', {
|
||||
schema: UserSchema,
|
||||
retries: 0,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/user', {
|
||||
schema: UserSchema,
|
||||
retries: 0,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -301,19 +291,18 @@ describe('callApi', () => {
|
||||
};
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/slow', {
|
||||
retries: 0,
|
||||
});
|
||||
const promise = callApi('https://api.example.com/slow', {
|
||||
retries: 0,
|
||||
});
|
||||
|
||||
// 타임아웃 전에는 에러 없음
|
||||
await vi.advanceTimersByTimeAsync(29000);
|
||||
// 타임아웃 전에는 에러 없음
|
||||
await vi.advanceTimersByTimeAsync(29000);
|
||||
|
||||
// 타임아웃 발생
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
// 타임아웃 발생
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
it('should use custom timeout value', async () => {
|
||||
@@ -330,20 +319,19 @@ describe('callApi', () => {
|
||||
};
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/slow', {
|
||||
timeout: 5000, // 5초 타임아웃
|
||||
retries: 0,
|
||||
});
|
||||
const promise = callApi('https://api.example.com/slow', {
|
||||
timeout: 5000, // 5초 타임아웃
|
||||
retries: 0,
|
||||
});
|
||||
|
||||
// 타임아웃 전
|
||||
await vi.advanceTimersByTimeAsync(4000);
|
||||
// 타임아웃 전
|
||||
await vi.advanceTimersByTimeAsync(4000);
|
||||
|
||||
// 타임아웃 발생
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
// 타임아웃 발생
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
it('should complete before timeout', async () => {
|
||||
@@ -435,13 +423,12 @@ describe('callApi', () => {
|
||||
json: async () => ({}),
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/always-fails', {
|
||||
retries: 2,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/always-fails', {
|
||||
retries: 2,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
expect(mockFetch).toHaveBeenCalledTimes(3); // 초기 + 2회 재시도
|
||||
});
|
||||
|
||||
@@ -453,13 +440,12 @@ describe('callApi', () => {
|
||||
json: async () => ({}),
|
||||
});
|
||||
|
||||
await expect(async () => {
|
||||
const promise = callApi('https://api.example.com/missing', {
|
||||
retries: 3,
|
||||
});
|
||||
await vi.runAllTimersAsync();
|
||||
await promise;
|
||||
}).rejects.toThrow();
|
||||
const promise = callApi('https://api.example.com/missing', {
|
||||
retries: 3,
|
||||
});
|
||||
const expectPromise = expect(promise).rejects.toThrow();
|
||||
await vi.runAllTimersAsync();
|
||||
await expectPromise;
|
||||
// 재시도 로직은 4xx 에러를 재시도하지 않음 (retryWithBackoff 구현에 따라 다름)
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user