test(web): 补充流式断连的对抗性测试(stream_end 幂等性 + 多周期循环)
对抗性审查 commit 30b7d90 的修复健壮性,新增两个边缘场景测试: - 用例 18: 验证断连后 stream_end 到达是幂等的(不崩溃、不改变 已 flush 内容),且后续 assistant_response 能正常按 id 替换 - 用例 19: 验证多次断连-重连循环下 finishStreaming 幂等 (连续调用不崩溃,消息状态稳定)
This commit is contained in:
parent
c749df4e0a
commit
934c7aa804
@ -523,4 +523,56 @@ describe('useChat - handleServerMessage characterization', () => {
|
|||||||
const s1 = result.current.messages.find((m) => m.id === 's1');
|
const s1 = result.current.messages.find((m) => m.id === 's1');
|
||||||
expect(s1?.content).toBe('part1part2');
|
expect(s1?.content).toBe('part1part2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('18. stream_end arriving after onDisconnect is idempotent (no crash, no side effect)', () => {
|
||||||
|
const { result } = renderUseChat();
|
||||||
|
act(() => {
|
||||||
|
result.current.handleServerMessage({ type: 'stream_delta', id: 'e1', delta: 'partial' });
|
||||||
|
});
|
||||||
|
expect(result.current.messages[0].content).toBe('partial');
|
||||||
|
|
||||||
|
// 断连:finishStreaming 重置 streamingRef
|
||||||
|
act(() => result.current.finishStreaming());
|
||||||
|
|
||||||
|
// 重连后 stream_end 到达(可能在断连前已发出,重连后才收到)
|
||||||
|
expect(() => {
|
||||||
|
act(() => result.current.handleServerMessage({ type: 'stream_end', id: 'e1' }));
|
||||||
|
}).not.toThrow();
|
||||||
|
// stream_end 不应改变已 flush 的内容
|
||||||
|
const e1 = result.current.messages.find((m) => m.id === 'e1');
|
||||||
|
expect(e1?.content).toBe('partial');
|
||||||
|
|
||||||
|
// 紧接着 assistant_response 到达,应正常按 id 替换(断连后的正常恢复路径)
|
||||||
|
act(() =>
|
||||||
|
result.current.handleServerMessage({
|
||||||
|
type: 'assistant_response',
|
||||||
|
id: 'e1',
|
||||||
|
content: 'final',
|
||||||
|
role: 'assistant',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(result.current.messages.find((m) => m.id === 'e1')?.content).toBe('final');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('19. multiple disconnect-reconnect cycles: finishStreaming is idempotent across cycles', () => {
|
||||||
|
const { result } = renderUseChat();
|
||||||
|
|
||||||
|
// 周期 1
|
||||||
|
act(() => result.current.handleServerMessage({ type: 'stream_delta', id: 'c1', delta: 'a' }));
|
||||||
|
act(() => result.current.finishStreaming());
|
||||||
|
expect(result.current.messages.find((m) => m.id === 'c1')?.content).toBe('a');
|
||||||
|
|
||||||
|
// 周期 2:新流式消息
|
||||||
|
act(() => result.current.handleServerMessage({ type: 'stream_delta', id: 'c2', delta: 'b' }));
|
||||||
|
act(() => result.current.finishStreaming());
|
||||||
|
expect(result.current.messages.find((m) => m.id === 'c2')?.content).toBe('b');
|
||||||
|
// c1 不受影响
|
||||||
|
expect(result.current.messages.find((m) => m.id === 'c1')?.content).toBe('a');
|
||||||
|
|
||||||
|
// 周期 3:连续两次 finishStreaming(无 delta 间隔),验证幂等
|
||||||
|
act(() => result.current.finishStreaming());
|
||||||
|
act(() => result.current.finishStreaming());
|
||||||
|
// 不崩溃,消息状态稳定
|
||||||
|
expect(result.current.messages).toHaveLength(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user