edeed2ee2c
- Deleted hook-prompt-renderer.js and hook-prompts.config.js as they are no longer needed. - Removed path-resolver.js, stop.js, and user-prompt-submit.js for streamlining the codebase. - Updated package.json scripts to point to new build and publish scripts. - Adjusted test imports to reflect new directory structure after removing unnecessary files.
254 lines
7.9 KiB
TypeScript
254 lines
7.9 KiB
TypeScript
#!/usr/bin/env bun
|
|
/**
|
|
* Phase 3 Integration Tests
|
|
* Tests the complete hook lifecycle and end-to-end integration
|
|
*
|
|
* Note: These tests verify database integration rather than calling hooks directly
|
|
* since hooks call process.exit() which would terminate the test process
|
|
*/
|
|
|
|
import { describe, it, expect, beforeAll, afterAll } from 'bun:test';
|
|
import { HooksDatabase } from '../src/services/sqlite/HooksDatabase.js';
|
|
import { DatabaseManager } from '../src/services/sqlite/Database.js';
|
|
import { migrations } from '../src/services/sqlite/migrations.js';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
// Test database path
|
|
const TEST_DB_DIR = '/tmp/claude-mem-phase3-test';
|
|
const TEST_DB_PATH = path.join(TEST_DB_DIR, 'claude-mem.db');
|
|
|
|
describe('Phase 3: Hook Database Integration', () => {
|
|
beforeAll(async () => {
|
|
// Create test directory
|
|
fs.mkdirSync(TEST_DB_DIR, { recursive: true });
|
|
|
|
// Set test environment
|
|
process.env.CLAUDE_MEM_DATA_DIR = TEST_DB_DIR;
|
|
|
|
// Initialize database with migrations
|
|
const dbManager = DatabaseManager.getInstance();
|
|
migrations.forEach(m => dbManager.registerMigration(m));
|
|
await dbManager.initialize();
|
|
dbManager.close();
|
|
});
|
|
|
|
afterAll(() => {
|
|
// Clean up test database and all files
|
|
if (fs.existsSync(TEST_DB_DIR)) {
|
|
const files = fs.readdirSync(TEST_DB_DIR);
|
|
files.forEach(file => {
|
|
fs.unlinkSync(path.join(TEST_DB_DIR, file));
|
|
});
|
|
fs.rmdirSync(TEST_DB_DIR);
|
|
}
|
|
});
|
|
|
|
describe('HooksDatabase - Session Management', () => {
|
|
it('should create and find SDK sessions', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
const sessionId = db.createSDKSession(
|
|
'test-claude-session-1',
|
|
'my-project',
|
|
'Implement authentication'
|
|
);
|
|
|
|
expect(sessionId).toBeGreaterThan(0);
|
|
|
|
const found = db.findActiveSDKSession('test-claude-session-1');
|
|
expect(found).not.toBeNull();
|
|
expect(found!.project).toBe('my-project');
|
|
expect(found!.id).toBe(sessionId);
|
|
|
|
db.close();
|
|
});
|
|
|
|
it('should update SDK session ID', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
const sessionId = db.createSDKSession(
|
|
'test-claude-session-2',
|
|
'my-project',
|
|
'Test prompt'
|
|
);
|
|
|
|
db.updateSDKSessionId(sessionId, 'sdk-session-abc');
|
|
|
|
const found = db.findActiveSDKSession('test-claude-session-2');
|
|
expect(found!.sdk_session_id).toBe('sdk-session-abc');
|
|
|
|
db.close();
|
|
});
|
|
|
|
it('should mark session as completed', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
const sessionId = db.createSDKSession(
|
|
'test-claude-session-3',
|
|
'my-project',
|
|
'Test prompt'
|
|
);
|
|
|
|
db.markSessionCompleted(sessionId);
|
|
|
|
const found = db.findActiveSDKSession('test-claude-session-3');
|
|
expect(found).toBeNull(); // Should not find active session
|
|
|
|
db.close();
|
|
});
|
|
});
|
|
|
|
describe('HooksDatabase - Observation Queue', () => {
|
|
it('should queue and retrieve observations', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
// Create session first (FK constraint requirement)
|
|
const sessionId = db.createSDKSession('claude-queue-1', 'test-project', 'Test');
|
|
db.updateSDKSessionId(sessionId, 'sdk-queue-test-1');
|
|
|
|
db.queueObservation(
|
|
'sdk-queue-test-1',
|
|
'Read',
|
|
JSON.stringify({ file_path: 'src/app.ts' }),
|
|
JSON.stringify({ content: 'test content' })
|
|
);
|
|
|
|
const pending = db.getPendingObservations('sdk-queue-test-1', 10);
|
|
expect(pending).toHaveLength(1);
|
|
expect(pending[0].tool_name).toBe('Read');
|
|
|
|
db.close();
|
|
});
|
|
|
|
it('should mark observations as processed', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
// Create session first (FK constraint requirement)
|
|
const sessionId = db.createSDKSession('claude-queue-2', 'test-project', 'Test');
|
|
db.updateSDKSessionId(sessionId, 'sdk-queue-test-2');
|
|
|
|
db.queueObservation(
|
|
'sdk-queue-test-2',
|
|
'Edit',
|
|
JSON.stringify({ file_path: 'src/app.ts' }),
|
|
JSON.stringify({ success: true })
|
|
);
|
|
|
|
const pending = db.getPendingObservations('sdk-queue-test-2', 10);
|
|
expect(pending).toHaveLength(1);
|
|
|
|
db.markObservationProcessed(pending[0].id);
|
|
|
|
const stillPending = db.getPendingObservations('sdk-queue-test-2', 10);
|
|
expect(stillPending).toHaveLength(0);
|
|
|
|
db.close();
|
|
});
|
|
|
|
it('should queue FINALIZE messages', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
// Create session first (FK constraint requirement)
|
|
const sessionId = db.createSDKSession('claude-finalize', 'test-project', 'Test');
|
|
db.updateSDKSessionId(sessionId, 'sdk-finalize-test');
|
|
|
|
db.queueObservation('sdk-finalize-test', 'FINALIZE', '{}', '{}');
|
|
|
|
const pending = db.getPendingObservations('sdk-finalize-test', 10);
|
|
expect(pending).toHaveLength(1);
|
|
expect(pending[0].tool_name).toBe('FINALIZE');
|
|
|
|
db.close();
|
|
});
|
|
});
|
|
|
|
describe('HooksDatabase - Observations Storage', () => {
|
|
it('should store observations from SDK', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
// Create session first (FK constraint requirement)
|
|
const sessionId = db.createSDKSession('claude-obs-1', 'my-project', 'Test');
|
|
db.updateSDKSessionId(sessionId, 'sdk-obs-test-1');
|
|
|
|
db.storeObservation(
|
|
'sdk-obs-test-1',
|
|
'my-project',
|
|
'feature',
|
|
'Implemented JWT authentication'
|
|
);
|
|
|
|
const dbInstance = (db as any).db;
|
|
const query = dbInstance.query('SELECT * FROM observations WHERE sdk_session_id = ?');
|
|
const observations = query.all('sdk-obs-test-1');
|
|
|
|
expect(observations).toHaveLength(1);
|
|
expect(observations[0].type).toBe('feature');
|
|
expect(observations[0].text).toBe('Implemented JWT authentication');
|
|
|
|
db.close();
|
|
});
|
|
});
|
|
|
|
describe('HooksDatabase - Summaries', () => {
|
|
it('should store and retrieve summaries', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
// Create session first (FK constraint requirement)
|
|
const sessionId = db.createSDKSession('claude-summary-1', 'my-project', 'Test');
|
|
db.updateSDKSessionId(sessionId, 'sdk-summary-test-1');
|
|
|
|
db.storeSummary('sdk-summary-test-1', 'my-project', {
|
|
request: 'Implement authentication',
|
|
investigated: 'Existing patterns',
|
|
learned: 'No JWT support',
|
|
completed: 'Implemented JWT',
|
|
next_steps: 'Add tests',
|
|
files_read: JSON.stringify(['src/auth.ts']),
|
|
files_edited: JSON.stringify(['src/auth.ts']),
|
|
notes: 'Used bcrypt'
|
|
});
|
|
|
|
const summaries = db.getRecentSummaries('my-project', 10);
|
|
expect(summaries.length).toBeGreaterThan(0);
|
|
|
|
const summary = summaries.find(s => s.request === 'Implement authentication');
|
|
expect(summary).not.toBeUndefined();
|
|
expect(summary!.completed).toBe('Implemented JWT');
|
|
|
|
db.close();
|
|
});
|
|
|
|
it('should return recent summaries only for specific project', () => {
|
|
const db = new HooksDatabase();
|
|
|
|
// Create sessions first (FK constraint requirement)
|
|
const session1Id = db.createSDKSession('claude-proj-1', 'project-1', 'Test');
|
|
db.updateSDKSessionId(session1Id, 'sdk-proj1');
|
|
|
|
const session2Id = db.createSDKSession('claude-proj-2', 'project-2', 'Test');
|
|
db.updateSDKSessionId(session2Id, 'sdk-proj2');
|
|
|
|
db.storeSummary('sdk-proj1', 'project-1', {
|
|
request: 'Feature for project 1',
|
|
completed: 'Done'
|
|
});
|
|
|
|
db.storeSummary('sdk-proj2', 'project-2', {
|
|
request: 'Feature for project 2',
|
|
completed: 'Done'
|
|
});
|
|
|
|
const proj1Summaries = db.getRecentSummaries('project-1', 10);
|
|
const proj2Summaries = db.getRecentSummaries('project-2', 10);
|
|
|
|
expect(proj1Summaries.every(s => s.request?.includes('project 1'))).toBe(true);
|
|
expect(proj2Summaries.every(s => s.request?.includes('project 2'))).toBe(true);
|
|
|
|
db.close();
|
|
});
|
|
});
|
|
});
|
|
|
|
console.log('Running Phase 3 Integration Tests...');
|