/**
* Jest 测试设置文件
*/
import { config as loadEnvConfig } from 'dotenv';
import { ZenTaoClient } from '../src/client';
import { LRUCache } from '../src/utils/cache';
import { Logger, LogLevel } from '../src/utils/logger';
// 加载环境变量
loadEnvConfig({ path: '.env' });
// 全局测试变量
global.testConfig = {
baseUrl: process.env.ZENDTAO_BASE_URL || 'http://localhost',
token: process.env.ZENDTAO_TOKEN || '',
timeout: parseInt(process.env.ZENDTAO_TIMEOUT || '30000'),
retry: parseInt(process.env.ZENDTAO_RETRY || '3'),
retryDelay: parseInt(process.env.ZENDTAO_RETRY_DELAY || '1000')
};
// 全局变量
declare global {
var testConfig: {
baseUrl: string;
token: string;
timeout: number;
retry: number;
retryDelay: number;
};
var testClient: ZenTaoClient;
var testCache: LRUCache<string, any>;
var testLogger: Logger;
}
beforeAll(async () => {
console.log('\n=== 初始化测试环境 ===');
// 检查环境配置
if (!global.testConfig.token) {
console.warn('⚠️ 警告: 未设置 ZENDTAO_TOKEN,测试可能会失败');
}
// 创建测试客户端
global.testLogger = new Logger(LogLevel.ERROR); // 测试时只显示错误
global.testClient = new ZenTaoClient(global.testConfig, global.testLogger);
global.testCache = new LRUCache<string, any>({
maxSize: 100,
defaultTtl: 5 * 60 * 1000,
enableStats: true
});
// 等待服务就绪
await waitForZenTaoService();
console.log('✅ 测试环境初始化完成\n');
}, 60000);
afterEach(async () => {
// 清理缓存
global.testCache.clear();
});
afterAll(async () => {
console.log('\n=== 清理测试环境 ===');
// 清理缓存统计
const stats = global.testCache.getStats();
console.log('缓存统计:', stats);
console.log('✅ 测试环境清理完成\n');
});
// 等待禅道服务就绪
async function waitForZenTaoService(): Promise<void> {
const maxAttempts = 30;
let attempts = 0;
while (attempts < maxAttempts) {
try {
await global.testClient.verifyConnection();
console.log('✅ 禅道服务连接成功');
return;
} catch (error) {
attempts++;
if (attempts >= maxAttempts) {
throw new Error(`禅道服务连接失败,已重试 ${maxAttempts} 次`);
}
console.log(`⏳ 等待禅道服务... (${attempts}/${maxAttempts})`);
await delay(2000);
}
}
}
// 延迟函数
export function delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 辅助函数:生成唯一测试名称
export function generateTestName(prefix: string): string {
const timestamp = Date.now();
const random = Math.random().toString(36).substring(2, 8);
return `${prefix}-${timestamp}-${random}`;
}
// 辅助函数:验证 Token 格式
export function validateTokenFormat(token: string): boolean {
return /^s\d+:[a-f0-9]{32}$/i.test(token);
}
// 辅助函数:检查对象是否具有必需属性
export function hasRequiredProperties(obj: any, properties: string[]): boolean {
return properties.every(prop => obj.hasOwnProperty(prop));
}