import { test, expect } from '@playwright/test' import { validateEmbedding, calculateL2Norm, normalizeEmbedding } from '../../lib/utils' test.describe('Embedding Validation', () => { test.describe('validateEmbedding()', () => { test('should validate a normal embedding', () => { const embedding = [0.1, 0.2, 0.3, 0.4, 0.5] const result = validateEmbedding(embedding) expect(result.valid).toBe(true) expect(result.issues).toHaveLength(0) }) test('should reject empty embedding', () => { const result = validateEmbedding([]) expect(result.valid).toBe(false) expect(result.issues).toContain('Embedding is empty or has zero dimensionality') }) test('should reject null embedding', () => { const result = validateEmbedding(null as any) expect(result.valid).toBe(false) expect(result.issues).toContain('Embedding is empty or has zero dimensionality') }) test('should reject embedding with NaN values', () => { const embedding = [0.1, NaN, 0.3, 0.4, 0.5] const result = validateEmbedding(embedding) expect(result.valid).toBe(false) expect(result.issues).toContain('Embedding contains NaN values') }) test('should reject embedding with Infinity values', () => { const embedding = [0.1, 0.2, Infinity, 0.4, 0.5] const result = validateEmbedding(embedding) expect(result.valid).toBe(false) expect(result.issues).toContain('Embedding contains Infinity values') }) test('should reject zero vector', () => { const embedding = [0, 0, 0, 0, 0] const result = validateEmbedding(embedding) expect(result.valid).toBe(false) expect(result.issues).toContain('Embedding is a zero vector (all values are 0)') }) test('should warn about L2 norm outside normal range', () => { // Very small norm const smallEmbedding = [0.01, 0.01, 0.01] const result1 = validateEmbedding(smallEmbedding) expect(result1.valid).toBe(false) expect(result1.issues.some(issue => issue.includes('L2 norm'))).toBe(true) // Very large norm const largeEmbedding = [2, 2, 2] const result2 = validateEmbedding(largeEmbedding) expect(result2.valid).toBe(false) expect(result2.issues.some(issue => issue.includes('L2 norm'))).toBe(true) }) test('should detect multiple issues', () => { const embedding = [NaN, Infinity, 0] const result = validateEmbedding(embedding) expect(result.valid).toBe(false) expect(result.issues.length).toBeGreaterThan(1) expect(result.issues).toContain('Embedding contains NaN values') expect(result.issues).toContain('Embedding contains Infinity values') // Note: NaN and Infinity are not zero, so it won't detect zero vector }) }) test.describe('calculateL2Norm()', () => { test('should calculate correct L2 norm', () => { const vector = [3, 4] const norm = calculateL2Norm(vector) expect(norm).toBe(5) // sqrt(3^2 + 4^2) = 5 }) test('should return 0 for zero vector', () => { const vector = [0, 0, 0] const norm = calculateL2Norm(vector) expect(norm).toBe(0) }) test('should handle negative values', () => { const vector = [-3, -4] const norm = calculateL2Norm(vector) expect(norm).toBe(5) // sqrt((-3)^2 + (-4)^2) = 5 }) }) test.describe('normalizeEmbedding()', () => { test('should normalize a vector to unit L2 norm', () => { const embedding = [3, 4] const normalized = normalizeEmbedding(embedding) const norm = calculateL2Norm(normalized) expect(norm).toBeCloseTo(1.0, 5) }) test('should preserve direction of vector', () => { const embedding = [1, 2, 3] const normalized = normalizeEmbedding(embedding) // Check that ratios are preserved expect(normalized[1] / normalized[0]).toBeCloseTo(embedding[1] / embedding[0], 5) expect(normalized[2] / normalized[1]).toBeCloseTo(embedding[2] / embedding[1], 5) }) test('should return zero vector unchanged', () => { const embedding = [0, 0, 0] const normalized = normalizeEmbedding(embedding) expect(normalized).toEqual(embedding) }) test('should handle already normalized vectors', () => { const embedding = [0.707, 0.707] // Already approximately unit norm const normalized = normalizeEmbedding(embedding) const norm = calculateL2Norm(normalized) expect(norm).toBeCloseTo(1.0, 5) }) }) })