Files
qiming/qimingclaw/crates/agent-gui-server/tests/safety/auditLog.test.ts

91 lines
2.9 KiB
TypeScript

/**
* Unit tests for safety/auditLog.ts — ring buffer, record, getEntries, clear.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { AuditLog } from '../../src/safety/auditLog.js';
describe('AuditLog', () => {
let log: AuditLog;
beforeEach(() => {
log = new AuditLog();
});
it('starts empty', () => {
expect(log.length).toBe(0);
expect(log.getEntries()).toHaveLength(0);
});
it('records entries with auto-generated timestamp', () => {
log.record({ tool: 'gui_click', args: { x: 100, y: 200 }, success: true });
expect(log.length).toBe(1);
const entries = log.getEntries();
expect(entries).toHaveLength(1);
expect(entries[0].tool).toBe('gui_click');
expect(entries[0].args).toEqual({ x: 100, y: 200 });
expect(entries[0].success).toBe(true);
expect(entries[0].timestamp).toBeDefined();
});
it('returns entries most recent first', () => {
log.record({ tool: 'tool_1', args: {}, success: true });
log.record({ tool: 'tool_2', args: {}, success: true });
log.record({ tool: 'tool_3', args: {}, success: true });
const entries = log.getEntries();
expect(entries[0].tool).toBe('tool_3');
expect(entries[1].tool).toBe('tool_2');
expect(entries[2].tool).toBe('tool_1');
});
it('limits entries by count parameter', () => {
for (let i = 0; i < 10; i++) {
log.record({ tool: `tool_${i}`, args: {}, success: true });
}
const entries = log.getEntries(3);
expect(entries).toHaveLength(3);
expect(entries[0].tool).toBe('tool_9');
expect(entries[1].tool).toBe('tool_8');
expect(entries[2].tool).toBe('tool_7');
});
it('wraps around at 1000 entries (ring buffer)', () => {
for (let i = 0; i < 1050; i++) {
log.record({ tool: `tool_${i}`, args: {}, success: true });
}
// Size should cap at 1000
expect(log.length).toBe(1000);
const entries = log.getEntries(1);
expect(entries[0].tool).toBe('tool_1049');
// Oldest entry should be tool_50 (0-49 were overwritten)
const allEntries = log.getEntries();
expect(allEntries).toHaveLength(1000);
expect(allEntries[allEntries.length - 1].tool).toBe('tool_50');
});
it('clears all entries', () => {
for (let i = 0; i < 5; i++) {
log.record({ tool: `tool_${i}`, args: {}, success: true });
}
expect(log.length).toBe(5);
log.clear();
expect(log.length).toBe(0);
expect(log.getEntries()).toHaveLength(0);
});
it('records durationMs when provided', () => {
log.record({ tool: 'gui_screenshot', args: {}, success: true, durationMs: 150 });
const entries = log.getEntries();
expect(entries[0].durationMs).toBe(150);
});
it('works correctly after clear and re-record', () => {
log.record({ tool: 'before_clear', args: {}, success: true });
log.clear();
log.record({ tool: 'after_clear', args: {}, success: true });
expect(log.length).toBe(1);
expect(log.getEntries()[0].tool).toBe('after_clear');
});
});