@claude-flow/embeddings
Version:
V3 Embedding Service - OpenAI, Transformers.js, Agentic-Flow (ONNX), Mock providers with hyperbolic embeddings, normalization, and chunking
75 lines (68 loc) • 2.81 kB
text/typescript
/**
* ADR-121 Phase 5 (lightweight) — ruvector sidecar probe tests.
*
* Fast tests (no real shellout to ruvector in the default path) —
* we exercise the parser + the missing-CLI graceful degradation
* path by pointing the probe at a binary name that definitely
* doesn't exist.
*
* The "real CLI" path (asserting the probe handles an actual
* `ruvector --version` shellout) is exercised in the CI smoke
* which runs ruvector when installed.
*/
import { describe, it, expect } from 'vitest';
import {
probeRuvectorSidecar,
formatRuvectorAvailability,
} from '../ruvector-mcp-probe.js';
describe('probeRuvectorSidecar — graceful degradation', () => {
it('returns available:false with a reason when the CLI is missing', async () => {
// Use a name that definitely isn't on the PATH.
const r = await probeRuvectorSidecar({ binary: 'ruvector-does-not-exist-xyz-9876', timeoutMs: 2_000 });
expect(r.available).toBe(false);
expect(typeof r.reason).toBe('string');
expect(r.reason).toMatch(/did not return cleanly|not installed/i);
expect(r.probeMs).toBeGreaterThanOrEqual(0);
expect(r.tools).toBeUndefined();
});
it('never throws, even with a binary that produces spawn errors', async () => {
// Empty-string binary should fail at spawn — the probe must
// catch that and return a friendly report, not throw.
await expect(probeRuvectorSidecar({ binary: '', timeoutMs: 1_000 })).resolves.toMatchObject({
available: false,
});
});
it('formatRuvectorAvailability produces a single-line table-ready string', () => {
const r = formatRuvectorAvailability({
available: true,
version: '0.2.13',
binary: '/usr/local/bin/ruvector',
tools: [{ group: 'hooks-core', name: 'x', params: '', description: '' }],
toolCount: 1,
groups: { 'hooks-core': 1 },
probeMs: 42,
});
expect(r).toMatch(/^ruvector: 0\.2\.13/);
expect(r).toMatch(/hooks-core=1/);
expect(r).not.toContain('\n');
});
it('formatRuvectorAvailability handles unavailable state', () => {
const r = formatRuvectorAvailability({
available: false,
reason: 'CLI not on PATH',
probeMs: 17,
});
expect(r).toMatch(/^ruvector: not available/);
expect(r).toMatch(/CLI not on PATH/);
});
});
describe('parseMcpTools — output-shape robustness', () => {
// We can't import the parser directly (it's not exported), but
// we can drive the probe with a binary that prints a fixture
// matching the documented shape. Easier: cover the cases where
// the parser is forgiving via the public surface in CI.
// (Tested end-to-end in the smoke when ruvector is installed.)
it('placeholder — full parser coverage is in the CI smoke', () => {
expect(true).toBe(true);
});
});