2025-12-17 17:42:37 -08:00
/ * *
* WASM Embedding Integration Test
*
2026-01-06 12:52:34 -08:00
* Tests the Candle WASM embedding engine with real model inference .
* NO mocks - this loads the real embedded model and generates real embeddings .
2025-12-17 17:42:37 -08:00
* /
import { describe , it , expect , beforeAll } from 'vitest'
import { WASMEmbeddingEngine } from '../../src/embeddings/wasm/WASMEmbeddingEngine.js'
import { embeddingManager } from '../../src/embeddings/EmbeddingManager.js'
// Ensure we're NOT in mock mode for these tests
beforeAll ( ( ) = > {
delete process . env . BRAINY_UNIT_TEST
; ( globalThis as any ) . __BRAINY_UNIT_TEST__ = false
} )
describe ( 'WASM Embedding Engine - Real Embeddings' , ( ) = > {
it ( 'should initialize the WASM engine' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
await engine . initialize ( )
expect ( engine . isInitialized ( ) ) . toBe ( true )
} )
it ( 'should generate 384-dimensional embeddings' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const embedding = await engine . embed ( 'Hello world' )
expect ( embedding ) . toBeInstanceOf ( Array )
expect ( embedding . length ) . toBe ( 384 )
expect ( typeof embedding [ 0 ] ) . toBe ( 'number' )
} )
it ( 'should produce consistent embeddings for same input' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const emb1 = await engine . embed ( 'test consistency' )
const emb2 = await engine . embed ( 'test consistency' )
expect ( emb1 ) . toEqual ( emb2 )
} )
it ( 'should produce normalized embeddings (unit length)' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const embedding = await engine . embed ( 'normalize test' )
// Calculate L2 norm
const norm = Math . sqrt ( embedding . reduce ( ( sum , v ) = > sum + v * v , 0 ) )
// Should be approximately 1.0 (normalized)
expect ( norm ) . toBeCloseTo ( 1.0 , 4 )
} )
it ( 'should produce semantically meaningful embeddings' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
// Similar sentences
const catEmb = await engine . embed ( 'The cat sat on the mat' )
const felineEmb = await engine . embed ( 'A feline rests on a rug' )
// Dissimilar sentence
const stockEmb = await engine . embed ( 'The stock market crashed today' )
// Cosine similarity function
const cosineSim = ( a : number [ ] , b : number [ ] ) = > {
let dot = 0 , normA = 0 , normB = 0
for ( let i = 0 ; i < a . length ; i ++ ) {
dot += a [ i ] * b [ i ]
normA += a [ i ] * a [ i ]
normB += b [ i ] * b [ i ]
}
return dot / ( Math . sqrt ( normA ) * Math . sqrt ( normB ) )
}
const similarSim = cosineSim ( catEmb , felineEmb )
const dissimilarSim = cosineSim ( catEmb , stockEmb )
// Similar sentences should have higher similarity than dissimilar
expect ( similarSim ) . toBeGreaterThan ( dissimilarSim )
expect ( similarSim ) . toBeGreaterThan ( 0.4 ) // Reasonably similar
expect ( dissimilarSim ) . toBeLessThan ( 0.3 ) // Not very similar
} )
it ( 'should handle empty string' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const embedding = await engine . embed ( '' )
expect ( embedding . length ) . toBe ( 384 )
} )
it ( 'should handle long text' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const longText = 'word ' . repeat ( 1000 )
const embedding = await engine . embed ( longText )
expect ( embedding . length ) . toBe ( 384 )
} )
it ( 'should work through EmbeddingManager' , async ( ) = > {
await embeddingManager . init ( )
const embedding = await embeddingManager . embed ( 'test via manager' )
expect ( embedding . length ) . toBe ( 384 )
expect ( embeddingManager . isInitialized ( ) ) . toBe ( true )
} )
it ( 'should report correct stats' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const stats = engine . getStats ( )
expect ( stats . initialized ) . toBe ( true )
expect ( stats . modelName ) . toBe ( 'all-MiniLM-L6-v2' )
expect ( stats . embedCount ) . toBeGreaterThan ( 0 )
} )
} )
describe ( 'WASM Embedding - Batch Operations' , ( ) = > {
it ( 'should embed multiple texts' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const texts = [
'First document about cats' ,
'Second document about dogs' ,
'Third document about birds'
]
const embeddings = await engine . embedBatch ( texts )
expect ( embeddings . length ) . toBe ( 3 )
expect ( embeddings [ 0 ] . length ) . toBe ( 384 )
expect ( embeddings [ 1 ] . length ) . toBe ( 384 )
expect ( embeddings [ 2 ] . length ) . toBe ( 384 )
} )
it ( 'should handle empty batch' , async ( ) = > {
const engine = WASMEmbeddingEngine . getInstance ( )
const embeddings = await engine . embedBatch ( [ ] )
expect ( embeddings ) . toEqual ( [ ] )
} )
} )