Files
zclaw_openfang/tests/desktop/context-compactor.test.ts
iven 1900abe152 test(intelligence): update tests to use intelligenceClient
- Rewrite context-compactor.test.ts to use intelligenceClient
- Rewrite heartbeat-reflection.test.ts to use intelligenceClient
- Rewrite swarm-skills.test.ts to use intelligenceClient
- Update CLAUDE.md architecture section for unified intelligence layer

All tests now mock Tauri backend calls for unit testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 15:26:35 +08:00

126 lines
3.9 KiB
TypeScript

/**
* Tests for Context Compactor (Phase 2)
*
* Covers: token estimation, threshold checking, memory flush, compaction
*
* Now uses intelligenceClient which delegates to Rust backend.
* These tests mock the backend calls for unit testing.
*/
import { describe, it, expect, beforeEach, vi } from 'vitest';
import {
intelligenceClient,
type CompactableMessage,
} from '../../desktop/src/lib/intelligence-client';
// === Mock localStorage ===
const localStorageMock = (() => {
let store: Record<string, string> = {};
return {
getItem: (key: string) => store[key] ?? null,
setItem: (key: string, value: string) => { store[key] = value; },
removeItem: (key: string) => { delete store[key]; },
clear: () => { store = {}; },
};
})();
vi.stubGlobal('localStorage', localStorageMock);
// === Mock Tauri invoke ===
vi.mock('@tauri-apps/api/core', () => ({
invoke: vi.fn(async (cmd: string, _args?: unknown) => {
// Mock responses for compactor commands
if (cmd === 'compactor_check_threshold') {
return {
should_compact: false,
current_tokens: 100,
threshold: 15000,
urgency: 'none',
};
}
if (cmd === 'compactor_compact') {
return {
compacted_messages: _args?.messages?.slice(-4) || [],
summary: '压缩摘要:讨论了技术方案',
original_count: _args?.messages?.length || 0,
retained_count: 4,
flushed_memories: 0,
tokens_before_compaction: 1000,
tokens_after_compaction: 200,
};
}
return null;
}),
}));
// === Helpers ===
function makeMessages(count: number, contentLength: number = 100): CompactableMessage[] {
const msgs: CompactableMessage[] = [];
for (let i = 0; i < count; i++) {
msgs.push({
role: i % 2 === 0 ? 'user' : 'assistant',
content: '测试消息内容'.repeat(Math.ceil(contentLength / 6)).slice(0, contentLength),
id: `msg_${i}`,
timestamp: new Date(Date.now() - (count - i) * 60000).toISOString(),
});
}
return msgs;
}
// =============================================
// ContextCompactor Tests (via intelligenceClient)
// =============================================
describe('ContextCompactor (via intelligenceClient)', () => {
beforeEach(() => {
localStorageMock.clear();
vi.clearAllMocks();
});
describe('checkThreshold', () => {
it('returns check result with expected structure', async () => {
const msgs = makeMessages(4);
const check = await intelligenceClient.compactor.checkThreshold(msgs);
expect(check).toHaveProperty('should_compact');
expect(check).toHaveProperty('current_tokens');
expect(check).toHaveProperty('threshold');
expect(check).toHaveProperty('urgency');
});
it('returns none urgency for small conversations', async () => {
const msgs = makeMessages(4);
const check = await intelligenceClient.compactor.checkThreshold(msgs);
expect(check.urgency).toBe('none');
});
});
describe('compact', () => {
it('returns compaction result with expected structure', async () => {
const msgs = makeMessages(20);
const result = await intelligenceClient.compactor.compact(msgs, 'agent-1');
expect(result).toHaveProperty('compacted_messages');
expect(result).toHaveProperty('summary');
expect(result).toHaveProperty('original_count');
expect(result).toHaveProperty('retained_count');
});
it('generates a summary', async () => {
const msgs = makeMessages(20);
const result = await intelligenceClient.compactor.compact(msgs, 'agent-1');
expect(result.summary).toBeDefined();
expect(result.summary.length).toBeGreaterThan(0);
});
it('handles empty message list', async () => {
const result = await intelligenceClient.compactor.compact([], 'agent-1');
expect(result).toHaveProperty('retained_count');
});
});
});