- 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>
177 lines
4.8 KiB
TypeScript
177 lines
4.8 KiB
TypeScript
/**
|
|
* Tests for Heartbeat + Reflection (via intelligenceClient)
|
|
*
|
|
* These tests mock the Tauri backend calls for unit testing.
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import {
|
|
intelligenceClient,
|
|
type HeartbeatConfig,
|
|
type HeartbeatResult,
|
|
} 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 heartbeat commands
|
|
if (cmd === 'heartbeat_init') {
|
|
return true;
|
|
}
|
|
if (cmd === 'heartbeat_start') {
|
|
return true;
|
|
}
|
|
if (cmd === 'heartbeat_stop') {
|
|
return true;
|
|
}
|
|
if (cmd === 'heartbeat_tick') {
|
|
return {
|
|
status: 'ok',
|
|
alerts: [],
|
|
checked_items: 3,
|
|
timestamp: new Date().toISOString(),
|
|
} as HeartbeatResult;
|
|
}
|
|
if (cmd === 'heartbeat_get_status') {
|
|
return {
|
|
running: false,
|
|
last_tick: null,
|
|
next_tick: null,
|
|
config: _args?.config || null,
|
|
};
|
|
}
|
|
// Reflection commands
|
|
if (cmd === 'reflection_reflect') {
|
|
return {
|
|
patterns: [],
|
|
improvements: [],
|
|
identity_proposals: [],
|
|
new_memories: 0,
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
}
|
|
if (cmd === 'reflection_get_history') {
|
|
return [];
|
|
}
|
|
if (cmd === 'reflection_get_state') {
|
|
return {
|
|
conversations_since_reflection: 0,
|
|
last_reflection_time: null,
|
|
last_reflection_agent_id: null,
|
|
};
|
|
}
|
|
return null;
|
|
}),
|
|
}));
|
|
|
|
// =============================================
|
|
// Heartbeat Tests (via intelligenceClient)
|
|
// =============================================
|
|
|
|
describe('Heartbeat (via intelligenceClient)', () => {
|
|
const defaultConfig: HeartbeatConfig = {
|
|
enabled: true,
|
|
interval_minutes: 30,
|
|
quiet_hours_start: null,
|
|
quiet_hours_end: null,
|
|
notify_channel: 'ui',
|
|
proactivity_level: 'standard',
|
|
max_alerts_per_tick: 5,
|
|
};
|
|
|
|
beforeEach(() => {
|
|
localStorageMock.clear();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('init', () => {
|
|
it('initializes heartbeat with config', async () => {
|
|
await expect(
|
|
intelligenceClient.heartbeat.init('test-agent', defaultConfig)
|
|
).resolves.toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('tick', () => {
|
|
it('returns heartbeat result', async () => {
|
|
const result = await intelligenceClient.heartbeat.tick('test-agent');
|
|
|
|
expect(result).toHaveProperty('status');
|
|
expect(result).toHaveProperty('alerts');
|
|
expect(result).toHaveProperty('checked_items');
|
|
expect(result).toHaveProperty('timestamp');
|
|
});
|
|
|
|
it('returns ok status when no issues', async () => {
|
|
const result = await intelligenceClient.heartbeat.tick('test-agent');
|
|
expect(result.status).toBe('ok');
|
|
});
|
|
});
|
|
|
|
describe('start/stop', () => {
|
|
it('starts heartbeat', async () => {
|
|
await expect(
|
|
intelligenceClient.heartbeat.start('test-agent')
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
it('stops heartbeat', async () => {
|
|
await expect(
|
|
intelligenceClient.heartbeat.stop('test-agent')
|
|
).resolves.toBeUndefined();
|
|
});
|
|
});
|
|
});
|
|
|
|
// =============================================
|
|
// Reflection Tests (via intelligenceClient)
|
|
// =============================================
|
|
|
|
describe('Reflection (via intelligenceClient)', () => {
|
|
beforeEach(() => {
|
|
localStorageMock.clear();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('reflect', () => {
|
|
it('returns reflection result', async () => {
|
|
const result = await intelligenceClient.reflection.reflect('test-agent', []);
|
|
|
|
expect(result).toHaveProperty('patterns');
|
|
expect(result).toHaveProperty('improvements');
|
|
expect(result).toHaveProperty('identity_proposals');
|
|
expect(result).toHaveProperty('new_memories');
|
|
expect(result).toHaveProperty('timestamp');
|
|
});
|
|
});
|
|
|
|
describe('getHistory', () => {
|
|
it('returns reflection history', async () => {
|
|
const history = await intelligenceClient.reflection.getHistory();
|
|
expect(Array.isArray(history)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('getState', () => {
|
|
it('returns reflection state', async () => {
|
|
const state = await intelligenceClient.reflection.getState();
|
|
expect(state).toHaveProperty('conversations_since_reflection');
|
|
expect(state).toHaveProperty('last_reflection_time');
|
|
});
|
|
});
|
|
});
|