/** * OpenFang 协议兼容性测试 * * 验证 ZCLAW 前端与 OpenFang 后端的协议兼容性。 */ import { test, expect } from '@playwright/test'; import { openFangResponses, streamEvents, gatewayFrames } from '../fixtures/openfang-responses'; const BASE_URL = 'http://localhost:1420'; test.describe('OpenFang 协议兼容性测试', () => { test.describe('PROTO-01: 流事件类型解析', () => { test('应正确解析 text_delta 事件', () => { const event = streamEvents.textDelta('Hello World'); expect(event.type).toBe('text_delta'); expect(event.content).toBe('Hello World'); }); test('应正确解析 phase 事件', () => { const doneEvent = streamEvents.phaseDone; expect(doneEvent.type).toBe('phase'); expect(doneEvent.phase).toBe('done'); }); test('应正确解析 tool_call 和 tool_result 事件', () => { const toolCall = streamEvents.toolCall('search', { query: 'test' }); expect(toolCall.type).toBe('tool_call'); expect(toolCall.tool).toBe('search'); const toolResult = streamEvents.toolResult('search', { results: [] }); expect(toolResult.type).toBe('tool_result'); }); test('应正确解析 hand 事件', () => { const handEvent = streamEvents.hand('Browser', 'completed', { pages: 5 }); expect(handEvent.type).toBe('hand'); expect(handEvent.hand_name).toBe('Browser'); expect(handEvent.hand_status).toBe('completed'); }); test('应正确解析 error 事件', () => { const errorEvent = streamEvents.error('TIMEOUT', 'Request timed out'); expect(errorEvent.type).toBe('error'); expect(errorEvent.code).toBe('TIMEOUT'); }); }); test.describe('PROTO-02: Gateway 帧格式兼容', () => { test('应正确构造请求帧', () => { const frame = gatewayFrames.request(1, 'chat', { message: 'Hello' }); expect(frame.type).toBe('req'); expect(frame.id).toBe(1); expect(frame.method).toBe('chat'); }); test('应正确构造响应帧', () => { const frame = gatewayFrames.response(1, { status: 'ok' }); expect(frame.type).toBe('res'); expect(frame.id).toBe(1); }); test('应正确构造事件帧', () => { const frame = gatewayFrames.event({ type: 'text_delta', content: 'test' }); expect(frame.type).toBe('event'); }); test('应正确构造 pong 帧', () => { const frame = gatewayFrames.pong(1); expect(frame.type).toBe('pong'); expect(frame.id).toBe(1); }); }); test.describe('PROTO-03: 连接状态管理', () => { const validStates = ['disconnected', 'connecting', 'handshaking', 'connected', 'reconnecting']; test('连接状态应为有效值', () => { validStates.forEach(state => { expect(['disconnected', 'connecting', 'handshaking', 'connected', 'reconnecting']).toContain(state); }); }); }); test.describe('PROTO-04: 心跳机制', () => { test('心跳帧格式正确', () => { const pingFrame = { type: 'ping' }; expect(pingFrame.type).toBe('ping'); }); test('pong 响应格式正确', () => { const pongFrame = gatewayFrames.pong(1); expect(pongFrame.type).toBe('pong'); }); }); test.describe('PROTO-05: 设备认证流程', () => { test('设备认证响应格式', () => { const authResponse = { status: 'authenticated', device_id: 'device-001', token: 'jwt-token-here', }; expect(authResponse.status).toBe('authenticated'); expect(authResponse.device_id).toBeDefined(); }); }); });