test: add comprehensive unit tests for utils and security
- Add security.test.ts: 36 tests for webhook validation, rate limiting - Add circuit-breaker.test.ts: 31 tests for state transitions - Add retry.test.ts: 25 tests for exponential backoff - Add api-helper.test.ts: 25 tests for API abstraction - Add optimistic-lock.test.ts: 11 tests for concurrency control - Add summary-service.test.ts: 29 tests for profile system Total: 157 new test cases (222 passing overall) - Fix setup.ts D1 schema initialization for Miniflare - Update vitest.config.ts to exclude demo files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
105
tests/setup.ts
105
tests/setup.ts
@@ -6,40 +6,66 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { beforeAll, afterEach } from 'vitest';
|
||||
import { Miniflare } from 'miniflare';
|
||||
|
||||
let mf: Miniflare | null = null;
|
||||
let db: D1Database | null = null;
|
||||
|
||||
// 이전 코드와의 호환성을 위한 전역 함수
|
||||
declare global {
|
||||
function getMiniflareBindings(): {
|
||||
var getMiniflareBindings: () => {
|
||||
DB: D1Database;
|
||||
RATE_LIMIT_KV: KVNamespace;
|
||||
};
|
||||
}
|
||||
|
||||
let db: D1Database | null = null;
|
||||
|
||||
beforeAll(async () => {
|
||||
// Miniflare 바인딩 가져오기 (있을 경우만)
|
||||
if (typeof getMiniflareBindings === 'function') {
|
||||
try {
|
||||
const bindings = getMiniflareBindings();
|
||||
db = bindings.DB;
|
||||
// Miniflare 인스턴스 생성 (D1만 사용)
|
||||
mf = new Miniflare({
|
||||
modules: true,
|
||||
script: 'export default { fetch() { return new Response("test"); } }',
|
||||
d1Databases: {
|
||||
DB: '__test_db__',
|
||||
},
|
||||
kvNamespaces: ['RATE_LIMIT_KV', 'SESSION_KV'],
|
||||
bindings: {
|
||||
SUMMARY_THRESHOLD: '20',
|
||||
MAX_SUMMARIES_PER_USER: '3',
|
||||
},
|
||||
});
|
||||
|
||||
// 스키마 초기화
|
||||
const schemaPath = join(__dirname, '../schema.sql');
|
||||
const schema = readFileSync(schemaPath, 'utf-8');
|
||||
db = await mf.getD1Database('DB');
|
||||
|
||||
// 각 statement를 개별 실행
|
||||
const statements = schema
|
||||
.split(';')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0 && !s.startsWith('--'));
|
||||
// 전역 함수 등록
|
||||
(global as any).getMiniflareBindings = () => ({
|
||||
DB: db as D1Database,
|
||||
RATE_LIMIT_KV: {} as KVNamespace, // Mock KV (테스트에 필요 시)
|
||||
});
|
||||
|
||||
for (const statement of statements) {
|
||||
await db.exec(statement);
|
||||
}
|
||||
} catch (error) {
|
||||
// Miniflare 바인딩이 없는 테스트는 skip
|
||||
console.warn('Miniflare bindings not available, skipping DB setup');
|
||||
// 스키마 초기화
|
||||
const schemaPath = join(__dirname, '../schema.sql');
|
||||
const schema = readFileSync(schemaPath, 'utf-8');
|
||||
|
||||
// 주석 제거하고 statement별로 분리
|
||||
const cleanSchema = schema
|
||||
.split('\n')
|
||||
.filter(line => !line.trim().startsWith('--'))
|
||||
.join('\n');
|
||||
|
||||
// 세미콜론으로 statement 분리하고 각 statement를 한 줄로 압축
|
||||
const statements = cleanSchema
|
||||
.split(';')
|
||||
.map(s => s.replace(/\s+/g, ' ').trim())
|
||||
.filter(s => s.length > 0);
|
||||
|
||||
// 각 statement 개별 실행
|
||||
try {
|
||||
for (const statement of statements) {
|
||||
await db.exec(statement + ';');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Schema initialization failed:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -117,3 +143,38 @@ export async function createDepositTransaction(
|
||||
export function getTestDB(): D1Database {
|
||||
return getMiniflareBindings().DB;
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트용 헬퍼 함수: 요약 생성
|
||||
*/
|
||||
export async function createSummary(
|
||||
userId: number,
|
||||
chatId: string,
|
||||
generation: number,
|
||||
summary: string,
|
||||
messageCount: number
|
||||
): Promise<number> {
|
||||
const bindings = getMiniflareBindings();
|
||||
const result = await bindings.DB.prepare(
|
||||
'INSERT INTO summaries (user_id, chat_id, generation, summary, message_count) VALUES (?, ?, ?, ?, ?)'
|
||||
).bind(userId, chatId, generation, summary, messageCount).run();
|
||||
|
||||
return Number(result.meta?.last_row_id || 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트용 헬퍼 함수: 메시지 버퍼 생성
|
||||
*/
|
||||
export async function createMessageBuffer(
|
||||
userId: number,
|
||||
chatId: string,
|
||||
role: 'user' | 'bot',
|
||||
message: string
|
||||
): Promise<number> {
|
||||
const bindings = getMiniflareBindings();
|
||||
const result = await bindings.DB.prepare(
|
||||
'INSERT INTO message_buffer (user_id, chat_id, role, message) VALUES (?, ?, ?, ?)'
|
||||
).bind(userId, chatId, role, message).run();
|
||||
|
||||
return Number(result.meta?.last_row_id || 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user