Files
whale-town-end/test/zulip_integration/real_zulip_api.spec.ts
moyin d04ab7f75f CRITICAL ISSUES: Database management service with major problems
WARNING: This commit contains code with significant issues that need immediate attention:

1. Type Safety Issues:
   - Unused import ZulipAccountsService causing compilation warnings
   - Implicit 'any' type in formatZulipAccount method parameter
   - Type inconsistencies in service injections

2. Service Integration Problems:
   - Inconsistent service interface usage
   - Missing proper type definitions for injected services
   - Potential runtime errors due to type mismatches

3. Code Quality Issues:
   - Violation of TypeScript strict mode requirements
   - Inconsistent error handling patterns
   - Missing proper interface implementations

 Files affected:
   - src/business/admin/database_management.service.ts (main issue)
   - Multiple test files and service implementations
   - Configuration and documentation updates

 Next steps required:
   1. Fix TypeScript compilation errors
   2. Implement proper type safety
   3. Resolve service injection inconsistencies
   4. Add comprehensive error handling
   5. Update tests to match new implementations

 Impact: High - affects admin functionality and system stability
 Priority: Urgent - requires immediate review and fixes

Author: moyin
Date: 2026-01-10
2026-01-10 19:27:28 +08:00

393 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 真实Zulip API测试
*
* 功能描述:
* - 测试与真实Zulip服务器的HTTP通信
* - 验证API请求格式、认证和响应处理
* - 需要真实的Zulip服务器配置才能运行
*
* 注意:
* - 这些测试需要设置环境变量ZULIP_SERVER_URL, ZULIP_BOT_EMAIL, ZULIP_BOT_API_KEY
* - 如果没有配置,测试将被跳过
* - 测试会在真实服务器上创建消息,请谨慎使用
*
* @author moyin
* @version 1.0.0
* @since 2026-01-10
*/
import { Test, TestingModule } from '@nestjs/testing';
import { ZulipClientService, ZulipClientConfig, SendMessageResult } from '../../src/core/zulip_core/services/zulip_client.service';
// 测试配置
const REAL_ZULIP_CONFIG = {
serverUrl: process.env.ZULIP_SERVER_URL || '',
botEmail: process.env.ZULIP_BOT_EMAIL || '',
botApiKey: process.env.ZULIP_BOT_API_KEY || '',
testStream: process.env.ZULIP_TEST_STREAM || 'test-stream',
testTopic: process.env.ZULIP_TEST_TOPIC || 'API Test',
};
// 检查是否有真实配置
const hasRealConfig: boolean = !!(REAL_ZULIP_CONFIG.serverUrl &&
REAL_ZULIP_CONFIG.botEmail &&
REAL_ZULIP_CONFIG.botApiKey);
describe('Real Zulip API Integration', () => {
let service: ZulipClientService;
let clientConfig: ZulipClientConfig;
beforeAll(async () => {
if (!hasRealConfig) {
console.warn('跳过真实Zulip API测试缺少环境变量配置');
console.warn('需要设置: ZULIP_SERVER_URL, ZULIP_BOT_EMAIL, ZULIP_BOT_API_KEY');
return;
}
const module: TestingModule = await Test.createTestingModule({
providers: [ZulipClientService],
}).compile();
service = module.get<ZulipClientService>(ZulipClientService);
clientConfig = {
username: REAL_ZULIP_CONFIG.botEmail,
apiKey: REAL_ZULIP_CONFIG.botApiKey,
realm: REAL_ZULIP_CONFIG.serverUrl,
};
});
// 如果没有真实配置,跳过所有测试
const testIf = (condition: boolean) => condition ? it : it.skip;
describe('API连接测试', () => {
testIf(hasRealConfig)('应该能够连接到Zulip服务器', async () => {
const clientInstance = await service.createClient('test-user', clientConfig);
expect(clientInstance).toBeDefined();
expect(clientInstance.isValid).toBe(true);
expect(clientInstance.config.realm).toBe(REAL_ZULIP_CONFIG.serverUrl);
// 清理
await service.destroyClient(clientInstance);
}, 10000);
testIf(hasRealConfig)('应该能够验证API Key', async () => {
const clientInstance = await service.createClient('test-user', clientConfig);
const isValid = await service.validateApiKey(clientInstance);
expect(isValid).toBe(true);
await service.destroyClient(clientInstance);
}, 10000);
testIf(hasRealConfig)('应该拒绝无效的API Key', async () => {
const invalidConfig = {
...clientConfig,
apiKey: 'invalid-api-key-12345',
};
await expect(service.createClient('test-user', invalidConfig))
.rejects.toThrow();
}, 10000);
});
describe('消息发送测试', () => {
let clientInstance: any;
beforeEach(async () => {
if (!hasRealConfig) return;
clientInstance = await service.createClient('test-user', clientConfig);
});
afterEach(async () => {
if (clientInstance) {
await service.destroyClient(clientInstance);
}
});
testIf(hasRealConfig)('应该能够发送消息到Zulip', async () => {
const testMessage = `Test message from automated test - ${new Date().toISOString()}`;
const result = await service.sendMessage(
clientInstance,
REAL_ZULIP_CONFIG.testStream,
REAL_ZULIP_CONFIG.testTopic,
testMessage
);
expect(result.success).toBe(true);
expect(result.messageId).toBeDefined();
expect(typeof result.messageId).toBe('number');
console.log(`消息发送成功ID: ${result.messageId}`);
}, 15000);
testIf(hasRealConfig)('应该处理不存在的Stream', async () => {
const result = await service.sendMessage(
clientInstance,
'nonexistent-stream-12345',
'test-topic',
'This should fail'
);
expect(result.success).toBe(false);
expect(result.error).toBeDefined();
console.log(`预期的错误: ${result.error}`);
}, 10000);
testIf(hasRealConfig)('应该能够发送包含特殊字符的消息', async () => {
const specialMessage = `特殊字符测试 🎮🎯🚀 @#$%^&*() - ${new Date().toISOString()}`;
const result = await service.sendMessage(
clientInstance,
REAL_ZULIP_CONFIG.testStream,
REAL_ZULIP_CONFIG.testTopic,
specialMessage
);
expect(result.success).toBe(true);
expect(result.messageId).toBeDefined();
}, 10000);
testIf(hasRealConfig)('应该能够发送Markdown格式的消息', async () => {
const markdownMessage = `
# Markdown测试消息
**粗体文本** 和 *斜体文本*
- 列表项 1
- 列表项 2
\`代码块\`
> 引用文本
[链接](https://example.com)
时间戳: ${new Date().toISOString()}
`.trim();
const result = await service.sendMessage(
clientInstance,
REAL_ZULIP_CONFIG.testStream,
REAL_ZULIP_CONFIG.testTopic,
markdownMessage
);
expect(result.success).toBe(true);
expect(result.messageId).toBeDefined();
}, 10000);
});
describe('事件队列测试', () => {
let clientInstance: any;
beforeEach(async () => {
if (!hasRealConfig) return;
clientInstance = await service.createClient('test-user', clientConfig);
});
afterEach(async () => {
if (clientInstance) {
await service.destroyClient(clientInstance);
}
});
testIf(hasRealConfig)('应该能够注册事件队列', async () => {
const result = await service.registerQueue(clientInstance, ['message']);
expect(result.success).toBe(true);
expect(result.queueId).toBeDefined();
expect(result.lastEventId).toBeDefined();
expect(typeof result.lastEventId).toBe('number');
console.log(`队列注册成功ID: ${result.queueId}, 最后事件ID: ${result.lastEventId}`);
}, 10000);
testIf(hasRealConfig)('应该能够获取事件', async () => {
// 先注册队列
const registerResult = await service.registerQueue(clientInstance, ['message']);
expect(registerResult.success).toBe(true);
// 获取事件(非阻塞模式)
const eventsResult = await service.getEvents(clientInstance, true);
expect(eventsResult.success).toBe(true);
expect(Array.isArray(eventsResult.events)).toBe(true);
console.log(`获取到 ${eventsResult.events?.length || 0} 个事件`);
}, 10000);
testIf(hasRealConfig)('应该能够注销事件队列', async () => {
// 先注册队列
const registerResult = await service.registerQueue(clientInstance, ['message']);
expect(registerResult.success).toBe(true);
// 注销队列
const deregisterResult = await service.deregisterQueue(clientInstance);
expect(deregisterResult).toBe(true);
expect(clientInstance.queueId).toBeUndefined();
}, 10000);
});
describe('HTTP请求详细测试', () => {
testIf(hasRealConfig)('应该发送正确格式的HTTP请求', async () => {
// 这个测试验证HTTP请求的具体格式
const clientInstance = await service.createClient('test-user', clientConfig);
// 监听HTTP请求这需要拦截zulip-js的请求
const originalSend = clientInstance.client.messages.send;
let capturedRequest: any = null;
clientInstance.client.messages.send = jest.fn().mockImplementation(async (params) => {
capturedRequest = params;
return originalSend.call(clientInstance.client.messages, params);
});
const testMessage = `HTTP格式测试 - ${new Date().toISOString()}`;
const result = await service.sendMessage(
clientInstance,
REAL_ZULIP_CONFIG.testStream,
REAL_ZULIP_CONFIG.testTopic,
testMessage
);
expect(result.success).toBe(true);
expect(capturedRequest).toBeDefined();
expect(capturedRequest.type).toBe('stream');
expect(capturedRequest.to).toBe(REAL_ZULIP_CONFIG.testStream);
expect(capturedRequest.subject).toBe(REAL_ZULIP_CONFIG.testTopic);
expect(capturedRequest.content).toBe(testMessage);
await service.destroyClient(clientInstance);
}, 15000);
});
describe('错误处理测试', () => {
testIf(hasRealConfig)('应该处理网络超时', async () => {
const clientInstance = await service.createClient('test-user', clientConfig);
// 模拟网络超时(通过修改客户端配置或使用无效的服务器地址)
const timeoutConfig = {
...clientConfig,
realm: 'https://timeout-test.invalid-domain-12345.com',
};
try {
const timeoutClient = await service.createClient('timeout-test', timeoutConfig);
// 如果到达这里,说明没有超时,跳过测试
await service.destroyClient(timeoutClient);
console.log('网络超时测试跳过:连接成功');
} catch (error) {
// 预期的超时错误
expect(error).toBeDefined();
console.log(`预期的超时错误: ${(error as Error).message}`);
}
await service.destroyClient(clientInstance);
}, 20000);
testIf(hasRealConfig)('应该处理认证错误', async () => {
const invalidConfig = {
...clientConfig,
apiKey: 'definitely-invalid-api-key-12345',
};
try {
await service.createClient('auth-test', invalidConfig);
fail('应该抛出认证错误');
} catch (error) {
expect(error).toBeDefined();
expect((error as Error).message).toContain('API Key验证失败');
console.log(`预期的认证错误: ${(error as Error).message}`);
}
}, 10000);
});
describe('性能测试', () => {
testIf(hasRealConfig)('应该测量消息发送性能', async () => {
const clientInstance = await service.createClient('perf-test', clientConfig);
const messageCount = 10; // 减少数量以避免对服务器造成压力
const startTime = Date.now();
const promises: Promise<SendMessageResult>[] = [];
for (let i = 0; i < messageCount; i++) {
promises.push(
service.sendMessage(
clientInstance,
REAL_ZULIP_CONFIG.testStream,
'Performance Test',
`Performance test message ${i} - ${new Date().toISOString()}`
)
);
}
const results = await Promise.all(promises);
const endTime = Date.now();
const duration = endTime - startTime;
// 验证所有消息都成功发送
results.forEach((result, index) => {
expect(result.success).toBe(true);
console.log(`消息 ${index}: ID ${result.messageId}`);
});
const avgTime = duration / messageCount;
console.log(`发送${messageCount}条消息耗时: ${duration}ms, 平均: ${avgTime.toFixed(2)}ms/条`);
// 性能断言(根据网络情况调整)
expect(avgTime).toBeLessThan(2000); // 平均每条消息不超过2秒
await service.destroyClient(clientInstance);
}, 30000);
});
// 清理测试:在所有测试完成后清理测试数据
describe('清理测试', () => {
testIf(hasRealConfig)('应该发送清理完成消息', async () => {
const clientInstance = await service.createClient('cleanup-test', clientConfig);
const cleanupMessage = `
🧹 自动化测试完成 - ${new Date().toISOString()}
本次测试运行的消息已发送完毕。
如果看到此消息说明Zulip API集成测试成功完成。
测试包括:
- ✅ API连接和认证
- ✅ 消息发送和格式化
- ✅ 事件队列管理
- ✅ 错误处理
- ✅ 性能测试
所有测试消息可以安全删除。
`.trim();
const result = await service.sendMessage(
clientInstance,
REAL_ZULIP_CONFIG.testStream,
'Test Cleanup',
cleanupMessage
);
expect(result.success).toBe(true);
console.log('清理消息发送成功');
await service.destroyClient(clientInstance);
}, 10000);
});
});
// 导出配置检查函数,供其他测试使用
export function hasZulipConfig(): boolean {
return hasRealConfig;
}
export function getZulipTestConfig() {
return REAL_ZULIP_CONFIG;
}