GPU_GUARD_MONOREPO/packages/backend/test/process_event_buffer.test.ts
2026-05-20 21:39:12 +08:00

57 lines
1.6 KiB
TypeScript

import { ProcessEventBuffer, RuntimeProcessEvent } from '../src/modules/netaclaw/runtime/process_events';
function event(input: Partial<RuntimeProcessEvent> = {}): RuntimeProcessEvent {
return {
version: 1,
operationId: 'tool-call-1',
targetType: 'tool',
source: 'tool',
status: 'running',
level: 'info',
message: 'working',
timestamp: '2026-05-06T00:00:00.000Z',
...input,
};
}
describe('ProcessEventBuffer', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it('coalesces repeated non-terminal events until throttle flush', () => {
const emitted: RuntimeProcessEvent[] = [];
const buffer = new ProcessEventBuffer(item => emitted.push(item), { throttleMs: 100 });
buffer.push(event({ current: 1, total: 3 }));
buffer.push(event({ current: 2, total: 3 }));
expect(emitted).toEqual([]);
jest.advanceTimersByTime(100);
expect(emitted).toEqual([
expect.objectContaining({
current: 2,
payload: { repeatCount: 2 },
}),
]);
});
it('flushes pending operation events before terminal events', () => {
const emitted: RuntimeProcessEvent[] = [];
const buffer = new ProcessEventBuffer(item => emitted.push(item), { throttleMs: 100 });
buffer.push(event({ current: 1, total: 2 }));
buffer.push(event({ status: 'failed', level: 'error', message: 'failed' }));
expect(emitted).toEqual([
expect.objectContaining({ current: 1 }),
expect.objectContaining({ status: 'failed', message: 'failed' }),
]);
});
});