Files
Claude-Code-Workflow/ccw/tests/unified-vector-index.test.ts
catlog22 5a4b18d9b1 feat: enhance search, ranking, reranker and CLI tooling across ccw and codex-lens
Major improvements to smart-search, chain-search cascade, ranking pipeline,
reranker factory, CLI history store, codex-lens integration, and uv-manager.
Simplify command-generator skill by inlining phases. Add comprehensive tests.

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

98 lines
3.2 KiB
TypeScript

import { after, beforeEach, describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { EventEmitter } from 'node:events';
import { createRequire } from 'node:module';
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const require = createRequire(import.meta.url);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require('node:fs') as typeof import('node:fs');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const childProcess = require('node:child_process') as typeof import('node:child_process');
class FakeChildProcess extends EventEmitter {
stdout = new EventEmitter();
stderr = new EventEmitter();
stdinChunks: string[] = [];
stdin = {
write: (chunk: string | Buffer) => {
this.stdinChunks.push(String(chunk));
return true;
},
end: () => undefined,
};
}
type SpawnCall = {
command: string;
args: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
options: any;
child: FakeChildProcess;
};
const spawnCalls: SpawnCall[] = [];
const tempDirs: string[] = [];
let embedderAvailable = true;
const originalExistsSync = fs.existsSync;
const originalSpawn = childProcess.spawn;
fs.existsSync = ((..._args: unknown[]) => embedderAvailable) as typeof fs.existsSync;
childProcess.spawn = ((command: string, args: string[] = [], options: unknown = {}) => {
const child = new FakeChildProcess();
spawnCalls.push({ command: String(command), args: args.map(String), options, child });
queueMicrotask(() => {
child.stdout.emit('data', JSON.stringify({
success: true,
total_chunks: 4,
hnsw_available: true,
hnsw_count: 4,
dimension: 384,
}));
child.emit('close', 0);
});
return child as unknown as ReturnType<typeof childProcess.spawn>;
}) as typeof childProcess.spawn;
after(() => {
fs.existsSync = originalExistsSync;
childProcess.spawn = originalSpawn;
while (tempDirs.length > 0) {
rmSync(tempDirs.pop() as string, { recursive: true, force: true });
}
});
describe('unified-vector-index', () => {
beforeEach(() => {
embedderAvailable = true;
spawnCalls.length = 0;
});
it('spawns CodexLens venv python with hidden window options', async () => {
const projectDir = mkdtempSync(join(tmpdir(), 'ccw-unified-vector-index-'));
tempDirs.push(projectDir);
const moduleUrl = new URL('../dist/core/unified-vector-index.js', import.meta.url);
moduleUrl.searchParams.set('t', String(Date.now()));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mod: any = await import(moduleUrl.href);
const index = new mod.UnifiedVectorIndex(projectDir);
const status = await index.getStatus();
assert.equal(status.success, true);
assert.equal(spawnCalls.length, 1);
assert.equal(spawnCalls[0].options.shell, false);
assert.equal(spawnCalls[0].options.windowsHide, true);
assert.equal(spawnCalls[0].options.env.PYTHONIOENCODING, 'utf-8');
assert.deepEqual(spawnCalls[0].options.stdio, ['pipe', 'pipe', 'pipe']);
assert.match(spawnCalls[0].child.stdinChunks.join(''), /"operation":"status"/);
});
});