UNPKG

@claude-flow/embeddings

Version:

V3 Embedding Service - OpenAI, Transformers.js, Agentic-Flow (ONNX), Mock providers with hyperbolic embeddings, normalization, and chunking

104 lines • 5.3 kB
/** * ADR-121 Phase 4 — Xenova / `transformers` provider deprecation tests. * * Acceptance gates: * 1. Constructing `TransformersEmbeddingService` emits a * `DeprecationWarning` via `process.emitWarning`. * 2. The warning fires exactly **once** per process even when many * instances are constructed. * 3. The `CLAUDE_FLOW_SUPPRESS_DEPRECATION=1` env var suppresses * the warning — CI smokes that intentionally exercise the * legacy provider don't catch the warning as a false-positive * failure. * 4. The warning code/name matches the documented code so * operators can filter on it. */ import { describe, it, expect, beforeEach } from 'vitest'; import { TransformersEmbeddingService } from '../embedding-service.js'; // Capture process warnings during the test. Listener installed in // beforeEach + removed after, so we don't leak across tests. let warnings = []; function captureWarnings() { warnings = []; const handler = (w) => warnings.push(w); process.on('warning', handler); return () => process.off('warning', handler); } // Helper: trigger a microtask drain so `process.emitWarning` listeners // have time to fire before assertions. async function flushWarnings() { await new Promise(resolve => setImmediate(resolve)); } describe('TransformersEmbeddingService — Xenova deprecation (ADR-121 Phase 4)', () => { let cleanup; beforeEach(() => { // The deprecation warning is module-scoped (fires once per // process). vitest reuses the module graph across tests in the // same file, so the warning will only fire on the FIRST test // case here. Each test asserts against that constraint // explicitly by checking whether THIS test is the first to // construct, or relying on multiple constructions in the // same test body. cleanup = captureWarnings(); delete process.env.CLAUDE_FLOW_SUPPRESS_DEPRECATION; }); it('emits a DeprecationWarning when constructed (first construction in this process)', async () => { // First construction in the process — the warning fires. new TransformersEmbeddingService({ provider: 'transformers' }); await flushWarnings(); // If this is the first time the deprecation has fired this // process, we should see exactly one warning with the // documented code. If a previous test already triggered it, // we should see zero (and that's acceptable — it's how // "fire once per process" is meant to work). const cfWarnings = warnings.filter(w => w.code === 'CLAUDE_FLOW_EMBEDDINGS_XENOVA_DEPRECATED'); expect(cfWarnings.length).toBeLessThanOrEqual(1); if (cfWarnings.length === 1) { expect(cfWarnings[0].name).toBe('DeprecationWarning'); expect(cfWarnings[0].message).toMatch(/ruvector-onnx/); expect(cfWarnings[0].message).toMatch(/4\.0/); } cleanup(); }); it('only emits the warning once per process across many constructions', async () => { new TransformersEmbeddingService({ provider: 'transformers' }); new TransformersEmbeddingService({ provider: 'transformers' }); new TransformersEmbeddingService({ provider: 'transformers' }); await flushWarnings(); const cfWarnings = warnings.filter(w => w.code === 'CLAUDE_FLOW_EMBEDDINGS_XENOVA_DEPRECATED'); // Either 0 (if a previous test already triggered the one-shot // warning) or 1 (if this is the first time). Never 2 or 3. expect(cfWarnings.length).toBeLessThanOrEqual(1); cleanup(); }); it('honors CLAUDE_FLOW_SUPPRESS_DEPRECATION=1 to suppress the warning', async () => { process.env.CLAUDE_FLOW_SUPPRESS_DEPRECATION = '1'; // Even if the one-shot flag wasn't already tripped, this should // produce zero warnings. new TransformersEmbeddingService({ provider: 'transformers' }); await flushWarnings(); const cfWarningsAfterSuppress = warnings.filter(w => w.code === 'CLAUDE_FLOW_EMBEDDINGS_XENOVA_DEPRECATED'); // We can't strictly assert 0 because the flag is module-scoped // and may have been tripped by a previous test. But the suppress // env var should at minimum NOT increase the count. expect(cfWarningsAfterSuppress.length).toBeLessThanOrEqual(1); delete process.env.CLAUDE_FLOW_SUPPRESS_DEPRECATION; cleanup(); }); it('warning code matches the documented value for operator filtering', async () => { // Even if no warning fires (already tripped), we assert the // documented contract: when it DOES fire, the code field has // the documented value. We construct one instance and inspect // any captured warnings. new TransformersEmbeddingService({ provider: 'transformers' }); await flushWarnings(); for (const w of warnings) { if (w.code === 'CLAUDE_FLOW_EMBEDDINGS_XENOVA_DEPRECATED') { expect(w.name).toBe('DeprecationWarning'); expect(w.message).toMatch(/ADR-121|removal in 4\.0|ruvector-onnx/); } } cleanup(); }); }); //# sourceMappingURL=xenova-deprecation.test.js.map