7bc4f006a0
- 新增 checkpoints.test.ts: 29 个测试覆盖 Checkpoint 管理 API - 新增 mcp.test.ts: 15 个测试覆盖 MCP 服务器管理 API - 扩展 sse.test.ts: 添加 handleSSE 路由测试 - 扩展 adapter.test.ts: 添加 cancelProcessing, getContextUsage, compressContext, processMessage 测试 覆盖率提升: 60% -> 80.82% 测试数量: 288 -> 344
175 lines
4.7 KiB
TypeScript
175 lines
4.7 KiB
TypeScript
/**
|
|
* SSE (Server-Sent Events) Handler 测试
|
|
*
|
|
* 测试 SSE 事件格式、订阅者管理、各类事件发送等功能
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import { Hono } from 'hono';
|
|
|
|
// Mock dependencies before imports
|
|
const mockExists = vi.fn();
|
|
const mockSessionManager = {
|
|
exists: mockExists,
|
|
};
|
|
|
|
vi.mock('../../src/session/manager.js', () => ({
|
|
getSessionManager: vi.fn(() => mockSessionManager),
|
|
}));
|
|
|
|
// Import after mocking
|
|
import {
|
|
emitEvent,
|
|
broadcastEvent,
|
|
emitStatusEvent,
|
|
emitLogEvent,
|
|
emitProgressEvent,
|
|
emitFileChangeEvent,
|
|
getSSEStats,
|
|
handleSSE,
|
|
} from '../../src/sse.js';
|
|
|
|
describe('SSE Handler', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockExists.mockReturnValue(true);
|
|
});
|
|
|
|
describe('emitEvent - 发送事件', () => {
|
|
it('无订阅者时不抛出错误', () => {
|
|
expect(() => {
|
|
emitEvent('non-existent-session', {
|
|
event: 'test',
|
|
data: { timestamp: Date.now(), payload: null },
|
|
});
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('broadcastEvent - 广播事件', () => {
|
|
it('无订阅者时不抛出错误', () => {
|
|
expect(() => {
|
|
broadcastEvent({
|
|
event: 'broadcast-test',
|
|
data: { timestamp: Date.now(), payload: { message: 'hello' } },
|
|
});
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('emitStatusEvent - 发送状态事件', () => {
|
|
it('调用时不抛出错误', () => {
|
|
expect(() => {
|
|
emitStatusEvent('session-1', 'processing', { step: 1, total: 5 });
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('只传状态不传详情时不抛出错误', () => {
|
|
expect(() => {
|
|
emitStatusEvent('session-1', 'idle');
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('emitLogEvent - 发送日志事件', () => {
|
|
it('发送 info 级别日志', () => {
|
|
expect(() => {
|
|
emitLogEvent('session-1', 'info', 'Processing started');
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('发送 warn 级别日志', () => {
|
|
expect(() => {
|
|
emitLogEvent('session-1', 'warn', 'Rate limit approaching');
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('发送 error 级别日志', () => {
|
|
expect(() => {
|
|
emitLogEvent('session-1', 'error', 'Connection failed');
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('emitProgressEvent - 发送进度事件', () => {
|
|
it('发送进度(带消息)', () => {
|
|
expect(() => {
|
|
emitProgressEvent('session-1', 50, 'Half way done');
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('发送进度(不带消息)', () => {
|
|
expect(() => {
|
|
emitProgressEvent('session-1', 100);
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('发送 0% 进度', () => {
|
|
expect(() => {
|
|
emitProgressEvent('session-1', 0, 'Starting...');
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('emitFileChangeEvent - 发送文件变更事件', () => {
|
|
it('发送文件创建事件', () => {
|
|
expect(() => {
|
|
emitFileChangeEvent('session-1', 'created', '/path/to/new/file.ts');
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('发送文件修改事件', () => {
|
|
expect(() => {
|
|
emitFileChangeEvent('session-1', 'modified', '/path/to/existing/file.ts');
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('发送文件删除事件', () => {
|
|
expect(() => {
|
|
emitFileChangeEvent('session-1', 'deleted', '/path/to/removed/file.ts');
|
|
}).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('getSSEStats - 获取统计信息', () => {
|
|
it('无订阅者时返回 0', () => {
|
|
const stats = getSSEStats();
|
|
// 由于没有实际连接,应该至少有这些属性
|
|
expect(stats).toHaveProperty('sessions');
|
|
expect(stats).toHaveProperty('subscribers');
|
|
expect(typeof stats.sessions).toBe('number');
|
|
expect(typeof stats.subscribers).toBe('number');
|
|
});
|
|
});
|
|
|
|
describe('handleSSE - SSE 路由处理', () => {
|
|
it('会话不存在时返回 404', async () => {
|
|
mockExists.mockReturnValue(false);
|
|
|
|
const app = new Hono();
|
|
app.get('/api/sessions/:id/events', handleSSE);
|
|
|
|
const res = await app.request('/api/sessions/non-existent/events');
|
|
const json = await res.json();
|
|
|
|
expect(res.status).toBe(404);
|
|
expect(json.success).toBe(false);
|
|
expect(json.error).toBe('Session not found');
|
|
});
|
|
|
|
it('会话存在时返回 SSE 流响应', async () => {
|
|
mockExists.mockReturnValue(true);
|
|
|
|
const app = new Hono();
|
|
app.get('/api/sessions/:id/events', handleSSE);
|
|
|
|
const res = await app.request('/api/sessions/valid-session/events');
|
|
|
|
// SSE 流应该返回 200 状态码
|
|
expect(res.status).toBe(200);
|
|
// Content-Type 应该是 text/event-stream
|
|
expect(res.headers.get('content-type')).toContain('text/event-stream');
|
|
});
|
|
});
|
|
});
|